• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import ts from 'typescript';
17import path from "path";
18
19import { Comment } from './Comment';
20import { DecoratorInfo } from './Decorator';
21import { JsDocProcessorHelper } from '../../coreImpl/parser/JsDocProcessor';
22
23export enum ApiType {
24  SOURCE_FILE = 'SourceFile',
25  REFERENCE_FILE = 'Reference',
26  PROPERTY = 'Property',
27  CLASS = 'Class',
28  INTERFACE = 'Interface',
29  NAMESPACE = 'Namespace',
30  METHOD = 'Method',
31  MODULE = 'Module',
32  EXPORT = 'Export',
33  EXPORT_DEFAULT = 'ExportDefault',
34  CONSTANT = 'Constant',
35  IMPORT = 'Import',
36  DECLARE_CONST = 'DeclareConst',
37  ENUM_VALUE = 'EnumValue',
38  TYPE_ALIAS = 'TypeAlias',
39  PARAM = 'Param',
40  ENUM = 'Enum',
41  STRUCT = 'Struct',
42}
43
44export enum TypeAliasType {
45  UNION_TYPE = 'UnionType',
46  OBJECT_TYPE = 'ObjectType',
47  TUPLE_TYPE = 'TupleType',
48  REFERENCE_TYPE = 'ReferenceType',
49}
50
51export class BasicApiInfo {
52  private node: ts.Node | undefined = undefined; //astnode节点
53  filePath: string = ''; // api所在文件的路径
54  apiType: ApiType = '' as ApiType; // api的类型
55  // api的定义语句,如果为namespace、class、interface、enum等节点的话,则仅为定义的那行
56  definedText: string = '';
57  pos: ts.LineAndCharacter = { line: -1, character: -1 }; // api所在的位置信息
58  parentApi: BasicApiInfo | undefined = undefined; // 定义api节点的父节点的api信息
59  isExport: boolean = false; // api节点是否有export关键字进行导出
60  apiName: string = ''; // api的名称
61  hierarchicalRelations: string[] = []; // api所属的层级关系
62  decorators: DecoratorInfo[] | undefined = undefined; //decorators修饰器集合
63  isStruct: boolean = false; //是否为structDeclaration内部api
64  syscap: string = '';
65  currentVersion = '-1';
66  jsDocText: string = '';
67  isJoinType: boolean = false;
68  genericInfo: GenericInfo[] = [];
69  parentApiType: string = '';
70  fileAbsolutePath: string = ''; //绝对路径
71  isSameNameFunction: boolean = false; //是否为同名API
72
73  constructor(apiType: string = '', node: ts.Node, parentApi: BasicApiInfo | undefined) {
74    this.node = node;
75    this.setParentApi(parentApi);
76    this.setParentApiType(parentApi?.getApiType());
77    if (parentApi) {
78      this.setFilePath(parentApi.getFilePath());
79      this.setFileAbsolutePath(parentApi.getFileAbsolutePath());
80      this.setIsStruct(parentApi.getIsStruct());
81    }
82    this.setApiType(apiType);
83    const sourceFile: ts.SourceFile = node.getSourceFile();
84    const start: number = node.getStart();
85    const pos: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(start);
86    pos.character++;
87    pos.line++;
88    this.setPos(pos);
89    if (node.decorators) {
90      node.decorators.forEach((decorator: ts.Decorator) => {
91        this.addDecorators([new DecoratorInfo(decorator)]);
92      });
93    }
94  }
95
96  getNode(): ts.Node | undefined {
97    return this.node;
98  }
99
100  removeNode(): void {
101    this.node = undefined;
102  }
103
104  setFilePath(fileFilePath: string): void {
105    this.filePath = fileFilePath;
106  }
107
108  getFilePath(): string {
109    return this.filePath;
110  }
111
112  setFileAbsolutePath(absolutePath: string): void {
113    this.fileAbsolutePath = absolutePath;
114  }
115
116  getFileAbsolutePath(): string {
117    return this.fileAbsolutePath;
118  }
119
120  setApiType(apiType: string): void {
121    this.apiType = apiType as ApiType;
122  }
123
124  getApiType(): string {
125    return this.apiType;
126  }
127
128  setDefinedText(definedText: string): void {
129    this.definedText = definedText;
130  }
131
132  getDefinedText(): string {
133    return this.definedText;
134  }
135
136  setPos(pos: ts.LineAndCharacter): void {
137    this.pos = pos;
138  }
139
140  getPos(): ts.LineAndCharacter {
141    return this.pos;
142  }
143
144  setParentApi(parentApi: BasicApiInfo | undefined): void {
145    this.parentApi = parentApi;
146  }
147
148  getParentApi(): BasicApiInfo | undefined {
149    return this.parentApi;
150  }
151
152  setParentApiType(parentApiType: string | undefined): void {
153    if (parentApiType) {
154      this.parentApiType = parentApiType;
155    }
156  }
157
158  getParentApiType(): string {
159    return this.parentApiType;
160  }
161
162  setIsExport(isExport: boolean): void {
163    this.isExport = isExport;
164  }
165
166  getIsExport(): boolean {
167    return this.isExport;
168  }
169
170  setApiName(apiName: string): void {
171    this.apiName = apiName;
172    if (this.parentApi) {
173      this.setHierarchicalRelations(this.parentApi.getHierarchicalRelations());
174    }
175    this.addHierarchicalRelation([apiName]);
176  }
177
178  getApiName(): string {
179    return this.apiName;
180  }
181
182  setHierarchicalRelations(hierarchicalRelations: string[]): void {
183    this.hierarchicalRelations = [...hierarchicalRelations];
184  }
185
186  getHierarchicalRelations(): string[] {
187    return this.hierarchicalRelations;
188  }
189
190  addHierarchicalRelation(hierarchicalRelation: string[]): void {
191    this.hierarchicalRelations.push(...hierarchicalRelation);
192  }
193
194  setDecorators(decorators: DecoratorInfo[]): void {
195    this.decorators = decorators;
196  }
197
198  addDecorators(decorators: DecoratorInfo[]): void {
199    if (!this.decorators) {
200      this.decorators = [];
201    }
202    this.decorators.push(...decorators);
203  }
204
205  getDecorators(): DecoratorInfo[] | undefined {
206    return this.decorators;
207  }
208
209  setIsStruct(isStruct: boolean): void {
210    this.isStruct = isStruct;
211  }
212
213  getIsStruct(): boolean {
214    return this.isStruct;
215  }
216
217  setSyscap(syscap: string): void {
218    this.syscap = syscap;
219  }
220
221  getSyscap(): string {
222    return this.syscap;
223  }
224
225  setCurrentVersion(version: string): void {
226    this.currentVersion = version;
227  }
228
229  getCurrentVersion(): string {
230    return this.currentVersion;
231  }
232
233  setJsDocText(jsDocText: string): void {
234    this.jsDocText = jsDocText;
235  }
236
237  getJsDocText(): string {
238    return this.jsDocText;
239  }
240
241  setIsJoinType(jsJoinType: boolean): void {
242    this.isJoinType = jsJoinType;
243  }
244
245  getIsJoinType(): boolean {
246    return this.isJoinType;
247  }
248
249  setGenericInfo(genericInfo: GenericInfo): void {
250    this.genericInfo.push(genericInfo);
251  }
252
253  getGenericInfo(): GenericInfo[] {
254    return this.genericInfo;
255  }
256
257  setIsSameNameFunction(isSameNameFunction: boolean): void {
258    this.isSameNameFunction = isSameNameFunction;
259  }
260
261  getIsSameNameFunction(): boolean {
262    return this.isSameNameFunction;
263  }
264}
265
266export class ExportDefaultInfo extends BasicApiInfo { }
267
268export class ReferenceInfo extends BasicApiInfo {
269  pathName: string = '';
270
271  setPathName(pathName: string): ReferenceInfo {
272    this.pathName = pathName;
273    return this;
274  }
275
276  getPathName(): string {
277    return this.pathName;
278  }
279}
280
281export class ExportDeclareInfo extends BasicApiInfo {
282  exportValues: Array<ExportImportValue> = [];
283
284  addExportValues(name: string, type: string): void {
285    this.exportValues.push({ key: name, value: type || name });
286  }
287
288  getExportValues(): Array<ExportImportValue> {
289    return this.exportValues;
290  }
291}
292
293/**
294 * import导入的信息,包含导入的值和路径信息
295 */
296export class ImportInfo extends BasicApiInfo {
297  importValues: Array<ExportImportValue> = [];
298  importPath: string = '';
299
300  addImportValue(name: string, type: string): void {
301    this.importValues.push({ key: name, value: type || name });
302  }
303
304  getImportValues(): Array<ExportImportValue> {
305    return this.importValues;
306  }
307
308  setImportPath(importPath: string): void {
309    this.importPath = importPath;
310  }
311
312  getImportPath(): string {
313    return this.importPath;
314  }
315}
316
317export class ApiInfo extends BasicApiInfo {
318  jsDocInfos: Comment.JsDocInfo[] = []; // 所有的JsDoc信息
319
320  constructor(apiType: string = '', node: ts.Node, parentApi: BasicApiInfo | undefined) {
321    super(apiType, node, parentApi);
322    let parentKitInfo: string = 'NA';
323    let parentIsFile: boolean = false;
324    if (parentApi) {
325      parentKitInfo = this.getKitInfoFromParent(parentApi).kitInfo;
326      parentIsFile = this.getKitInfoFromParent(parentApi).isFile;
327    }
328    const jsDocInfos: Comment.JsDocInfo[] = JsDocProcessorHelper.processJsDocInfos(
329      node,
330      apiType,
331      parentKitInfo,
332      parentIsFile
333    );
334    const jsDocText: string = node
335      .getFullText()
336      .substring(0, node.getFullText().length - node.getText().length)
337      .trim();
338    this.setJsDocText(jsDocText);
339    this.addJsDocInfos(jsDocInfos);
340  }
341
342  getKitInfoFromParent(parentApi: BasicApiInfo): FileTag {
343    const parentApiInfo = parentApi as ApiInfo;
344    const jsDocInfos: Comment.JsDocInfo[] = parentApiInfo.getJsDocInfos();
345    let kitInfo: string | undefined = '';
346    let isFile: boolean = false;
347    jsDocInfos.forEach((jsDocInfo: Comment.JsDocInfo) => {
348      kitInfo = jsDocInfo.getKit();
349      isFile = jsDocInfo.getIsFile();
350    });
351    return { kitInfo, isFile };
352  }
353
354  getJsDocInfos(): Comment.JsDocInfo[] {
355    return this.jsDocInfos;
356  }
357
358  getLastJsDocInfo(): Comment.JsDocInfo | undefined {
359    const length: number = this.jsDocInfos.length;
360    if (length === 0) {
361      return undefined;
362    }
363    return this.jsDocInfos[length - 1];
364  }
365
366  addJsDocInfos(jsDocInfos: Comment.JsDocInfo[]): void {
367    if (jsDocInfos.length > 0) {
368      this.setCurrentVersion(jsDocInfos[jsDocInfos.length - 1]?.getSince());
369    }
370    this.jsDocInfos.push(...jsDocInfos);
371  }
372
373  addJsDocInfo(jsDocInfo: Comment.JsDocInfo): void {
374    this.setCurrentVersion(jsDocInfo.getSince());
375    this.jsDocInfos.push(jsDocInfo);
376  }
377}
378
379export class ClassInfo extends ApiInfo {
380  parentClasses: ParentClass[] = []; // 继承的父类
381  childApis: BasicApiInfo[] = []; // 子节点的信息
382
383  setParentClasses(parentClass: ParentClass): void {
384    this.parentClasses.push(parentClass);
385  }
386
387  getParentClasses(): ParentClass[] {
388    return this.parentClasses;
389  }
390
391  addChildApis(childApis: BasicApiInfo[]): void {
392    this.childApis.push(...childApis);
393  }
394
395  addChildApi(childApi: BasicApiInfo): void {
396    this.childApis.push(childApi);
397  }
398
399  getChildApis(): BasicApiInfo[] {
400    return this.childApis;
401  }
402}
403
404export class InterfaceInfo extends ApiInfo {
405  parentClasses: ParentClass[] = []; // 继承的父类
406  childApis: BasicApiInfo[] = []; // 子节点的信息
407
408  setParentClasses(parentClass: ParentClass): void {
409    this.parentClasses.push(parentClass);
410  }
411
412  getParentClasses(): ParentClass[] {
413    return this.parentClasses;
414  }
415
416  addChildApis(childApis: BasicApiInfo[]): void {
417    this.childApis.push(...childApis);
418  }
419
420  addChildApi(childApi: BasicApiInfo): void {
421    this.childApis.push(childApi);
422  }
423
424  getChildApis(): BasicApiInfo[] {
425    return this.childApis;
426  }
427}
428
429export class NamespaceInfo extends ApiInfo {
430  childApis: BasicApiInfo[] = [];
431
432  addChildApis(childApis: BasicApiInfo[]): void {
433    this.childApis.push(...childApis);
434  }
435
436  addChildApi(childApi: BasicApiInfo): void {
437    this.childApis.push(childApi);
438  }
439
440  getChildApis(): BasicApiInfo[] {
441    return this.childApis;
442  }
443}
444
445export class StructInfo extends ApiInfo {
446  childApis: BasicApiInfo[] = [];
447
448  addChildApis(childApis: BasicApiInfo[]): void {
449    this.childApis.push(...childApis);
450  }
451
452  addChildApi(childApi: BasicApiInfo): void {
453    this.childApis.push(childApi);
454  }
455
456  getChildApis(): BasicApiInfo[] {
457    return this.childApis;
458  }
459}
460
461export class ModuleInfo extends ApiInfo {
462  childApis: BasicApiInfo[] = [];
463
464  addChildApis(childApis: BasicApiInfo[]): void {
465    this.childApis.push(...childApis);
466  }
467
468  addChildApi(childApi: BasicApiInfo): void {
469    this.childApis.push(childApi);
470  }
471
472  getChildApis(): BasicApiInfo[] {
473    return this.childApis;
474  }
475}
476
477export class EnumInfo extends ApiInfo {
478  childApis: BasicApiInfo[] = [];
479
480  addChildApis(childApis: BasicApiInfo[]): void {
481    this.childApis.push(...childApis);
482  }
483
484  addChildApi(childApi: BasicApiInfo): void {
485    this.childApis.push(childApi);
486  }
487
488  getChildApis(): BasicApiInfo[] {
489    return this.childApis;
490  }
491}
492
493/**
494 * 属性会包含declare const定义的节点
495 */
496export class PropertyInfo extends ApiInfo {
497  type: string[] = []; // 属性的类型,数组是由于可能为联合类型
498  isReadOnly: boolean = false; // 属性是否为只读
499  isRequired: boolean = false; // 属性是否为必选
500  isStatic: boolean = false; // 属性是否为静态
501  typeKind: ts.SyntaxKind = ts.SyntaxKind.Unknown; //type类型的kind值
502  typeLocations: TypeLocationInfo[] = []; // 参数、返回值的JsDoc信息
503  objLocations: TypeLocationInfo[] = []; // 匿名类型的JsDoc信息
504
505  constructor(apiType: string = '', node: ts.Node, parentApi: BasicApiInfo | undefined) {
506    super(apiType, node, parentApi);
507    let propertyNode: PropertyNode = node as PropertyNode;
508    this.setTypeKind(propertyNode.type ? propertyNode.type.kind : ts.SyntaxKind.Unknown);
509  }
510
511  addType(type: string[]): void {
512    this.type.push(...type);
513  }
514
515  getType(): string[] {
516    return this.type;
517  }
518
519  setIsReadOnly(isReadOnly: boolean): void {
520    this.isReadOnly = isReadOnly;
521  }
522
523  getIsReadOnly(): boolean {
524    return this.isReadOnly;
525  }
526
527  setIsRequired(isRequired: boolean): void {
528    this.isRequired = isRequired;
529  }
530
531  getIsRequired(): boolean {
532    return this.isRequired;
533  }
534
535  setIsStatic(isStatic: boolean): void {
536    this.isStatic = isStatic;
537  }
538
539  getIsStatic(): boolean {
540    return this.isStatic;
541  }
542
543  setTypeKind(typeKind: ts.SyntaxKind | undefined): void {
544    this.typeKind = typeKind ? typeKind : ts.SyntaxKind.Unknown;
545  }
546
547  getTypeKind(): ts.SyntaxKind {
548    return this.typeKind;
549  }
550
551  addTypeLocations(typeLocation: TypeLocationInfo): void {
552    this.typeLocations.push(typeLocation);
553  }
554
555  getTypeLocations(): TypeLocationInfo[] {
556    return this.typeLocations;
557  }
558
559  addObjLocations(ObjLocation: TypeLocationInfo): void {
560    this.objLocations.push(ObjLocation);
561  }
562
563  getObjLocations(): TypeLocationInfo[] {
564    return this.objLocations;
565  }
566}
567
568export class ConstantInfo extends ApiInfo {
569  value: string = ''; // 常量的取值
570
571  setValue(value: string): void {
572    this.value = value;
573  }
574
575  getValue(): string {
576    return this.value;
577  }
578}
579
580/**
581 * 使用type关键字定义的节点,归为自定义类型的范畴
582 */
583export class TypeAliasInfo extends ApiInfo {
584  type: string[] = []; // type定义的类型
585  typeName: TypeAliasType = '' as TypeAliasType; //type的类型
586  returnType: string = ''; //type类型为function时的返回值
587  paramInfos: ParamInfo[] = []; //type类型为function时的参数名和参数类型
588  typeIsFunction: boolean = false; //type类型是否为function
589
590  addType(type: string[]): void {
591    this.type.push(...type);
592  }
593
594  getType(): string[] {
595    return this.type;
596  }
597
598  setTypeName(typeName: string): TypeAliasInfo {
599    this.typeName = typeName as TypeAliasType;
600    return this;
601  }
602
603  getTypeName(): string {
604    return this.typeName;
605  }
606
607  setReturnType(returnType: string): TypeAliasInfo {
608    this.returnType = returnType;
609    return this;
610  }
611
612  getReturnType(): string {
613    return this.returnType;
614  }
615
616  setParamInfos(paramInfo: ParamInfo): TypeAliasInfo {
617    this.paramInfos.push(paramInfo);
618    return this;
619  }
620
621  getParamInfos(): ParamInfo[] {
622    return this.paramInfos;
623  }
624
625  setTypeIsFunction(typeIsFunction: boolean): TypeAliasInfo {
626    this.typeIsFunction = typeIsFunction;
627    return this;
628  }
629
630  getTypeIsFunction(): boolean {
631    return this.typeIsFunction;
632  }
633}
634
635/**
636 * type自定义类型为function时,解析参数
637 */
638export class TypeParamInfo {
639  //type类型为function时的参数名
640  paramName: string = '';
641  //type类型为function时的参数类型
642  paramType: string = '';
643
644  setParamName(paramName: string): TypeParamInfo {
645    this.paramName = paramName;
646    return this;
647  }
648
649  getParamName(): string {
650    return this.paramName;
651  }
652
653  setParamType(paramType: string | undefined): TypeParamInfo {
654    if (!paramType) {
655      return this;
656    }
657    this.paramType = paramType;
658    return this;
659  }
660
661  getParamType(): string {
662    return this.paramType;
663  }
664}
665
666export class EnumValueInfo extends ApiInfo {
667  value: string = ''; // 枚举值
668
669  setValue(value: string): void {
670    this.value = value;
671  }
672
673  getValue(): string {
674    return this.value;
675  }
676}
677
678export class MethodInfo extends ApiInfo {
679  callForm: string = ''; // 方法的调用形式
680  params: ParamInfo[] = []; // 方法的参数列表
681  returnValue: string[] = []; // 方法的返回值类型
682  isStatic: boolean = false; // 方法是否是静态
683  sync: string = ''; //同步函数标志
684  returnValueType: ts.SyntaxKind = ts.SyntaxKind.Unknown;
685  typeLocations: Comment.JsDocInfo[] = []; // 参数、返回值的JsDoc信息
686  objLocations: Comment.JsDocInfo[] = []; // 匿名类型的JsDoc信息
687  isRequired: boolean = false;
688
689  setCallForm(callForm: string): void {
690    this.callForm = callForm;
691  }
692
693  getCallForm(): string {
694    return this.callForm;
695  }
696
697  addParam(paramInfo: ParamInfo): void {
698    this.params.push(paramInfo);
699  }
700
701  getParams(): ParamInfo[] {
702    return this.params;
703  }
704
705  setReturnValue(returnValue: string[]): void {
706    this.returnValue.push(...returnValue);
707  }
708
709  getReturnValue(): string[] {
710    return this.returnValue;
711  }
712
713  setReturnValueType(returnValueType: ts.SyntaxKind): void {
714    this.returnValueType = returnValueType;
715  }
716
717  getReturnValueType(): ts.SyntaxKind {
718    return this.returnValueType;
719  }
720
721  setIsStatic(isStatic: boolean): void {
722    this.isStatic = isStatic;
723  }
724
725  getIsStatic(): boolean {
726    return this.isStatic;
727  }
728
729  addTypeLocations(typeLocation: Comment.JsDocInfo): void {
730    this.typeLocations.push(typeLocation);
731  }
732
733  getTypeLocations(): Comment.JsDocInfo[] {
734    return this.typeLocations;
735  }
736
737  addObjLocations(ObjLocation: Comment.JsDocInfo): void {
738    this.objLocations.push(ObjLocation);
739  }
740
741  getObjLocations(): Comment.JsDocInfo[] {
742    return this.objLocations;
743  }
744
745  setSync(sync: string): void {
746    this.sync = sync;
747  }
748
749  getSync(): string {
750    return this.sync;
751  }
752
753  setIsRequired(isRequired: boolean):void {
754    this.isRequired = isRequired;
755  }
756
757  getIsRequired(): boolean {
758    return this.isRequired;
759  }
760}
761
762export class TypeLocationInfo extends Comment.JsDocInfo {
763  typeName: string = '';//当前类型名称
764
765  getTypeName(): string {
766    return this.typeName;
767  }
768
769  setTypeName(typeName: string): void {
770    this.typeName = typeName;
771  }
772}
773
774export class ParamInfo {
775  apiType: string = ''; // api的类型为方法参数
776  apiName: string = ''; // 参数名
777  paramType: ts.SyntaxKind = ts.SyntaxKind.Unknown; // 参数类型的kind
778  type: string[] = []; // 参数的类型
779  isRequired: boolean = false; // 参数是否必选
780  definedText: string = '';
781  typeLocations: Comment.JsDocInfo[] = []; // 参数、返回值的JsDoc信息
782  objLocations: Comment.JsDocInfo[] = []; // 匿名类型的JsDoc信息
783
784  constructor(apiType: string) {
785    this.apiType = apiType;
786  }
787
788  getApiType(): string {
789    return this.apiType;
790  }
791
792  setApiName(apiName: string): void {
793    this.apiName = apiName;
794  }
795
796  getApiName(): string {
797    return this.apiName;
798  }
799
800  setType(type: string[]): void {
801    this.type.push(...type);
802  }
803
804  getParamType(): ts.SyntaxKind {
805    return this.paramType;
806  }
807
808  setParamType(paramType: ts.SyntaxKind | undefined): void {
809    this.paramType = paramType ? paramType : ts.SyntaxKind.Unknown;
810  }
811
812  getType(): string[] {
813    return this.type;
814  }
815
816  setIsRequired(isRequired: boolean): void {
817    this.isRequired = isRequired;
818  }
819
820  getIsRequired(): boolean {
821    return this.isRequired;
822  }
823
824  setDefinedText(definedText: string): void {
825    this.definedText = definedText;
826  }
827
828  getDefinedText(): string {
829    return this.definedText;
830  }
831
832  addTypeLocations(typeLocation: Comment.JsDocInfo): void {
833    this.typeLocations.push(typeLocation);
834  }
835
836  getTypeLocations(): Comment.JsDocInfo[] {
837    return this.typeLocations;
838  }
839
840  addObjLocations(ObjLocation: Comment.JsDocInfo): void {
841    this.objLocations.push(ObjLocation);
842  }
843
844  getObjLocations(): Comment.JsDocInfo[] {
845    return this.objLocations;
846  }
847}
848
849export class GenericInfo {
850  isGenericity: boolean = false;
851  genericContent: string = '';
852
853  setIsGenericity(isGenericity: boolean): void {
854    this.isGenericity = isGenericity;
855  }
856  getIsGenericity(): boolean {
857    return this.isGenericity;
858  }
859
860  setGenericContent(genericContent: string): void {
861    this.genericContent = genericContent;
862  }
863
864  getGenericContent(): string {
865    return this.genericContent;
866  }
867}
868
869export class ParentClass {
870  extendClass: string = '';
871  implementClass: string = '';
872
873  setExtendClass(extendClass: string): void {
874    this.extendClass = extendClass;
875  }
876
877  getExtendClass(): string {
878    return this.extendClass;
879  }
880
881  setImplementClass(implementClass: string): void {
882    this.implementClass = implementClass;
883  }
884
885  getImplementClass(): string {
886    return this.implementClass;
887  }
888}
889
890export class ParserParam {
891  fileDir: string = '';
892  filePath: string = '';
893  sdkPath: string = '';
894  rootNames: string[] = [];
895  tsProgram: ts.Program = ts.createProgram({
896    rootNames: [],
897    options: {},
898  });
899  constructor() { }
900
901  getFileDir(): string {
902    return this.fileDir;
903  }
904
905  setFileDir(fileDir: string): void {
906    this.fileDir = fileDir;
907  }
908
909  getFilePath(): string {
910    return this.filePath;
911  }
912
913  setFilePath(filePath: string): void {
914    this.filePath = filePath;
915  }
916
917  getSdkPath(): string {
918    return this.sdkPath;
919  }
920
921  setSdkPath(sdkPath: string): void {
922    this.sdkPath = sdkPath;
923  }
924
925  getRootNames(): string[] {
926    return this.rootNames;
927  }
928
929  setRootNames(rootNames: string[]): void {
930    this.rootNames = rootNames;
931  }
932
933  getTsProgram(): ts.Program {
934    return this.tsProgram;
935  }
936
937  getETSOptions(componentLibs: Array<string>): any {
938    const tsconfig = require('../../config/tsconfig.json');
939    const etsConfig = tsconfig.compilerOptions.ets;
940    etsConfig.libs = [...componentLibs];
941    return etsConfig;
942  }
943
944  setProgram(apiLibs: Array<string>): void {
945    const compilerOption: ts.CompilerOptions = {
946      target: ts.ScriptTarget.ES2017,
947      ets: this.getETSOptions([]),
948      allowJs: false,
949      lib: [...apiLibs, ...this.rootNames],
950      module: ts.ModuleKind.CommonJS,
951      baseUrl: "./",
952      paths: {
953        "@/*": ["./*"]
954      },
955    };
956    const compilerHost: ts.CompilerHost = ts.createCompilerHost(compilerOption);
957    // 设置别名
958    compilerHost.resolveModuleNames = (moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ts.ResolvedProjectReference | undefined, compilerOptions: ts.CompilerOptions) => {
959      return moduleNames.map(moduleName => {
960        if (process.env.IS_OH === 'true') {
961          return ts.resolveModuleName(moduleName, containingFile, compilerOptions, compilerHost).resolvedModule;
962        }
963        const value: ts.ResolvedModule = {
964          resolvedFileName: '',
965          isExternalLibraryImport: false
966        };
967        const alias: { [key: string]: string; } = {
968          "^(@ohos\\.inner\\.)(.*)$": "../../../base/ets/api/",
969          "^(@ohos\\.)(.*)$": "../../../base/ets/api/",
970        };
971        for (const key in alias) {
972          const regex = new RegExp(key);
973          if (regex.test(moduleName)) {
974            moduleName = moduleName.replace(regex, ($0, $1, $2) => {
975              let realPath = '';
976              switch ($1) {
977                case "@ohos.":
978                  realPath = alias[key] + $1 + $2;
979                  break;
980                case "@ohos\.inner\.":
981                  realPath = alias[key] + $2.replace(/\./g, '/');
982                  break;
983                default:
984                  realPath = '';
985                  break;
986              }
987              return realPath;
988            });
989            break;
990          }
991        }
992        const resolvedFileName: string | undefined = ts.resolveModuleName(moduleName, containingFile, compilerOptions,
993          compilerHost).resolvedModule?.resolvedFileName;
994        if (resolvedFileName) {
995          value.resolvedFileName = resolvedFileName;
996          value.isExternalLibraryImport = true;
997        } else {
998          return undefined;
999        }
1000        return value;
1001      });
1002    };
1003    this.tsProgram = ts.createProgram({
1004      rootNames: [...apiLibs],
1005      options: compilerOption,
1006      host: compilerHost
1007    });
1008  }
1009}
1010
1011export type ExportImportValue = { key: string; value: string; };
1012export interface NodeProcessorInterface {
1013  (node: ts.Node, parentApiInfo: BasicApiInfo): BasicApiInfo;
1014}
1015
1016export type PropertyNode = ts.PropertyDeclaration | ts.PropertySignature;
1017
1018export interface ModifierProcessorInterface {
1019  (propertyInfo: BasicApiInfo): void;
1020}
1021
1022export interface FileTag {
1023  kitInfo: string;
1024  isFile: boolean;
1025}
1026
1027/**
1028 * ts中所有方法节点
1029 */
1030export type MethodType =
1031  | ts.MethodDeclaration
1032  | ts.MethodSignature
1033  | ts.FunctionDeclaration
1034  | ts.CallSignatureDeclaration
1035  | ts.ConstructorDeclaration
1036  | ts.ConstructSignatureDeclaration;
1037
1038/**
1039 * 拥有子节点的class,处理数据时需要addChildApi,获取数据时可以getChildApis
1040 */
1041export type ContainerApiInfo = NamespaceInfo | ClassInfo | InterfaceInfo | EnumInfo | ModuleInfo | StructInfo;
1042
1043/**
1044 * 将节点强制转换为ContainerApiInfo节点时需要根据ApiType来判断哪些apiInfo节点有childApi
1045 */
1046export const containerApiTypes: Set<string> = new Set([
1047  ApiType.NAMESPACE,
1048  ApiType.CLASS,
1049  ApiType.INTERFACE,
1050  ApiType.ENUM,
1051  ApiType.MODULE,
1052  ApiType.STRUCT,
1053]);
1054
1055/**
1056 * 不存在jsdoc信息的节点
1057 */
1058export const notJsDocApiTypes: Set<string> = new Set([
1059  ApiType.SOURCE_FILE,
1060  ApiType.IMPORT,
1061  ApiType.EXPORT,
1062  ApiType.EXPORT_DEFAULT,
1063  ApiType.MODULE,
1064  ApiType.REFERENCE_FILE,
1065]);
1066