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