• 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, { TypeParameter, TypeParameterDeclaration } from 'typescript';
17import _ from 'lodash';
18import path from 'path';
19
20import {
21  ApiInfo,
22  ApiType,
23  BasicApiInfo,
24  ClassInfo,
25  ConstantInfo,
26  ContainerApiInfo,
27  EnumInfo,
28  EnumValueInfo,
29  ExportDeclareInfo,
30  ExportDefaultInfo,
31  ImportInfo,
32  InterfaceInfo,
33  MethodInfo,
34  MethodType,
35  ModifierProcessorInterface,
36  ModuleInfo,
37  NamespaceInfo,
38  NodeProcessorInterface,
39  ParamInfo,
40  PropertyInfo,
41  PropertyNode,
42  PropertyTypeNode,
43  ReferenceInfo,
44  StructInfo,
45  TypeAliasType,
46  TypeAliasInfo,
47  containerApiTypes,
48  GenericInfo,
49  ParentClass,
50  ParserParam,
51  FileTag,
52  TypeParamInfo,
53} from '../../typedef/parser/ApiInfoDefination';
54import { Comment } from '../../typedef/parser/Comment';
55import { StringUtils } from '../../utils/StringUtils';
56import { StringConstant, EventConstant } from '../../utils/Constant';
57import { BasicApiInfoMap, ApiInfosMap, FileInfoMap } from './parser';
58import { JsDocProcessorHelper } from './JsDocProcessor';
59
60export const parserParam: ParserParam = new ParserParam();
61
62export class NodeProcessorHelper {
63  // 如果是字符串的话,会出现单双引号重复的情况
64  static regQuotation: RegExp = /^[\'|\"](.*)[\'|\"]$/;
65
66
67  /**
68   * 停止递归
69   *
70   */
71  static stopRecursion = false;
72
73  /**
74   * 解析文件typereference对应symbol集合
75   *
76   * @type {Map<string, Map<string, ts.Symbol>>}
77   */
78  static symbolOfTypeReferenceMap: Map<string, Map<string, ts.Symbol>> = new Map<string, Map<string, ts.Symbol>>();
79
80  static typeReferenceFileMap: Map<string, ApiInfo> = new Map();
81
82  static processReference(
83    sourceFile: ts.SourceFile,
84    parentMap: Map<string, object>,
85    parentApiInfo: BasicApiInfo
86  ): void {
87    const references: ReferenceInfo[] = [];
88    sourceFile.referencedFiles.forEach((referencedFile: ts.FileReference) => {
89      const referenceInfo: ReferenceInfo = new ReferenceInfo(ApiType.REFERENCE_FILE, sourceFile, parentApiInfo);
90      referenceInfo.setApiName(ApiType.REFERENCE_FILE);
91      referenceInfo.setPathName(referencedFile.fileName);
92      references.push(referenceInfo);
93    });
94    if (references.length === 0) {
95      return;
96    }
97    const currentMap: Map<string, object> = new Map();
98    currentMap.set(StringConstant.SELF, references);
99    parentMap.set(StringConstant.REFERENCE, currentMap);
100  }
101  /**
102   * 根据节点类型处理节点的方法,处理的主流程
103   *
104   * @param { ts.Node } node 当前处理的节点
105   * @param { FileInfoMap } parentMap 父节点建立的map对象
106   * @param { BasicApiInfo } parentApiInfo 父节点解析后的对象
107   * @param { boolean } [stopRecursion=false] 是否停止递归
108   */
109  static processNode(node: ts.Node, parentMap: FileInfoMap | ApiInfosMap, parentApiInfo: BasicApiInfo,
110    stopRecursion: boolean = false): void {
111    NodeProcessorHelper.stopRecursion = stopRecursion;
112    const nodeProcessor: NodeProcessorInterface | undefined = nodeProcessorMap.get(node.kind);
113    if (!nodeProcessor) {
114      return;
115    }
116    const apiInfo: BasicApiInfo = nodeProcessor(node, parentApiInfo);
117    const currentMap: BasicApiInfoMap = NodeProcessorHelper.setApiInfo(apiInfo, parentMap, node);
118    const childNodes: ts.NodeArray<ts.Node> | undefined = NodeProcessorHelper.getChildNodes(node);
119    if (!childNodes) {
120      return;
121    }
122    childNodes.forEach((cNode: ts.Node) => {
123      if (apiInfo.getApiType() === ApiType.STRUCT && cNode.getFullText() === '') {
124        // 去除struct的默认构造方法
125        return;
126      }
127      NodeProcessorHelper.processNode(cNode, currentMap as ApiInfosMap, apiInfo, stopRecursion);
128    });
129  }
130
131  /**
132   * 将解析后的api添加到当前的map中,会对某些特殊情况进行调整
133   *
134   * @param { BasicApiInfo } apiInfo 当前api的解析对象
135   * @param { Map<string, object> } parentMap 当前父节点所在的map
136   * @param { ts.Node } node 当前apinode节点
137   * @returns { Map<string, object> } 返回当前节点所属的map
138   */
139  static setApiInfo(apiInfo: BasicApiInfo, parentMap: FileInfoMap | ApiInfosMap, node: ts.Node): BasicApiInfoMap {
140    if (apiInfo.getApiType() !== ApiType.METHOD) {
141      return NodeProcessorHelper.setSingleApiInfo(apiInfo, parentMap);
142    }
143    let apiInfos: BasicApiInfo[] = [];
144    apiInfos = NodeProcessorHelper.processEventMethod(apiInfo, node);
145    // 处理promise/asynccallback
146    NodeProcessorHelper.processAsyncMethod(apiInfos);
147    let currentMap: BasicApiInfoMap = new Map();
148    apiInfos.forEach((apiInfo: BasicApiInfo) => {
149      currentMap = NodeProcessorHelper.setSingleApiInfo(apiInfo, parentMap);
150    });
151    return currentMap;
152  }
153
154  /**
155   *  将解析后的单个api添加到当前的map中,不允许对apiInfo进行二次修改
156   *
157   * @param { BasicApiInfo } apiInfo 当前api的解析对象
158   * @param { ApiInfosMap } parentMap  当前父节点所在的map
159   * @return { BasicApiInfoMap } 返回当前节点所属的map
160   */
161  static setSingleApiInfo(apiInfo: BasicApiInfo, parentMap: FileInfoMap | ApiInfosMap): BasicApiInfoMap {
162    const apiName: string = apiInfo.getApiName();
163    const parentApiInfo: BasicApiInfo | undefined = apiInfo.getParentApi();
164    if (parentApiInfo && containerApiTypes.has(parentApiInfo.apiType)) {
165      const containerApiInfo: ContainerApiInfo = parentApiInfo as ContainerApiInfo;
166      containerApiInfo.addChildApi(apiInfo);
167    }
168    if (parentMap.has(apiName)) {
169      //同名方法处理
170      const currentMap: BasicApiInfoMap = parentMap.get(apiName) as BasicApiInfoMap;
171      const methodInfos: BasicApiInfo[] = currentMap.get(StringConstant.SELF) as BasicApiInfo[];
172      methodInfos.push(apiInfo);
173      return currentMap;
174    }
175    const apiInfos: BasicApiInfo[] = [];
176    apiInfos.push(apiInfo);
177    const currentMap: BasicApiInfoMap = new Map();
178    currentMap.set(StringConstant.SELF, apiInfos);
179    parentMap.set(apiName, currentMap);
180    return currentMap;
181  }
182
183  /**
184   * 处理方法节点中事件订阅相关方法
185   *
186   * 第一个参数只要是字符串的字面量就将apiName修改为on_string,联合类型进行分开解析
187   * @param {BasicApiInfo} apiInfo 当前api的解析对象
188   * @param {ts.Node} node 当前apinode节点
189   * @return {BasicApiInfo[]} 解析完on/off的apiInfo数组
190   */
191  static processEventMethod(apiInfo: BasicApiInfo, node: ts.Node): BasicApiInfo[] {
192    const apiInfos: BasicApiInfo[] = [];
193    const type: ts.TypeNode | undefined = NodeProcessorHelper.getOnOrOffMethodFirstParamType(
194      apiInfo,
195      node as MethodType
196    );
197    if (type === undefined) {
198      apiInfos.push(apiInfo);
199      return apiInfos;
200    }
201    const literal = (type as ts.LiteralTypeNode).literal;
202    if (type.kind === ts.SyntaxKind.LiteralType && ts.isStringLiteral(literal)) {
203      const text: string = literal.getText();
204      apiInfo.setApiName(`${apiInfo.getApiName()}_${text.substring(1, text.length - 1)}`);
205      apiInfo.setIsJoinType(true);
206    } else if (type.kind === ts.SyntaxKind.UnionType) {
207      const types: ts.NodeArray<ts.TypeNode> = (type as ts.UnionTypeNode).types;
208      types.forEach((item: ts.TypeNode) => {
209        if (ts.isLiteralTypeNode(item) && ts.isStringLiteral(item.literal)) {
210          const text: string = item.literal.getText();
211          const cloneApiInfo: BasicApiInfo = _.cloneDeep(apiInfo);
212          cloneApiInfo.setParentApi(apiInfo.getParentApi());
213          cloneApiInfo.setApiName(`${apiInfo.getApiName()}_${text.substring(1, text.length - 1)}`);
214          apiInfo.setIsJoinType(true);
215          apiInfos.push(cloneApiInfo);
216        }
217      });
218    } else if (type.kind === ts.SyntaxKind.StringKeyword) {
219      apiInfo.setApiName(`${apiInfo.getApiName()}_string`);
220      apiInfo.setIsJoinType(true);
221    } else if (type.kind === ts.SyntaxKind.BooleanKeyword) {
222      apiInfo.setApiName(`${apiInfo.getApiName()}_boolean`);
223      apiInfo.setIsJoinType(true);
224    } else {
225      apiInfo.setApiName(`${apiInfo.getApiName()}_${type.getText()}`);
226      apiInfo.setIsJoinType(true);
227    }
228    if (apiInfos.length === 0) {
229      apiInfos.push(apiInfo);
230    }
231    return apiInfos;
232  }
233
234  /**
235   * 获取on/off方法第一个参数的类型
236   *
237   * @param {BasicApiInfo} apiInfo 当前api的解析对象
238   * @param {MethodType} methodNode 当前apinode节点
239   * @return {(ts.TypeNode | undefined)} 满足条件的on/off第一个参数的类型
240   */
241  static getOnOrOffMethodFirstParamType(apiInfo: BasicApiInfo, methodNode: MethodType): ts.TypeNode | undefined {
242    const subscriotionSet: Set<string> = new Set(EventConstant.eventNameList);
243    if (!subscriotionSet.has(apiInfo.getApiName())) {
244      return undefined;
245    }
246    apiInfo.setIsJoinType(true);
247    if (methodNode.parameters.length === 0) {
248      return undefined;
249    }
250    const firstParam: ts.ParameterDeclaration = methodNode.parameters[0];
251    return firstParam.type;
252  }
253
254  /**
255   * 处理AsyncCallback和Promise,将符合规则的apiName修改为apiName(AsyncCallback/Promise256   *
257   * 1、返回参数是Promise类型
258   *
259   * 2、参数中有类型为AsyncCallback的参数
260   *
261   * @param {BasicApiInfo[]} apiInfos 需要处理的apiInfo集合
262   */
263  static processAsyncMethod(apiInfos: BasicApiInfo[]): void {
264    apiInfos.forEach((apiInfo: BasicApiInfo) => {
265      const methodInfo: MethodInfo = apiInfo as MethodInfo;
266      const returnValues: string[] = methodInfo.getReturnValue();
267      if (returnValues.length === 1 && returnValues[0].startsWith(StringConstant.PROMISE_METHOD_KEY)) {
268        methodInfo.setSync(StringConstant.PROMISE_METHOD_KEY_CHANGE);
269        return;
270      }
271      const params: ParamInfo[] = methodInfo.getParams();
272      for (let i = params.length - 1; i >= 0; i--) {
273        const paramType: string[] = params[i].getType();
274        if (paramType.length === 1 && paramType[0].startsWith(StringConstant.ASYNC_CALLBACK_METHOD_KEY)) {
275          methodInfo.setSync(StringConstant.ASYNC_CALLBACK_METHOD_KEY_CHANGE);
276          return;
277        }
278      }
279    });
280  }
281
282  /**
283   * 获取interface、class、namespace,struct以及type定义的对象的子节点
284   *
285   * @param { ts.Node } node 当前节点
286   * @returns { ts.NodeArray<ts.Node> | undefined } 返回当前节点的子节点
287   */
288  static getChildNodes(node: ts.Node): ts.NodeArray<ts.Node> | undefined {
289    if (ts.isInterfaceDeclaration(node) || ts.isClassDeclaration(node) || ts.isEnumDeclaration(node)) {
290      return node.members;
291    }
292    if (ts.isStructDeclaration(node)) {
293      return ts.visitNodes(node.members, (node) => {
294        if (ts.isConstructorDeclaration(node)) {
295          return undefined;
296        }
297        return node;
298      });
299    }
300    if (ts.isModuleDeclaration(node) && node.body && ts.isModuleBlock(node.body)) {
301      return node.body.statements;
302    }
303    return undefined;
304  }
305
306  /**
307   * 处理export default xxx节点
308   *
309   * @param { ts.Node } node 当前节点
310   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
311   * @returns { ExportDefaultInfo } 返回处理后得到的ExportDefaultInfo对象
312   */
313  static processExportAssignment(node: ts.Node, parentApi: BasicApiInfo): ExportDefaultInfo {
314    const exportDefaultInfo: ExportDefaultInfo = new ExportDefaultInfo(ApiType.EXPORT_DEFAULT, node, parentApi);
315    const exportDefaultNode: ts.ExportAssignment = node as ts.ExportAssignment;
316    exportDefaultInfo.setApiName(StringConstant.EXPORT_DEFAULT + exportDefaultNode.expression.getText());
317    exportDefaultInfo.setDefinedText(exportDefaultNode.getText());
318    ModifierHelper.processModifiers(exportDefaultNode.modifiers, exportDefaultInfo);
319    return exportDefaultInfo;
320  }
321
322  /**
323   * 处理export { xxx }节点
324   *
325   * @param { ts.Node } node 当前节点
326   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
327   * @returns { ExportDeclareInfo } 返回处理后得到的ExportDeclareInfoInfo对象
328   */
329  static processExportDeclaration(node: ts.Node, parentApi: BasicApiInfo): ExportDeclareInfo {
330    const exportDeclareInfo: ExportDeclareInfo = new ExportDeclareInfo(ApiType.EXPORT, node, parentApi);
331    const exportDeclarationNode: ts.ExportDeclaration = node as ts.ExportDeclaration;
332    const exportClause: ts.NamedExportBindings | undefined = exportDeclarationNode.exportClause;
333    if (!exportClause) {
334      //export * from 'test';
335      exportDeclareInfo.setApiName(
336        StringConstant.EXPORT +
337        (exportDeclarationNode.moduleSpecifier ? exportDeclarationNode.moduleSpecifier.getText() : '')
338      );
339    } else if (ts.isNamespaceExport(exportClause)) {
340      //export * as myTest from 'test';
341      exportDeclareInfo.setApiName(StringConstant.EXPORT + exportClause.name.getText());
342    } else if (ts.isNamedExports(exportClause)) {
343      // export { xxx , yyy  }
344      // export { xxx as x, yyy as y }
345      const exportValueNames: string[] = [];
346      exportClause.elements.forEach((element: ts.ExportSpecifier) => {
347        const exportValueType: string = element.propertyName ? element.propertyName.getText() : '';
348        const exportValueName: string = element.name.getText();
349        exportValueNames.push(exportValueName);
350        exportDeclareInfo.addExportValues(exportValueName, exportValueType);
351      });
352      exportDeclareInfo.setApiName(StringConstant.EXPORT + exportValueNames.join('_'));
353    }
354    exportDeclareInfo.setDefinedText(exportDeclarationNode.getText());
355    ModifierHelper.processModifiers(exportDeclarationNode.modifiers, exportDeclareInfo);
356    return exportDeclareInfo;
357  }
358
359  /**
360   * 处理 export import NetAddress = connection.NetAddress;
361   *
362   * @param { ts.Node } node 当前节点
363   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
364   * @returns { importInfo } 返回处理后得到的importInfo对象
365   */
366  static processImportEqualsDeclaration(node: ts.Node, parentApi: BasicApiInfo): ImportInfo {
367    const importInfo: ImportInfo = new ImportInfo(ApiType.EXPORT, node, parentApi);
368    return importInfo;
369  }
370
371  /**
372   * 处理import xxx from xxx 节点
373   *
374   * @param { ts.Node } node 当前节点
375   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
376   * @returns { ImportInfo } 返回处理后得到的ImportInfo对象
377   */
378  static processImportInfo(node: ts.Node, parentApi: BasicApiInfo): ImportInfo {
379    const importInfo: ImportInfo = new ImportInfo(ApiType.IMPORT, node, parentApi);
380    const importNode: ts.ImportDeclaration = node as ts.ImportDeclaration;
381    importInfo.setApiName(importNode.moduleSpecifier.getText());
382    importInfo.setImportPath(importNode.moduleSpecifier.getText());
383    importInfo.setDefinedText(importNode.getText());
384    ModifierHelper.processModifiers(importNode.modifiers, importInfo);
385    if (importNode.importClause === undefined) {
386      return importInfo;
387    }
388    const importClause: ts.ImportClause = importNode.importClause;
389    if (importClause.namedBindings && ts.isNamedImports(importClause.namedBindings)) {
390      importClause.namedBindings.elements.forEach((element: ts.ImportSpecifier) => {
391        const importValueType: string = element.propertyName ? element.propertyName.getText() : '';
392        const importValueName: string = element.name.getText();
393        importInfo.addImportValue(importValueName, importValueType);
394      });
395    } else {
396      const importValueName: string = importClause.name ? importClause.name.escapedText.toString() : '';
397      importInfo.addImportValue(importValueName, importValueName);
398    }
399    return importInfo;
400  }
401
402  /**
403   * 处理interface节点
404   *
405   * @param { ts.Node } node 当前节点
406   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
407   * @returns { InterfaceInfo } 返回处理后得到的InterfaceInfo对象
408   */
409  static processInterface(node: ts.Node, parentApi: BasicApiInfo): InterfaceInfo {
410    const interfaceDeclaration: ts.InterfaceDeclaration = node as ts.InterfaceDeclaration;
411    const interfaceInfo: InterfaceInfo = new InterfaceInfo(ApiType.INTERFACE, node, parentApi);
412    interfaceInfo.setApiName(interfaceDeclaration.name.getText());
413    interfaceDeclaration.typeParameters?.forEach((typeParameter: ts.TypeParameterDeclaration) => {
414      interfaceInfo.setGenericInfo(NodeProcessorHelper.processGenericity(typeParameter));
415    });
416    ModifierHelper.processModifiers(interfaceDeclaration.modifiers, interfaceInfo);
417    if (interfaceDeclaration.heritageClauses === undefined) {
418      return interfaceInfo;
419    }
420    interfaceDeclaration.heritageClauses.forEach((value: ts.HeritageClause) => {
421      if (value.token === ts.SyntaxKind.ExtendsKeyword) {
422        value.types.forEach((value: ts.ExpressionWithTypeArguments) => {
423          const parentClass: ParentClass = new ParentClass();
424          parentClass.setImplementClass('');
425          parentClass.setExtendClass(value.getText());
426          interfaceInfo.setParentClasses(parentClass);
427        });
428      } else if (value.token === ts.SyntaxKind.ImplementsKeyword) {
429        value.types.forEach((value: ts.ExpressionWithTypeArguments) => {
430          const parentClass: ParentClass = new ParentClass();
431          parentClass.setImplementClass(value.getText());
432          parentClass.setExtendClass('');
433          interfaceInfo.setParentClasses(parentClass);
434        });
435      }
436    });
437    return interfaceInfo;
438  }
439
440  static processGenericity(typeParameter: ts.TypeParameterDeclaration): GenericInfo {
441    const genericInfo: GenericInfo = new GenericInfo();
442    genericInfo.setIsGenericity(true);
443    genericInfo.setGenericContent(typeParameter.getText());
444    return genericInfo;
445  }
446  /**
447   * 处理class节点
448   *
449   * @param { ts.Node } node 当前节点
450   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
451   * @returns { ClassInfo } 返回处理后得到的ClassInfo对象
452   */
453  static processClass(node: ts.Node, parentApi: BasicApiInfo): ClassInfo {
454    const classDeclaration: ts.ClassDeclaration = node as ts.ClassDeclaration;
455    const classInfo: ClassInfo = new ClassInfo(ApiType.CLASS, node, parentApi);
456    const className: string = classDeclaration.name ? classDeclaration.name.getText() : '';
457    classInfo.setApiName(className);
458    classDeclaration.typeParameters?.forEach((typeParameter: ts.TypeParameterDeclaration) => {
459      classInfo.setGenericInfo(NodeProcessorHelper.processGenericity(typeParameter));
460    });
461    ModifierHelper.processModifiers(classDeclaration.modifiers, classInfo);
462    if (classDeclaration.heritageClauses === undefined) {
463      return classInfo;
464    }
465    classDeclaration.heritageClauses.forEach((value: ts.HeritageClause) => {
466      if (value.token === ts.SyntaxKind.ExtendsKeyword) {
467        value.types.forEach((value: ts.ExpressionWithTypeArguments) => {
468          const parentClass: ParentClass = new ParentClass();
469          parentClass.setExtendClass(value.getText());
470          parentClass.setImplementClass('');
471          classInfo.setParentClasses(parentClass);
472        });
473      } else if (value.token === ts.SyntaxKind.ImplementsKeyword) {
474        value.types.forEach((value: ts.ExpressionWithTypeArguments) => {
475          const parentClass: ParentClass = new ParentClass();
476          parentClass.setImplementClass(value.getText());
477          parentClass.setExtendClass('');
478          classInfo.setParentClasses(parentClass);
479        });
480      }
481    });
482    return classInfo;
483  }
484
485  /**
486   * 处理module节点,分为外部模块(module)和内部模块(namespace)
487   *
488   * @param { ts.Node } node 当前节点
489   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
490   * @returns { NamespaceInfo } 返回处理后得到的NamespaceInfo对象
491   */
492  static processBaseModule(node: ts.Node, parentApi: BasicApiInfo): NamespaceInfo {
493    const moduleDeclaration: ts.ModuleDeclaration = node as ts.ModuleDeclaration;
494    if (!ts.isIdentifier(moduleDeclaration.name)) {
495      return NodeProcessorHelper.processModule(node, parentApi);
496    }
497    return NodeProcessorHelper.processNamespace(node, parentApi);
498  }
499
500  /**
501   * 处理module节点-外部模块
502   *
503   * @param { ts.Node } node 当前节点
504   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
505   * @returns { ModuleInfo } 返回处理后得到的ModuleInfo对象
506   */
507  static processModule(node: ts.Node, parentApi: BasicApiInfo): ModuleInfo {
508    const moduleDeclaration: ts.ModuleDeclaration = node as ts.ModuleDeclaration;
509    const moduleInfo: ModuleInfo = new ModuleInfo(ApiType.MODULE, node, parentApi);
510    moduleInfo.setApiName(moduleDeclaration.name.getText());
511    ModifierHelper.processModifiers(moduleDeclaration.modifiers, moduleInfo);
512    return moduleInfo;
513  }
514
515  /**
516   * 处理namespace节点-内部模块
517   *
518   * @param { ts.Node } node 当前节点
519   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
520   * @returns { NamespaceInfo } 返回处理后得到的NamespaceInfo对象
521   */
522  static processNamespace(node: ts.Node, parentApi: BasicApiInfo): NamespaceInfo {
523    const moduleDeclaration: ts.ModuleDeclaration = node as ts.ModuleDeclaration;
524    const namespaceInfo: NamespaceInfo = new NamespaceInfo(ApiType.NAMESPACE, node, parentApi);
525    namespaceInfo.setApiName(moduleDeclaration.name.getText());
526    ModifierHelper.processModifiers(moduleDeclaration.modifiers, namespaceInfo);
527    return namespaceInfo;
528  }
529
530  /**
531   * 处理enum节点
532   *
533   * @param { ts.Node } node 当前节点
534   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
535   * @returns { EnumInfo } 返回处理后得到的EnumInfo对象
536   */
537  static processEnum(node: ts.Node, parentApi: BasicApiInfo): EnumInfo {
538    const enumDeclaration: ts.EnumDeclaration = node as ts.EnumDeclaration;
539    const enumInfo: EnumInfo = new EnumInfo(ApiType.ENUM, node, parentApi);
540    enumInfo.setApiName(enumDeclaration.name.getText());
541    ModifierHelper.processModifiers(enumDeclaration.modifiers, enumInfo);
542    return enumInfo;
543  }
544
545  /**
546   * 处理枚举值节点
547   *
548   * @param { ts.Node } node 当前节点
549   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
550   * @returns { EnumValueInfo } 返回处理后得到的EnumValueInfo对象
551   */
552  static processEnumValue(node: ts.Node, parentApi: BasicApiInfo): EnumValueInfo {
553    const enumValueNode: ts.EnumMember = node as ts.EnumMember;
554    const enumValue: string | undefined = enumValueNode.initializer?.getText();
555    const enumValueInfo: EnumValueInfo = new EnumValueInfo(ApiType.ENUM_VALUE, node, parentApi);
556    enumValueInfo.setApiName(enumValueNode.name.getText());
557    enumValueInfo.setDefinedText(enumValueNode.getText());
558    enumValueInfo.setValue(enumValue ?? NodeProcessorHelper.getCurrentEnumValue(parentApi));
559    if (enumValueNode.initializer) {
560      const value: string = enumValueNode.initializer.getText().replace(NodeProcessorHelper.regQuotation, '$1');
561      enumValueInfo.setValue(value);
562    }
563    return enumValueInfo;
564  }
565
566  /**
567   *
568   * @param  { BasicApiInfo } enumInfo Enum枚举类节点的信息
569   * @returns { string } 返回当前遍历到的枚举成员的可能的枚举值
570   */
571  static getCurrentEnumValue(enumInfo: BasicApiInfo): string {
572    if (!(enumInfo instanceof EnumInfo)) {
573      return '';
574    }
575    const length: number = enumInfo.getChildApis().length;
576    if (length === 0) {
577      return String(0);
578    }
579    const preEnumValueInfo: EnumValueInfo = enumInfo.getChildApis()[length - 1] as EnumValueInfo;
580    const preEnumValue: string = preEnumValueInfo.getValue();
581    return isNaN(Number(preEnumValue)) ? '' : `${Number(preEnumValue) + 1}`;
582  }
583
584  /**
585   * 处理interface或class下面的属性节点
586   *
587   * @param { ts.Node } node 当前节点
588   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
589   * @returns { PropertyInfo } 返回处理后得到的PropertyInfo对象
590   */
591  static processPropertySigAndDec(node: ts.Node, parentApi: BasicApiInfo): PropertyInfo {
592    const propertyNode: PropertyNode = node as PropertyNode;
593    const propertyInfo: PropertyInfo = new PropertyInfo(ApiType.PROPERTY, node, parentApi);
594    const typeNode: PropertyTypeNode = propertyNode.type ? propertyNode.type : propertyNode.initializer;
595    //TODO { [key: string]: any }   IndexSignature 类型节点需要处理
596    propertyInfo.setApiName(propertyNode.name?.getText());
597    propertyInfo.setDefinedText(propertyNode.getText());
598    ModifierHelper.processModifiers(propertyNode.modifiers, propertyInfo);
599    propertyInfo.setIsRequired(!propertyNode.questionToken ? true : false);
600    propertyInfo.addType(NodeProcessorHelper.processDataType(typeNode));
601    NodeProcessorHelper.processFunctionTypeNode(propertyNode.type, propertyInfo, new ParamInfo(ApiType.PARAM), false);
602    propertyInfo.setTypeKind(typeNode?.kind);
603    return propertyInfo;
604  }
605
606  /**
607   * 处理.d.ets文件中的Struct节点
608   *
609   * @param { ts.Node } node 当前节点
610   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
611   * @returns { StructInfo } 返回处理后得到的StructInfo对象
612   */
613  static processStruct(node: ts.Node, parentApi: BasicApiInfo): StructInfo {
614    const structNode: ts.StructDeclaration = node as ts.StructDeclaration;
615    const structInfo: StructInfo = new StructInfo(ApiType.STRUCT, node, parentApi);
616    const structName: string = structNode.name ? structNode.name.getText() : '';
617    structInfo.setApiName(structName);
618    structInfo.setDefinedText(structInfo.getApiName());
619    ModifierHelper.processModifiers(structNode.modifiers, structInfo);
620    return structInfo;
621  }
622
623  /**
624   * 处理方法节点
625   *
626   * @param { ts.Node } node 当前节点
627   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
628   * @returns { MethodInfo } 返回处理后得到的MethodInfo对象
629   */
630  static processMethod(node: ts.Node, parentApi: BasicApiInfo): MethodInfo {
631    const methodNode: MethodType = node as MethodType;
632    const methodInfo: MethodInfo = new MethodInfo(ApiType.METHOD, node, parentApi);
633    methodInfo.setDefinedText(methodNode.getText());
634    let methodName: string = methodNode.name ? methodNode.name.getText() : '';
635    if (
636      ts.isConstructorDeclaration(methodNode) ||
637      ts.isConstructSignatureDeclaration(methodNode) ||
638      ts.isCallSignatureDeclaration(methodNode)
639    ) {
640      methodName = StringConstant.CONSTRUCTOR_API_NAME;
641    }
642    methodInfo.setApiName(methodName);
643    methodInfo.setIsRequired(!methodNode.questionToken ? true : false);
644    methodNode.typeParameters?.forEach((typeParameter: ts.TypeParameterDeclaration) => {
645      methodInfo.setGenericInfo(NodeProcessorHelper.processGenericity(typeParameter));
646    });
647    const callForm: string = methodNode.getText().replace(/export\s+|declare\s+|function\s+|\r\n|\;/g, '');
648    methodInfo.setCallForm(callForm);
649    if (methodNode.type && ts.SyntaxKind.VoidKeyword !== methodNode.type.kind) {
650      const returnValues: string[] = NodeProcessorHelper.processDataType(methodNode.type);
651      methodInfo.setReturnValue(returnValues);
652      methodInfo.setReturnValueType(methodNode.type.kind);
653      NodeProcessorHelper.processFunctionTypeNode(methodNode.type, methodInfo, new ParamInfo(ApiType.PARAM), false);
654    }
655    for (let i = 0; i < methodNode.parameters.length; i++) {
656      const param: ts.ParameterDeclaration = methodNode.parameters[i];
657      const paramInfo: ParamInfo = NodeProcessorHelper.processParam(param, methodInfo);
658      methodInfo.addParam(paramInfo);
659    }
660    if (!ts.isCallSignatureDeclaration(methodNode) && !ts.isConstructSignatureDeclaration(methodNode)) {
661      ModifierHelper.processModifiers(methodNode.modifiers, methodInfo);
662    }
663    return methodInfo;
664  }
665
666  /**
667   * 处理方法入参
668   *
669   * @param { ts.ParameterDeclaration } param 参数节点
670   * @param { MethodInfo } methodInfo MethodInfo对象
671   * @returns { ParamInfo } 返回处理后的ParamInfo对象
672   */
673  static processParam(param: ts.ParameterDeclaration, methodInfo: MethodInfo): ParamInfo {
674    const paramInfo: ParamInfo = new ParamInfo(ApiType.PARAM);
675    paramInfo.setApiName(param.name.getText());
676    paramInfo.setIsRequired(!param.questionToken ? true : false);
677    paramInfo.setDefinedText(param.getText());
678    paramInfo.setParamType(param.type?.kind);
679    if (param.type === undefined) {
680      return paramInfo;
681    }
682    let typeMapValue: string | undefined = undefined;
683    NodeProcessorHelper.processFunctionTypeNode(param.type, methodInfo, paramInfo, true);
684    if (ts.isLiteralTypeNode(param.type)) {
685      typeMapValue = typeMap.get(param.type.literal.kind);
686    } else if (ts.isFunctionTypeNode(param.type)) {
687      const methodApiInfo: MethodInfo = NodeProcessorHelper.processMethod(param.type, methodInfo);
688      paramInfo.setMethodApiInfo(methodApiInfo);
689    }
690    paramInfo.setType(NodeProcessorHelper.processDataType(param.type));
691    return paramInfo;
692  }
693
694  /**
695   * 根据node节点获取当前文件名称
696   *
697   * @param {ts.Node} node
698   * @return {string} 文件名称
699   */
700  static getFilePathFromNode(node: ts.Node): string {
701    if (ts.isSourceFile(node)) {
702      return node.fileName;
703    } else {
704      return NodeProcessorHelper.getFilePathFromNode(node.parent);
705    }
706  }
707
708  /**
709   * 设置SymbolOfTypeReferenceMap对象
710   *
711   * @param {string} filePath 文件路径
712   * @param {ts.TypeReferenceNode} tsNode 文件中的typeReference
713   * @param {ts.Symbol} symbol typereference对应symbol
714   */
715  static setSymbolOfTypeReferenceMap(filePath: string, tsNode: ts.TypeReferenceNode, symbol: ts.Symbol): void {
716    if (!NodeProcessorHelper.symbolOfTypeReferenceMap.has(filePath)) {
717      NodeProcessorHelper.symbolOfTypeReferenceMap.set(filePath, new Map<string, ts.Symbol>());
718    }
719    const typeSymbolMap: Map<string, ts.Symbol> | undefined =
720      NodeProcessorHelper.symbolOfTypeReferenceMap.get(filePath);
721    if (!typeSymbolMap) {
722      return;
723    }
724    if (!typeSymbolMap.has(tsNode.getFullText().trim())) {
725      typeSymbolMap.set(tsNode.getFullText().trim(), symbol);
726    }
727  }
728
729  /**
730   * 从symbolOfTypeReferenceMap获取值
731   *
732   * @param {string} filePath 文件路径
733   * @param {ts.TypeReferenceNode} tsNode 文件中的typeReference
734   * @return {(ts.Symbol | undefined)} symbol值
735   */
736  static getSymbolOfTypeReferenceMap(filePath: string, tsNode: ts.TypeReferenceNode): ts.Symbol | undefined {
737    const fileSymbolMap: Map<string, ts.Symbol> | undefined =
738      NodeProcessorHelper.symbolOfTypeReferenceMap.get(filePath);
739    if (!fileSymbolMap) {
740      return undefined;
741    }
742    const typeSymbol: ts.Symbol | undefined = fileSymbolMap.get(tsNode.getFullText().trim());
743    if (!typeSymbol) {
744      return undefined;
745    }
746    return typeSymbol;
747  }
748
749  /**
750   * 处理方法入参的类型、联合类型时会将多个类型遍历传入
751   * 引用类型获取对应文件中的jsdoc
752   * 匿名类型获取属性的doc信息
753   *
754   * @param { ts.TypeNode } typeNode 参数类型
755   * @param { MethodInfo } methodInfo MethodInfo对象
756   * @param { ParamInfo } paramInfo ParamInfo对象
757   * @param { boolean } [isParam = true] 是否是参数的type,
758   * true:类型为参数(入参)的数据
759   * false:类型为返回值(出参)的数据
760   */
761  static processFunctionTypeNode(
762    typeNode: ts.TypeNode | undefined,
763    methodInfo: MethodInfo | PropertyInfo,
764    paramInfo: ParamInfo,
765    isParam: boolean = true
766  ): void {
767    if (NodeProcessorHelper.stopRecursion) {
768      return;
769    }
770    if (!typeNode) {
771      return;
772    }
773    if (ts.isTypeLiteralNode(typeNode)) {
774      NodeProcessorHelper.processFunctionTypeObject(typeNode, methodInfo, paramInfo, isParam);
775    } else if (ts.isUnionTypeNode(typeNode)) {
776      typeNode.types.forEach((type: ts.TypeNode) => {
777        NodeProcessorHelper.processFunctionTypeNode(type, methodInfo, paramInfo, isParam);
778      });
779    }
780    if (!ts.isTypeReferenceNode(typeNode)) {
781      return;
782    }
783    NodeProcessorHelper.processFunctionTypeReference(typeNode, methodInfo, paramInfo, isParam);
784  }
785
786  /**
787   * 处理方法引用类型
788   *
789   * @param { ts.TypeNode } typeNode 参数类型
790   * @param { MethodInfo } methodInfo MethodInfo对象
791   * @param { ParamInfo } paramInfo ParamInfo对象
792   * @param { boolean } [isParam = true] 是否是参数的type,
793   * true:类型为参数(入参)的数据
794   * false:类型为返回值(出参)的数据
795   */
796  static processFunctionTypeReference(
797    typeNode: ts.TypeReferenceNode,
798    methodInfo: MethodInfo | PropertyInfo,
799    paramInfo: ParamInfo,
800    isParam: boolean = true
801  ): void {
802    let typeNodeName: string = '';
803    const typeArguments: ts.NodeArray<ts.TypeNode> | undefined = typeNode.typeArguments;
804    typeArguments?.forEach((typeArgument: ts.TypeNode) => {
805      NodeProcessorHelper.processFunctionTypeNode(typeArgument, methodInfo, paramInfo, isParam);
806    });
807    if (ts.isIdentifier(typeNode.typeName)) {
808      typeNodeName = typeNode.typeName.escapedText.toString();
809    } else {
810      typeNodeName = typeNode.typeName.right.escapedText.toString();
811    }
812    if (NodeProcessorHelper.typeReferenceFileMap.has(typeNodeName)) {
813      const apiInfo: ApiInfo = NodeProcessorHelper.typeReferenceFileMap.get(typeNodeName)!;
814      if (isParam) {
815        paramInfo.addTypeLocations(apiInfo);
816      } else {
817        methodInfo.addTypeLocations(apiInfo);
818      }
819      return;
820    }
821    try {
822      const tsProgram: ts.Program = parserParam.getTsProgram();
823      const typeChecker: ts.TypeChecker = tsProgram.getTypeChecker();
824      const currentTypeSymbol: ts.Symbol | undefined = typeChecker.getSymbolAtLocation(typeNode.typeName);
825      if (!currentTypeSymbol) {
826        return;
827      }
828      const declarations: ts.Declaration[] | undefined = currentTypeSymbol.declarations;
829      if (!declarations) {
830        return;
831      }
832      const declaration: ts.Declaration = declarations[0];
833      const currentApiMap: FileInfoMap = new Map();
834      NodeProcessorHelper.processNode(declaration, currentApiMap, methodInfo, true);
835      NodeProcessorHelper.stopRecursion = false;
836      if (currentApiMap.has(typeNodeName)) {
837        const currentMap: ApiInfosMap = currentApiMap.get(typeNodeName) as ApiInfosMap;
838        const baseApiInfo: ApiInfo[] = currentMap.get(StringConstant.SELF) as ApiInfo[];
839        const apiInfo: ApiInfo = baseApiInfo[0];
840        NodeProcessorHelper.typeReferenceFileMap.set(typeNodeName, apiInfo);
841        if (!apiInfo) {
842          return;
843        }
844        if (isParam) {
845          paramInfo.addTypeLocations(apiInfo);
846        } else {
847          methodInfo.addTypeLocations(apiInfo);
848        }
849      }
850    } catch (error) {
851    } finally {
852    }
853  }
854
855  /**
856   * 处理方法入参的匿名类型
857   * 将匿名类型的每个属性的doc存储
858   *
859   * @param {ts.TypeLiteralNode} typeObject 匿名对象
860   * @param {MethodInfo} methodInfo MethodInfo对象
861   * @param {ParamInfo} paramInfo ParamInfo对象
862   * @param { boolean } [isParam = true] 是否是参数的type,
863   * true:类型为参数(入参)的数据
864   * false:类型为返回值(出参)的数据
865   */
866  static processFunctionTypeObject(
867    typeObject: ts.TypeLiteralNode,
868    methodInfo: MethodInfo | PropertyInfo,
869    paramInfo: ParamInfo,
870    isParam: boolean = true
871  ): void {
872    const fileTags: FileTag = methodInfo.getKitInfoFromParent(methodInfo);
873    typeObject.members.forEach((member: ts.TypeElement) => {
874      const propertyInfo: PropertyInfo = NodeProcessorHelper.processPropertySigAndDec(member, methodInfo);
875      if (isParam) {
876        paramInfo.addObjLocations(propertyInfo);
877      } else {
878        methodInfo.addObjLocations(propertyInfo);
879      }
880    });
881  }
882
883  /**
884   * 处理数据类型,因为会存在联合类型的情况
885   *
886   * @param { string } dataType 类型信息的字符串
887   * @returns { string[] } 返回处理后的数组
888   */
889  static processDataType(dataType: ts.TypeNode | undefined | ts.Expression): string[] {
890    const typeArr: string[] = [];
891    if (!dataType) {
892      return typeArr;
893    }
894    if (ts.isUnionTypeNode(dataType)) {
895      dataType.types.forEach((type: ts.TypeNode) => {
896        typeArr.push(type.getText());
897      });
898      return typeArr;
899    }
900    typeArr.push(dataType.getText());
901    return typeArr;
902  }
903
904  /**
905   * 处理type关键字定义的节点TypeAliasDeclaration,包含定义别名(包含联合类型)以及自定义对象(归为interface)
906   *
907   * @param { ts.Node } node 当前节点
908   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
909   * @returns { ApiInfo } 返回处理后的ApiInfo对象
910   */
911  static TypeAliasDeclaration(node: ts.Node, parentApi: BasicApiInfo): ApiInfo {
912    const typeAliasNode: ts.TypeAliasDeclaration = node as ts.TypeAliasDeclaration;
913    if (typeAliasNode.type.kind === ts.SyntaxKind.TypeLiteral) {
914      return NodeProcessorHelper.processTypeInterface(typeAliasNode, parentApi);
915    } else {
916      return NodeProcessorHelper.processTypeAlias(typeAliasNode, parentApi);
917    }
918  }
919
920  /**
921   * 处理type关键字定义的对象,如type sample = { count: number }
922   *
923   * @param { ts.TypeAliasDeclaration } node 当前节点
924   * @returns { InterfaceInfo } 返回处理后的InterfaceInfo对象
925   */
926  static processTypeInterface(node: ts.TypeAliasDeclaration, parentApi: BasicApiInfo): InterfaceInfo {
927    const interfaceInfo: InterfaceInfo = new InterfaceInfo(ApiType.INTERFACE, node, parentApi);
928    interfaceInfo.setApiName(node.name.getText());
929    interfaceInfo.setDefinedText(interfaceInfo.getApiName());
930    ModifierHelper.processModifiers(node.modifiers, interfaceInfo);
931    return interfaceInfo;
932  }
933
934  /**
935   * 处理type关键字定义的类型别名,包含联合类型
936   *
937   * @param { ts.Node } node 当前节点
938   * @returns { TypeAliasInfo } 返回处理后的TypeAliasInfo对象
939   */
940  static processTypeAlias(node: ts.TypeAliasDeclaration, parentApi: BasicApiInfo): TypeAliasInfo {
941    const typeNameMap: Map<number, string> = new Map([
942      [ts.SyntaxKind.UnionType, TypeAliasType.UNION_TYPE],
943      [ts.SyntaxKind.TypeLiteral, TypeAliasType.OBJECT_TYPE],
944      [ts.SyntaxKind.TupleType, TypeAliasType.TUPLE_TYPE],
945      [ts.SyntaxKind.TypeReference, TypeAliasType.REFERENCE_TYPE],
946    ]);
947    const typeAliasInfo: TypeAliasInfo = new TypeAliasInfo(ApiType.TYPE_ALIAS, node, parentApi);
948    typeAliasInfo.setApiName(node.name.getText());
949    const typeName: string | undefined = typeNameMap.get(node.type.kind);
950    if (typeName) {
951      typeAliasInfo.setTypeName(typeName);
952    }
953    let nodeType: ts.TypeNode = node.type;
954    if (ts.isFunctionTypeNode(nodeType)) {
955      const typeParameters = nodeType.parameters;
956      typeParameters.forEach((typeParameter: ts.ParameterDeclaration) => {
957        const typeParamInfo: ParamInfo = NodeProcessorHelper.processParam(
958          typeParameter,
959          new MethodInfo(ApiType.METHOD, node, parentApi)
960        );
961        typeAliasInfo.setParamInfos(typeParamInfo);
962      });
963      typeAliasInfo.setReturnType(NodeProcessorHelper.processDataType(nodeType.type));
964      typeAliasInfo.setTypeIsFunction(true);
965    } else if (ts.isTypeLiteralNode(nodeType)) {
966      nodeType.members.forEach((member: ts.TypeElement) => {
967        const propertyInfo: PropertyInfo = NodeProcessorHelper.processPropertySigAndDec(member, typeAliasInfo);
968        typeAliasInfo.setTypeLiteralApiInfos(propertyInfo);
969      });
970      typeAliasInfo.setTypeIsObject(true);
971    }
972
973    typeAliasInfo.setDefinedText(node.getText());
974    ModifierHelper.processModifiers(node.modifiers, typeAliasInfo);
975    typeAliasInfo.addType(NodeProcessorHelper.processDataType(node.type));
976    return typeAliasInfo;
977  }
978
979  /**
980   * 处理VariableStatement节点,根据节点定义的情况会将其处理为常量或属性
981   *
982   * @param { ts.Node } node 当前节点
983   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
984   * @returns { BasicApiInfo } 返回处理后的节点对象
985   */
986  static processVariableStat(node: ts.Node, parentApi: BasicApiInfo): BasicApiInfo {
987    const variableNode: ts.VariableStatement = node as ts.VariableStatement;
988    const definedText: string = variableNode.getText();
989    const declarationNode: ts.VariableDeclaration = variableNode.declarationList.declarations[0];
990    const REG_DECLARE_CONSTANT: RegExp = /declare\s+const/;
991    const REG_COMPONENT: RegExp = /[a-zA-Z]+(Attribute|Interface)/;
992    // declare const
993    let variableType: string = '';
994    let value: string = '';
995    if (declarationNode.type) {
996      if (ts.isLiteralTypeNode(declarationNode.type)) {
997        const typeOfLiteral: string | undefined = typeMap.get(declarationNode.type.literal.kind);
998        variableType = typeOfLiteral ? typeOfLiteral : '';
999        value = declarationNode.type.literal.getText().replace(NodeProcessorHelper.regQuotation, '$1');
1000      } else {
1001        variableType = declarationNode.type.getText();
1002      }
1003    }
1004    if (REG_DECLARE_CONSTANT.test(variableNode.getText()) && REG_COMPONENT.test(variableType)) {
1005      return NodeProcessorHelper.processDeclareConstant(variableNode, definedText, variableType, parentApi);
1006    }
1007    // 节点有初始化值,如const a = 1,归为常量
1008    if (declarationNode.initializer) {
1009      const constantValue: string = declarationNode.initializer.getText();
1010      return NodeProcessorHelper.processConstant(variableNode, definedText, constantValue, parentApi);
1011    }
1012    // 节点的类型为字面量值,如const a: 111,归为常量
1013    const typeNode: ts.TypeNode | undefined = declarationNode.type;
1014    if (typeNode && ts.isLiteralTypeNode(typeNode)) {
1015      const constantValue: string = typeNode.getText();
1016      return NodeProcessorHelper.processConstant(variableNode, definedText, constantValue, parentApi);
1017    }
1018    // 除了上述两种常量的情况,其他归为属性
1019    return NodeProcessorHelper.processVaribleProperty(variableNode, definedText, parentApi);
1020  }
1021
1022  /**
1023   * 处理常量节点
1024   *
1025   * @param { ts.VariableDeclaration } node 当前节点
1026   * @param { string } definedText 节点定义的字符串
1027   * @param { string } value 常量的取值
1028   * @param { BasicApiInfo } parentApi 父节点解析后的对象
1029   * @returns { ConstantInfo } 返回解析后的常量对象
1030   */
1031  static processConstant(
1032    node: ts.VariableStatement,
1033    definedText: string,
1034    value: string,
1035    parentApi: BasicApiInfo
1036  ): ConstantInfo {
1037    const declarationNode: ts.VariableDeclaration = node.declarationList.declarations[0] as ts.VariableDeclaration;
1038    const constantInfo: ConstantInfo = new ConstantInfo(ApiType.CONSTANT, node, parentApi);
1039    constantInfo.setDefinedText(definedText);
1040    constantInfo.setApiName(declarationNode.name.getText());
1041    constantInfo.setValue(value);
1042    return constantInfo;
1043  }
1044
1045  /**
1046   * 处理declare常量节点
1047   *
1048   * @param { ts.VariableDeclaration } node 当前节点
1049   * @param { string } definedText 节点定义的字符串
1050   * @param { string } value 常量的取值
1051   * @param { BasicApiInfo } parentApi 父节点解析后的对象
1052   * @returns { ConstantInfo } 返回解析后的常量对象
1053   */
1054  static processDeclareConstant(
1055    node: ts.VariableStatement,
1056    definedText: string,
1057    value: string,
1058    parentApi: BasicApiInfo
1059  ): ConstantInfo {
1060    const declarationNode: ts.VariableDeclaration = node.declarationList.declarations[0] as ts.VariableDeclaration;
1061    const constantInfo: ConstantInfo = new ConstantInfo(ApiType.DECLARE_CONST, node, parentApi);
1062    constantInfo.setDefinedText(definedText);
1063    constantInfo.setApiName(declarationNode.name.getText());
1064    constantInfo.setValue(value);
1065    return constantInfo;
1066  }
1067
1068  /**
1069   * 处理VariableDeclaration节点类型的属性节点
1070   *
1071   * @param { ts.VariableDeclaration } node 当前节点
1072   * @param { string } definedText 节点定义的字符串
1073   * @param { BasicApiInfo } parentApi 父节点解析后的对象
1074   * @returns { ConstantInfo } 返回解析后的属性对象
1075   */
1076  static processVaribleProperty(
1077    node: ts.VariableStatement,
1078    definedText: string,
1079    parentApi: BasicApiInfo
1080  ): PropertyInfo {
1081    const declarationNode: ts.VariableDeclaration = node.declarationList.declarations[0] as ts.VariableDeclaration;
1082    const propertyInfo: PropertyInfo = new PropertyInfo(ApiType.PROPERTY, node, parentApi);
1083    propertyInfo.setDefinedText(definedText);
1084    propertyInfo.setApiName(declarationNode.name.getText());
1085    propertyInfo.addType(NodeProcessorHelper.processDataType(declarationNode.type));
1086    propertyInfo.setIsRequired(true);
1087    propertyInfo.setTypeKind(declarationNode?.type?.kind);
1088    if (StringUtils.hasSubstring(definedText, StringConstant.CONST_KEY_WORD)) {
1089      propertyInfo.setIsReadOnly(true);
1090    }
1091    return propertyInfo;
1092  }
1093}
1094
1095/**
1096 * 处理export readonly、static等修饰关键字
1097 */
1098export class ModifierHelper {
1099  static setIsStatic(apiInfo: BasicApiInfo): void {
1100    const propertyOrMethodInfo: PropertyInfo | MethodInfo = apiInfo as PropertyInfo | MethodInfo;
1101    propertyOrMethodInfo.setIsStatic(true);
1102  }
1103
1104  static setIsReadonly(apiInfo: BasicApiInfo): void {
1105    const propertyInfo: PropertyInfo = apiInfo as PropertyInfo;
1106    if (propertyInfo.setIsReadOnly) {
1107      propertyInfo.setIsReadOnly(true);
1108    }
1109  }
1110
1111  static setIsExport(apiInfo: BasicApiInfo): void {
1112    apiInfo.setIsExport(true);
1113  }
1114
1115  static processModifiers(modifiers: ts.NodeArray<ts.Modifier> | undefined, apiInfo: BasicApiInfo): void {
1116    let definedText: string = '';
1117    if (modifiers) {
1118      modifiers.forEach((modifier: ts.Modifier) => {
1119        if (containerApiTypes.has(apiInfo.apiType) && !ts.isDecorator(modifier)) {
1120          definedText += ` ${modifier.getText()}`;
1121        }
1122
1123        const setModifier: ModifierProcessorInterface | undefined = modifierProcessorMap.get(modifier.kind);
1124        setModifier ? setModifier(apiInfo) : undefined;
1125      });
1126    }
1127    if (containerApiTypes.has(apiInfo.apiType)) {
1128      definedText += ` ${apiInfo.getApiType().toLowerCase()} ${apiInfo.getApiName()}`;
1129      apiInfo.setDefinedText(definedText.trim());
1130    }
1131  }
1132}
1133
1134export const nodeProcessorMap: Map<ts.SyntaxKind, NodeProcessorInterface> = new Map([
1135  [ts.SyntaxKind.ExportAssignment, NodeProcessorHelper.processExportAssignment],
1136  [ts.SyntaxKind.ExportDeclaration, NodeProcessorHelper.processExportDeclaration],
1137  // [ts.SyntaxKind.ImportEqualsDeclaration, NodeProcessorHelper.processImportEqualsDeclaration],
1138  [ts.SyntaxKind.ImportDeclaration, NodeProcessorHelper.processImportInfo],
1139  [ts.SyntaxKind.VariableStatement, NodeProcessorHelper.processVariableStat],
1140  [ts.SyntaxKind.MethodDeclaration, NodeProcessorHelper.processMethod],
1141  [ts.SyntaxKind.MethodSignature, NodeProcessorHelper.processMethod],
1142  [ts.SyntaxKind.FunctionDeclaration, NodeProcessorHelper.processMethod],
1143  [ts.SyntaxKind.Constructor, NodeProcessorHelper.processMethod],
1144  [ts.SyntaxKind.ConstructSignature, NodeProcessorHelper.processMethod],
1145  [ts.SyntaxKind.CallSignature, NodeProcessorHelper.processMethod],
1146  [ts.SyntaxKind.PropertyDeclaration, NodeProcessorHelper.processPropertySigAndDec],
1147  [ts.SyntaxKind.PropertySignature, NodeProcessorHelper.processPropertySigAndDec],
1148  [ts.SyntaxKind.EnumMember, NodeProcessorHelper.processEnumValue],
1149  [ts.SyntaxKind.EnumDeclaration, NodeProcessorHelper.processEnum],
1150  [ts.SyntaxKind.TypeAliasDeclaration, NodeProcessorHelper.processTypeAlias],
1151  [ts.SyntaxKind.ClassDeclaration, NodeProcessorHelper.processClass],
1152  [ts.SyntaxKind.InterfaceDeclaration, NodeProcessorHelper.processInterface],
1153  [ts.SyntaxKind.ModuleDeclaration, NodeProcessorHelper.processBaseModule],
1154  [ts.SyntaxKind.StructDeclaration, NodeProcessorHelper.processStruct],
1155]);
1156
1157export const modifierProcessorMap: Map<ts.SyntaxKind, ModifierProcessorInterface> = new Map([
1158  [ts.SyntaxKind.ConstKeyword, ModifierHelper.setIsReadonly],
1159  [ts.SyntaxKind.ReadonlyKeyword, ModifierHelper.setIsReadonly],
1160  [ts.SyntaxKind.StaticKeyword, ModifierHelper.setIsStatic],
1161  [ts.SyntaxKind.ExportKeyword, ModifierHelper.setIsExport],
1162]);
1163
1164export const typeMap: Map<ts.SyntaxKind, string> = new Map([
1165  [ts.SyntaxKind.StringLiteral, 'string'],
1166  [ts.SyntaxKind.NumericLiteral, 'number'],
1167]);
1168