• 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 _ from 'lodash';
18
19import {
20  ApiInfo,
21  ApiType,
22  BasicApiInfo,
23  ClassInfo,
24  ConstantInfo,
25  ContainerApiInfo,
26  EnumInfo,
27  EnumValueInfo,
28  ExportDeclareInfo,
29  ExportDefaultInfo,
30  ImportInfo,
31  InterfaceInfo,
32  MethodInfo,
33  MethodType,
34  ModifierProcessorInterface,
35  ModuleInfo,
36  NamespaceInfo,
37  NodeProcessorInterface,
38  ParamInfo,
39  PropertyInfo,
40  PropertyNode,
41  ReferenceInfo,
42  StructInfo,
43  TypeAliasType,
44  TypeAliasInfo,
45  containerApiTypes,
46} from '../../typedef/parser/ApiInfoDefination';
47import { StringUtils } from '../../utils/StringUtils';
48import { StringConstant, EventConstant } from '../../utils/Constant';
49import { BasicApiInfoMap, ApiInfosMap, FileInfoMap } from './parser';
50
51export class NodeProcessorHelper {
52  // 如果是字符串的话,会出现单双引号重复的情况
53  static regQuotation: RegExp = /^[\'|\"](.*)[\'|\"]$/;
54
55  static processReference(
56    sourceFile: ts.SourceFile,
57    parentMap: Map<string, object>,
58    parentApiInfo: BasicApiInfo
59  ): void {
60    const references: ReferenceInfo[] = [];
61    sourceFile.referencedFiles.forEach((referencedFile: ts.FileReference) => {
62      const referenceInfo: ReferenceInfo = new ReferenceInfo(ApiType.REFERENCE_FILE, sourceFile, parentApiInfo);
63      referenceInfo.setApiName(ApiType.REFERENCE_FILE);
64      referenceInfo.setPathName(referencedFile.fileName);
65      references.push(referenceInfo);
66    });
67    if (references.length === 0) {
68      return;
69    }
70    const currentMap: Map<string, object> = new Map();
71    currentMap.set(StringConstant.SELF, references);
72    parentMap.set(StringConstant.REFERENCE, currentMap);
73  }
74  /**
75   * 根据节点类型处理节点的方法,处理的主流程
76   *
77   * @param { ts.Node } node 当前处理的节点
78   * @param { FileInfoMap } parentMap 父节点建立的map对象
79   * @param { BasicApiInfo } parentApiInfo 父节点解析后的对象
80   */
81  static processNode(node: ts.Node, parentMap: FileInfoMap | ApiInfosMap, parentApiInfo: BasicApiInfo): void {
82    const nodeProcessor: NodeProcessorInterface | undefined = nodeProcessorMap.get(node.kind);
83    if (!nodeProcessor) {
84      return;
85    }
86    const apiInfo: BasicApiInfo = nodeProcessor(node, parentApiInfo);
87    const currentMap: BasicApiInfoMap = NodeProcessorHelper.setApiInfo(apiInfo, parentMap, node);
88    const childNodes: ts.NodeArray<ts.Node> | undefined = NodeProcessorHelper.getChildNodes(node);
89    if (!childNodes) {
90      return;
91    }
92    childNodes.forEach((cNode: ts.Node) => {
93      NodeProcessorHelper.processNode(cNode, currentMap as ApiInfosMap, apiInfo);
94    });
95  }
96
97  /**
98   * 将解析后的api添加到当前的map中,会对某些特殊情况进行调整
99   *
100   * @param { BasicApiInfo } apiInfo 当前api的解析对象
101   * @param { Map<string, object> } parentMap 当前父节点所在的map
102   * @param { ts.Node } node 当前apinode节点
103   * @returns { Map<string, object> } 返回当前节点所属的map
104   */
105  static setApiInfo(apiInfo: BasicApiInfo, parentMap: FileInfoMap | ApiInfosMap, node: ts.Node): BasicApiInfoMap {
106    if (apiInfo.getApiType() !== ApiType.METHOD) {
107      return NodeProcessorHelper.setSingleApiInfo(apiInfo, parentMap);
108    }
109    let apiInfos: BasicApiInfo[] = [];
110    // 处理on/off
111    apiInfos = NodeProcessorHelper.processOnOrOffMethod(apiInfo, node);
112    // 处理promise/asynccallback
113    NodeProcessorHelper.processAsyncMethod(apiInfos);
114    let currentMap: BasicApiInfoMap = new Map();
115    apiInfos.forEach((apiInfo: BasicApiInfo) => {
116      currentMap = NodeProcessorHelper.setSingleApiInfo(apiInfo, parentMap);
117    });
118    return currentMap;
119  }
120
121  /**
122   *  将解析后的单个api添加到当前的map中,不允许对apiInfo进行二次修改
123   *
124   * @param { BasicApiInfo } apiInfo 当前api的解析对象
125   * @param { ApiInfosMap } parentMap  当前父节点所在的map
126   * @return { BasicApiInfoMap } 返回当前节点所属的map
127   */
128  static setSingleApiInfo(apiInfo: BasicApiInfo, parentMap: FileInfoMap | ApiInfosMap): BasicApiInfoMap {
129    const apiName: string = apiInfo.getApiName();
130    const parentApiInfo: BasicApiInfo | undefined = apiInfo.getParentApi();
131    if (parentApiInfo && containerApiTypes.has(parentApiInfo.apiType)) {
132      const containerApiInfo: ContainerApiInfo = parentApiInfo as ContainerApiInfo;
133      containerApiInfo.addChildApi(apiInfo);
134    }
135    if (parentMap.has(apiName)) {
136      //同名方法处理
137      const currentMap: BasicApiInfoMap = parentMap.get(apiName) as BasicApiInfoMap;
138      const methodInfos: BasicApiInfo[] = currentMap.get(StringConstant.SELF) as BasicApiInfo[];
139      methodInfos.push(apiInfo);
140      return currentMap;
141    }
142    const apiInfos: BasicApiInfo[] = [];
143    apiInfos.push(apiInfo);
144    const currentMap: BasicApiInfoMap = new Map();
145    currentMap.set(StringConstant.SELF, apiInfos);
146    parentMap.set(apiName, currentMap);
147    return currentMap;
148  }
149
150  /**
151   * 处理方法节点中方法名称为on或者off的方法
152   *
153   * 第一个参数只要是字符串的字面量就将apiName修改为on_string,联合类型进行分开解析
154   * @param {BasicApiInfo} apiInfo 当前api的解析对象
155   * @param {ts.Node} node 当前apinode节点
156   * @return {BasicApiInfo[]} 解析完on/off的apiInfo数组
157   */
158  static processOnOrOffMethod(apiInfo: BasicApiInfo, node: ts.Node): BasicApiInfo[] {
159    const apiInfos: BasicApiInfo[] = [];
160    const type: ts.TypeNode | undefined = NodeProcessorHelper.getOnOrOffMethodFirstParamType(
161      apiInfo,
162      node as MethodType
163    );
164    if (type === undefined) {
165      apiInfos.push(apiInfo);
166      return apiInfos;
167    }
168    const literal = (type as ts.LiteralTypeNode).literal;
169    if (type.kind === ts.SyntaxKind.LiteralType && ts.isStringLiteral(literal)) {
170      const text: string = literal.getText();
171      apiInfo.setApiName(`${apiInfo.getApiName()}_${text.substring(1, text.length - 1)}`);
172    } else if (type.kind === ts.SyntaxKind.UnionType) {
173      const types: ts.NodeArray<ts.TypeNode> = (type as ts.UnionTypeNode).types;
174      types.forEach((item: ts.TypeNode) => {
175        if (ts.isLiteralTypeNode(item) && ts.isStringLiteral(item.literal)) {
176          const text: string = item.literal.getText();
177          const cloneApiInfo: BasicApiInfo = _.cloneDeep(apiInfo);
178          cloneApiInfo.setParentApi(apiInfo.getParentApi());
179          cloneApiInfo.setApiName(`${apiInfo.getApiName()}_${text.substring(1, text.length - 1)}`);
180          apiInfos.push(cloneApiInfo);
181        }
182      });
183    } else if (type.kind === ts.SyntaxKind.StringKeyword) {
184      apiInfo.setApiName(`${apiInfo.getApiName()}_string`);
185    } else if (type.kind === ts.SyntaxKind.BooleanKeyword) {
186      apiInfo.setApiName(`${apiInfo.getApiName()}_boolean`);
187    }
188    if (apiInfos.length === 0) {
189      apiInfos.push(apiInfo);
190    }
191    return apiInfos;
192  }
193
194  /**
195   * 获取on/off方法第一个参数的类型
196   *
197   * @param {BasicApiInfo} apiInfo 当前api的解析对象
198   * @param {MethodType} methodNode 当前apinode节点
199   * @return {(ts.TypeNode | undefined)} 满足条件的on/off第一个参数的类型
200   */
201  static getOnOrOffMethodFirstParamType(apiInfo: BasicApiInfo, methodNode: MethodType): ts.TypeNode | undefined {
202    const subscriotionSet: Set<string> = new Set(EventConstant.eventNameList);
203    if (!subscriotionSet.has(apiInfo.getApiName())) {
204      return undefined;
205    }
206    if (methodNode.parameters.length === 0) {
207      return undefined;
208    }
209    const firstParam: ts.ParameterDeclaration = methodNode.parameters[0];
210    return firstParam.type;
211  }
212
213  /**
214   * 处理AsyncCallback和Promise,将符合规则的apiName修改为apiName(AsyncCallback/Promise215   *
216   * 1、返回参数是Promise类型
217   *
218   * 2、参数中有类型为AsyncCallback的参数
219   *
220   * @param {BasicApiInfo[]} apiInfos 需要处理的apiInfo集合
221   */
222  static processAsyncMethod(apiInfos: BasicApiInfo[]): void {
223    apiInfos.forEach((apiInfo: BasicApiInfo) => {
224      const methodInfo: MethodInfo = apiInfo as MethodInfo;
225      const returnValues: string[] = methodInfo.getReturnValue();
226      if (returnValues.length === 1 && returnValues[0].startsWith(StringConstant.PROMISE_METHOD_KEY)) {
227        methodInfo.setSync(StringConstant.PROMISE_METHOD_KEY_CHANGE);
228        return;
229      }
230      const params: ParamInfo[] = methodInfo.getParams();
231      for (let i = params.length - 1; i >= 0; i--) {
232        const paramType: string[] = params[i].getType();
233        if (paramType.length === 1 && paramType[0].startsWith(StringConstant.ASYNC_CALLBACK_METHOD_KEY)) {
234          methodInfo.setSync(StringConstant.ASYNC_CALLBACK_METHOD_KEY_CHANGE);
235          return;
236        }
237      }
238    });
239  }
240
241  /**
242   * 获取interface、class、namespace,struct以及type定义的对象的子节点
243   *
244   * @param { ts.Node } node 当前节点
245   * @returns { ts.NodeArray<ts.Node> | undefined } 返回当前节点的子节点
246   */
247  static getChildNodes(node: ts.Node): ts.NodeArray<ts.Node> | undefined {
248    if (
249      ts.isInterfaceDeclaration(node) ||
250      ts.isClassDeclaration(node) ||
251      ts.isEnumDeclaration(node) ||
252      ts.isStructDeclaration(node)
253    ) {
254      return node.members;
255    }
256    if (ts.isTypeAliasDeclaration(node) && ts.isTypeLiteralNode(node.type)) {
257      return node.type.members;
258    }
259    if (ts.isModuleDeclaration(node) && node.body && ts.isModuleBlock(node.body)) {
260      return node.body.statements;
261    }
262    return undefined;
263  }
264
265  /**
266   * 处理export default xxx节点
267   *
268   * @param { ts.Node } node 当前节点
269   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
270   * @returns { ExportDefaultInfo } 返回处理后得到的ExportDefaultInfo对象
271   */
272  static processExportAssignment(node: ts.Node, parentApi: BasicApiInfo): ExportDefaultInfo {
273    const exportDefaultInfo: ExportDefaultInfo = new ExportDefaultInfo(ApiType.EXPORT_DEFAULT, node, parentApi);
274    const exportDefaultNode: ts.ExportAssignment = node as ts.ExportAssignment;
275    exportDefaultInfo.setApiName(StringConstant.EXPORT_DEFAULT + exportDefaultNode.expression.getText());
276    exportDefaultInfo.setDefinedText(exportDefaultNode.getText());
277    ModifierHelper.processModifiers(exportDefaultNode.modifiers, exportDefaultInfo);
278    return exportDefaultInfo;
279  }
280
281  /**
282   * 处理export { xxx }节点
283   *
284   * @param { ts.Node } node 当前节点
285   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
286   * @returns { ExportDeclareInfo } 返回处理后得到的ExportDeclareInfoInfo对象
287   */
288  static processExportDeclaration(node: ts.Node, parentApi: BasicApiInfo): ExportDeclareInfo {
289    const exportDeclareInfo: ExportDeclareInfo = new ExportDeclareInfo(ApiType.EXPORT, node, parentApi);
290    const exportDeclarationNode: ts.ExportDeclaration = node as ts.ExportDeclaration;
291    const exportClause: ts.NamedExportBindings | undefined = exportDeclarationNode.exportClause;
292    if (!exportClause) {
293      //export * from 'test';
294      exportDeclareInfo.setApiName(
295        StringConstant.EXPORT +
296          (exportDeclarationNode.moduleSpecifier ? exportDeclarationNode.moduleSpecifier.getText() : '')
297      );
298    } else if (ts.isNamespaceExport(exportClause)) {
299      //export * as myTest from 'test';
300      exportDeclareInfo.setApiName(StringConstant.EXPORT + exportClause.name.getText());
301    } else if (ts.isNamedExports(exportClause)) {
302      // export { xxx , yyy  }
303      // export { xxx as x, yyy as y }
304      const exportValueNames: string[] = [];
305      exportClause.elements.forEach((element: ts.ExportSpecifier) => {
306        const exportValueType: string = element.propertyName ? element.propertyName.getText() : '';
307        const exportValueName: string = element.name.getText();
308        exportValueNames.push(exportValueName);
309        exportDeclareInfo.addExportValues(exportValueName, exportValueType);
310      });
311      exportDeclareInfo.setApiName(StringConstant.EXPORT + exportValueNames.join('_'));
312    }
313    exportDeclareInfo.setDefinedText(exportDeclarationNode.getText());
314    ModifierHelper.processModifiers(exportDeclarationNode.modifiers, exportDeclareInfo);
315    return exportDeclareInfo;
316  }
317
318  /**
319   * 处理 export import NetAddress = connection.NetAddress;
320   *
321   * @param { ts.Node } node 当前节点
322   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
323   * @returns { importInfo } 返回处理后得到的importInfo对象
324   */
325  static processImportEqualsDeclaration(node: ts.Node, parentApi: BasicApiInfo): ImportInfo {
326    const importInfo: ImportInfo = new ImportInfo(ApiType.EXPORT, node, parentApi);
327    return importInfo;
328  }
329
330  /**
331   * 处理import xxx from xxx 节点
332   *
333   * @param { ts.Node } node 当前节点
334   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
335   * @returns { ImportInfo } 返回处理后得到的ImportInfo对象
336   */
337  static processImportInfo(node: ts.Node, parentApi: BasicApiInfo): ImportInfo {
338    const importInfo: ImportInfo = new ImportInfo(ApiType.IMPORT, node, parentApi);
339    const importNode: ts.ImportDeclaration = node as ts.ImportDeclaration;
340    importInfo.setApiName(importNode.moduleSpecifier.getText());
341    importInfo.setImportPath(importNode.moduleSpecifier.getText());
342    importInfo.setDefinedText(importNode.getText());
343    ModifierHelper.processModifiers(importNode.modifiers, importInfo);
344    if (importNode.importClause === undefined) {
345      return importInfo;
346    }
347    const importClause: ts.ImportClause = importNode.importClause;
348    if (importClause.namedBindings && ts.isNamedImports(importClause.namedBindings)) {
349      importClause.namedBindings.elements.forEach((element: ts.ImportSpecifier) => {
350        const importValueType: string = element.propertyName ? element.propertyName.getText() : '';
351        const importValueName: string = element.name.getText();
352        importInfo.addImportValue(importValueName, importValueType);
353      });
354    } else {
355      const importValueName: string = importClause.name ? importClause.name.escapedText.toString() : '';
356      importInfo.addImportValue(importValueName, importValueName);
357    }
358    return importInfo;
359  }
360
361  /**
362   * 处理interface节点
363   *
364   * @param { ts.Node } node 当前节点
365   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
366   * @returns { InterfaceInfo } 返回处理后得到的InterfaceInfo对象
367   */
368  static processInterface(node: ts.Node, parentApi: BasicApiInfo): InterfaceInfo {
369    const interfaceDeclaration: ts.InterfaceDeclaration = node as ts.InterfaceDeclaration;
370    const interfaceInfo: InterfaceInfo = new InterfaceInfo(ApiType.INTERFACE, node, parentApi);
371    interfaceInfo.setApiName(interfaceDeclaration.name.getText());
372    ModifierHelper.processModifiers(interfaceDeclaration.modifiers, interfaceInfo);
373    if (interfaceDeclaration.heritageClauses === undefined) {
374      return interfaceInfo;
375    }
376    const parentClasses: string[] = [];
377    interfaceDeclaration.heritageClauses.forEach((value: ts.HeritageClause) => {
378      if (value.token === ts.SyntaxKind.ExtendsKeyword) {
379        value.types.forEach((value: ts.ExpressionWithTypeArguments) => {
380          parentClasses.push(value.getText());
381        });
382      }
383    });
384    interfaceInfo.setParentClasses(parentClasses);
385    return interfaceInfo;
386  }
387
388  /**
389   * 处理class节点
390   *
391   * @param { ts.Node } node 当前节点
392   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
393   * @returns { ClassInfo } 返回处理后得到的ClassInfo对象
394   */
395  static processClass(node: ts.Node, parentApi: BasicApiInfo): ClassInfo {
396    const classDeclaration: ts.ClassDeclaration = node as ts.ClassDeclaration;
397    const classInfo: ClassInfo = new ClassInfo(ApiType.CLASS, node, parentApi);
398    const className: string = classDeclaration.name ? classDeclaration.name.getText() : '';
399    classInfo.setApiName(className);
400    ModifierHelper.processModifiers(classDeclaration.modifiers, classInfo);
401    if (classDeclaration.heritageClauses === undefined) {
402      return classInfo;
403    }
404    const parentClasses: string[] = [];
405    classDeclaration.heritageClauses.forEach((value: ts.HeritageClause) => {
406      if (value.token === ts.SyntaxKind.ExtendsKeyword) {
407        value.types.forEach((value: ts.ExpressionWithTypeArguments) => {
408          parentClasses.push(value.getText());
409        });
410      }
411    });
412    classInfo.setParentClasses(parentClasses);
413    return classInfo;
414  }
415
416  /**
417   * 处理module节点,分为外部模块(module)和内部模块(namespace)
418   *
419   * @param { ts.Node } node 当前节点
420   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
421   * @returns { NamespaceInfo } 返回处理后得到的NamespaceInfo对象
422   */
423  static processBaseModule(node: ts.Node, parentApi: BasicApiInfo): NamespaceInfo {
424    const moduleDeclaration: ts.ModuleDeclaration = node as ts.ModuleDeclaration;
425    if (!ts.isIdentifier(moduleDeclaration.name)) {
426      return NodeProcessorHelper.processModule(node, parentApi);
427    }
428    return NodeProcessorHelper.processNamespace(node, parentApi);
429  }
430
431  /**
432   * 处理module节点-外部模块
433   *
434   * @param { ts.Node } node 当前节点
435   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
436   * @returns { ModuleInfo } 返回处理后得到的ModuleInfo对象
437   */
438  static processModule(node: ts.Node, parentApi: BasicApiInfo): ModuleInfo {
439    const moduleDeclaration: ts.ModuleDeclaration = node as ts.ModuleDeclaration;
440    const moduleInfo: ModuleInfo = new ModuleInfo(ApiType.MODULE, node, parentApi);
441    moduleInfo.setApiName(moduleDeclaration.name.getText());
442    ModifierHelper.processModifiers(moduleDeclaration.modifiers, moduleInfo);
443    return moduleInfo;
444  }
445
446  /**
447   * 处理namespace节点-内部模块
448   *
449   * @param { ts.Node } node 当前节点
450   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
451   * @returns { NamespaceInfo } 返回处理后得到的NamespaceInfo对象
452   */
453  static processNamespace(node: ts.Node, parentApi: BasicApiInfo): NamespaceInfo {
454    const moduleDeclaration: ts.ModuleDeclaration = node as ts.ModuleDeclaration;
455    const namespaceInfo: NamespaceInfo = new NamespaceInfo(ApiType.NAMESPACE, node, parentApi);
456    namespaceInfo.setApiName(moduleDeclaration.name.getText());
457    ModifierHelper.processModifiers(moduleDeclaration.modifiers, namespaceInfo);
458    return namespaceInfo;
459  }
460
461  /**
462   * 处理enum节点
463   *
464   * @param { ts.Node } node 当前节点
465   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
466   * @returns { EnumInfo } 返回处理后得到的EnumInfo对象
467   */
468  static processEnum(node: ts.Node, parentApi: BasicApiInfo): EnumInfo {
469    const enumDeclaration: ts.EnumDeclaration = node as ts.EnumDeclaration;
470    const enumInfo: EnumInfo = new EnumInfo(ApiType.ENUM, node, parentApi);
471    enumInfo.setApiName(enumDeclaration.name.getText());
472    ModifierHelper.processModifiers(enumDeclaration.modifiers, enumInfo);
473    return enumInfo;
474  }
475
476  /**
477   * 处理枚举值节点
478   *
479   * @param { ts.Node } node 当前节点
480   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
481   * @returns { EnumValueInfo } 返回处理后得到的EnumValueInfo对象
482   */
483  static processEnumValue(node: ts.Node, parentApi: BasicApiInfo): EnumValueInfo {
484    const enumValueNode: ts.EnumMember = node as ts.EnumMember;
485    const enumValueInfo: EnumValueInfo = new EnumValueInfo(ApiType.ENUM_VALUE, node, parentApi);
486    enumValueInfo.setApiName(enumValueNode.name.getText());
487    enumValueInfo.setDefinedText(enumValueNode.getText());
488    const enumInfo: EnumInfo = parentApi as EnumInfo;
489    enumValueInfo.setValue(NodeProcessorHelper.getCurrentEnumValue(enumInfo));
490    if (enumValueNode.initializer) {
491      const value: string = enumValueNode.initializer.getText().replace(NodeProcessorHelper.regQuotation, '$1');
492      enumValueInfo.setValue(value);
493    }
494    return enumValueInfo;
495  }
496
497  /**
498   *
499   * @param  { EnumInfo } enumInfo Enum枚举类节点的信息
500   * @returns { string } 返回当前遍历到的枚举成员的可能的枚举值
501   */
502  static getCurrentEnumValue(enumInfo: EnumInfo): string {
503    const length: number = enumInfo.getChildApis().length;
504    if (length === 0) {
505      return String(0);
506    }
507    const preEnumValueInfo: EnumValueInfo = enumInfo.getChildApis()[length - 1] as EnumValueInfo;
508    const preEnumValue: string = preEnumValueInfo.getValue();
509    return isNaN(Number(preEnumValue)) ? '' : `${Number(preEnumValue) + 1}`;
510  }
511
512  /**
513   * 处理interface或class下面的属性节点
514   *
515   * @param { ts.Node } node 当前节点
516   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
517   * @returns { PropertyInfo } 返回处理后得到的PropertyInfo对象
518   */
519  static processPropertySigAndDec(node: ts.Node, parentApi: BasicApiInfo): PropertyInfo {
520    const propertyNode: PropertyNode = node as PropertyNode;
521    const propertyInfo: PropertyInfo = new PropertyInfo(ApiType.PROPERTY, node, parentApi);
522    propertyInfo.setApiName(propertyNode.name.getText());
523    propertyInfo.setDefinedText(propertyNode.getText());
524    ModifierHelper.processModifiers(propertyNode.modifiers, propertyInfo);
525    propertyInfo.setIsRequired(!propertyNode.questionToken ? true : false);
526    propertyInfo.addType(NodeProcessorHelper.processDataType(propertyNode.type));
527    propertyInfo.setTypeKind(propertyNode.type ? propertyNode.type.kind : -1);
528    return propertyInfo;
529  }
530
531  /**
532   * 处理.d.ets文件中的Struct节点
533   *
534   * @param { ts.Node } node 当前节点
535   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
536   * @returns { StructInfo } 返回处理后得到的StructInfo对象
537   */
538  static processStruct(node: ts.Node, parentApi: BasicApiInfo): StructInfo {
539    const structNode: ts.StructDeclaration = node as ts.StructDeclaration;
540    const structInfo: StructInfo = new StructInfo(ApiType.STRUCT, node, parentApi);
541    const structName: string = structNode.name ? structNode.name.getText() : '';
542    structInfo.setApiName(structName);
543    structInfo.setDefinedText(structInfo.getApiName());
544    ModifierHelper.processModifiers(structNode.modifiers, structInfo);
545    return structInfo;
546  }
547
548  /**
549   * 处理方法节点
550   *
551   * @param { ts.Node } node 当前节点
552   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
553   * @returns { MethodInfo } 返回处理后得到的MethodInfo对象
554   */
555  static processMethod(node: ts.Node, parentApi: BasicApiInfo): MethodInfo {
556    const methodNode: MethodType = node as MethodType;
557    const methodInfo: MethodInfo = new MethodInfo(ApiType.METHOD, node, parentApi);
558    methodInfo.setDefinedText(methodNode.getText());
559    let methodName: string = methodNode.name ? methodNode.name.getText() : '';
560    if (
561      ts.isConstructorDeclaration(methodNode) ||
562      ts.isConstructSignatureDeclaration(methodNode) ||
563      ts.isCallSignatureDeclaration(methodNode)
564    ) {
565      methodName = StringConstant.CONSTRUCTOR_API_NAME;
566    }
567    methodInfo.setApiName(methodName);
568    const callForm: string = methodNode.getText().replace(/export\s+|declare\s+|function\s+|\r\n|\;/g, '');
569    methodInfo.setCallForm(callForm);
570    if (methodNode.type && ts.SyntaxKind.VoidKeyword !== methodNode.type.kind) {
571      const returnValues: string[] = NodeProcessorHelper.processDataType(methodNode.type);
572      methodInfo.setReturnValue(returnValues);
573      methodInfo.setReturnValueType(methodNode.type.kind);
574    }
575    for (let i = 0; i < methodNode.parameters.length; i++) {
576      const param: ts.ParameterDeclaration = methodNode.parameters[i];
577      const paramInfo: ParamInfo = NodeProcessorHelper.processParam(param);
578      methodInfo.addParam(paramInfo);
579    }
580    if (!ts.isCallSignatureDeclaration(methodNode) && !ts.isConstructSignatureDeclaration(methodNode)) {
581      ModifierHelper.processModifiers(methodNode.modifiers, methodInfo);
582    }
583    return methodInfo;
584  }
585
586  /**
587   * 处理方法入参
588   *
589   * @param { ts.ParameterDeclaration } param 参数节点
590   * @returns { ParamInfo } 返回处理后的ParamInfo对象
591   */
592  static processParam(param: ts.ParameterDeclaration): ParamInfo {
593    const paramInfo: ParamInfo = new ParamInfo(ApiType.PARAM);
594    paramInfo.setApiName(param.name.getText());
595    paramInfo.setIsRequired(!param.questionToken ? true : false);
596    paramInfo.setDefinedText(param.getText());
597    paramInfo.setParamType(param.type ? param.type.kind : -1);
598    if (param.type === undefined) {
599      return paramInfo;
600    }
601    let typeMapValue: string | undefined = undefined;
602    if (ts.isLiteralTypeNode(param.type)) {
603      typeMapValue = typeMap.get(param.type.literal.kind);
604    }
605    paramInfo.setType(NodeProcessorHelper.processDataType(param.type));
606    return paramInfo;
607  }
608
609  /**
610   * 处理数据类型,因为会存在联合类型的情况
611   *
612   * @param { string } dataType 类型信息的字符串
613   * @returns { string[] } 返回处理后的数组
614   */
615  static processDataType(dataType: ts.TypeNode | undefined): string[] {
616    const typeArr: string[] = [];
617    if (!dataType || dataType.kind === ts.SyntaxKind.VoidKeyword) {
618      return typeArr;
619    }
620    if (dataType.kind === ts.SyntaxKind.UnionType) {
621      const unionTypeNode: ts.UnionTypeNode = dataType as ts.UnionTypeNode;
622      unionTypeNode.types.forEach((type: ts.TypeNode) => {
623        typeArr.push(type.getText());
624      });
625      return typeArr;
626    }
627    typeArr.push(dataType.getText());
628    return typeArr;
629  }
630
631  /**
632   * 处理type关键字定义的节点TypeAliasDeclaration,包含定义别名(包含联合类型)以及自定义对象(归为interface)
633   *
634   * @param { ts.Node } node 当前节点
635   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
636   * @returns { ApiInfo } 返回处理后的ApiInfo对象
637   */
638  static TypeAliasDeclaration(node: ts.Node, parentApi: BasicApiInfo): ApiInfo {
639    const typeAliasNode: ts.TypeAliasDeclaration = node as ts.TypeAliasDeclaration;
640    if (typeAliasNode.type.kind === ts.SyntaxKind.TypeLiteral) {
641      return NodeProcessorHelper.processTypeInterface(typeAliasNode, parentApi);
642    } else {
643      return NodeProcessorHelper.processTypeAlias(typeAliasNode, parentApi);
644    }
645  }
646
647  /**
648   * 处理type关键字定义的对象,如type sample = { count: number }
649   *
650   * @param { ts.TypeAliasDeclaration } node 当前节点
651   * @returns { InterfaceInfo } 返回处理后的InterfaceInfo对象
652   */
653  static processTypeInterface(node: ts.TypeAliasDeclaration, parentApi: BasicApiInfo): InterfaceInfo {
654    const interfaceInfo: InterfaceInfo = new InterfaceInfo(ApiType.INTERFACE, node, parentApi);
655    interfaceInfo.setApiName(node.name.getText());
656    interfaceInfo.setDefinedText(interfaceInfo.getApiName());
657    ModifierHelper.processModifiers(node.modifiers, interfaceInfo);
658    return interfaceInfo;
659  }
660
661  /**
662   * 处理type关键字定义的类型别名,包含联合类型
663   *
664   * @param { ts.Node } node 当前节点
665   * @returns { TypeAliasInfo } 返回处理后的TypeAliasInfo对象
666   */
667  static processTypeAlias(node: ts.TypeAliasDeclaration, parentApi: BasicApiInfo): TypeAliasInfo {
668    const typeNameMap: Map<number, string> = new Map([
669      [ts.SyntaxKind.UnionType, TypeAliasType.UNION_TYPE],
670      [ts.SyntaxKind.TypeLiteral, TypeAliasType.OBJECT_TYPE],
671      [ts.SyntaxKind.TupleType, TypeAliasType.TUPLE_TYPE],
672      [ts.SyntaxKind.TypeReference, TypeAliasType.REFERENCE_TYPE],
673    ]);
674    const typeAliasInfo: TypeAliasInfo = new TypeAliasInfo(ApiType.TYPE_ALIAS, node, parentApi);
675    typeAliasInfo.setApiName(node.name.getText());
676    const typeName: string | undefined = typeNameMap.get(node.type.kind);
677    if (typeName) {
678      typeAliasInfo.setTypeName(typeName);
679    }
680    typeAliasInfo.setDefinedText(node.getText());
681    ModifierHelper.processModifiers(node.modifiers, typeAliasInfo);
682    typeAliasInfo.addType(NodeProcessorHelper.processDataType(node.type));
683    return typeAliasInfo;
684  }
685
686  /**
687   * 处理VariableStatement节点,根据节点定义的情况会将其处理为常量或属性
688   *
689   * @param { ts.Node } node 当前节点
690   * @param { BasicApiInfo } parentApi 存储父节点信息的对象
691   * @returns { BasicApiInfo } 返回处理后的节点对象
692   */
693  static processVariableStat(node: ts.Node, parentApi: BasicApiInfo): BasicApiInfo {
694    const variableNode: ts.VariableStatement = node as ts.VariableStatement;
695    const definedText: string = variableNode.getText();
696    const declarationNode: ts.VariableDeclaration = variableNode.declarationList.declarations[0];
697    const REG_DECLARE_CONSTANT: RegExp = /declare\s+const/;
698    const REG_COMPONENT: RegExp = /[a-zA-Z]+(Attribute|Interface)/;
699    // declare const
700    let variableType: string = '';
701    let value: string = '';
702    if (declarationNode.type) {
703      if (ts.isLiteralTypeNode(declarationNode.type)) {
704        const typeOfLiteral: string | undefined = typeMap.get(declarationNode.type.literal.kind);
705        variableType = typeOfLiteral ? typeOfLiteral : '';
706        value = declarationNode.type.literal.getText().replace(NodeProcessorHelper.regQuotation, '$1');
707      } else {
708        variableType = declarationNode.type.getText();
709      }
710    }
711    if (REG_DECLARE_CONSTANT.test(variableNode.getText()) && REG_COMPONENT.test(variableType)) {
712      return NodeProcessorHelper.processDeclareConstant(variableNode, definedText, variableType, parentApi);
713    }
714    // 节点有初始化值,如const a = 1,归为常量
715    if (declarationNode.initializer) {
716      const constantValue: string = declarationNode.initializer.getText();
717      return NodeProcessorHelper.processConstant(variableNode, definedText, constantValue, parentApi);
718    }
719    // 节点的类型为字面量值,如const a: 111,归为常量
720    const typeNode: ts.TypeNode | undefined = declarationNode.type;
721    if (typeNode && ts.isLiteralTypeNode(typeNode)) {
722      const constantValue: string = typeNode.getText();
723      return NodeProcessorHelper.processConstant(variableNode, definedText, constantValue, parentApi);
724    }
725    // 除了上述两种常量的情况,其他归为属性
726    return NodeProcessorHelper.processVaribleProperty(variableNode, definedText, parentApi);
727  }
728
729  /**
730   * 处理常量节点
731   *
732   * @param { ts.VariableDeclaration } node 当前节点
733   * @param { string } definedText 节点定义的字符串
734   * @param { string } value 常量的取值
735   * @param { BasicApiInfo } parentApi 父节点解析后的对象
736   * @returns { ConstantInfo } 返回解析后的常量对象
737   */
738  static processConstant(
739    node: ts.VariableStatement,
740    definedText: string,
741    value: string,
742    parentApi: BasicApiInfo
743  ): ConstantInfo {
744    const declarationNode: ts.VariableDeclaration = node.declarationList.declarations[0] as ts.VariableDeclaration;
745    const constantInfo: ConstantInfo = new ConstantInfo(ApiType.CONSTANT, node, parentApi);
746    constantInfo.setDefinedText(definedText);
747    constantInfo.setApiName(declarationNode.name.getText());
748    constantInfo.setValue(value);
749    return constantInfo;
750  }
751
752  /**
753   * 处理declare常量节点
754   *
755   * @param { ts.VariableDeclaration } node 当前节点
756   * @param { string } definedText 节点定义的字符串
757   * @param { string } value 常量的取值
758   * @param { BasicApiInfo } parentApi 父节点解析后的对象
759   * @returns { ConstantInfo } 返回解析后的常量对象
760   */
761  static processDeclareConstant(
762    node: ts.VariableStatement,
763    definedText: string,
764    value: string,
765    parentApi: BasicApiInfo
766  ): ConstantInfo {
767    const declarationNode: ts.VariableDeclaration = node.declarationList.declarations[0] as ts.VariableDeclaration;
768    const constantInfo: ConstantInfo = new ConstantInfo(ApiType.DECLARE_CONST, node, parentApi);
769    constantInfo.setDefinedText(definedText);
770    constantInfo.setApiName(declarationNode.name.getText());
771    constantInfo.setValue(value);
772    return constantInfo;
773  }
774
775  /**
776   * 处理VariableDeclaration节点类型的属性节点
777   *
778   * @param { ts.VariableDeclaration } node 当前节点
779   * @param { string } definedText 节点定义的字符串
780   * @param { BasicApiInfo } parentApi 父节点解析后的对象
781   * @returns { ConstantInfo } 返回解析后的属性对象
782   */
783  static processVaribleProperty(
784    node: ts.VariableStatement,
785    definedText: string,
786    parentApi: BasicApiInfo
787  ): PropertyInfo {
788    const declarationNode: ts.VariableDeclaration = node.declarationList.declarations[0] as ts.VariableDeclaration;
789    const propertyInfo: PropertyInfo = new PropertyInfo(ApiType.PROPERTY, node, parentApi);
790    propertyInfo.setDefinedText(definedText);
791    propertyInfo.setApiName(declarationNode.name.getText());
792    propertyInfo.addType(NodeProcessorHelper.processDataType(declarationNode.type));
793    propertyInfo.setIsRequired(true);
794    if (StringUtils.hasSubstring(definedText, StringConstant.CONST_KEY_WORD)) {
795      propertyInfo.setIsReadOnly(true);
796    }
797    return propertyInfo;
798  }
799}
800
801/**
802 * 处理export readonly、static等修饰关键字
803 */
804export class ModifierHelper {
805  static setIsStatic(apiInfo: BasicApiInfo): void {
806    const propertyOrMethodInfo: PropertyInfo | MethodInfo = apiInfo as PropertyInfo | MethodInfo;
807    propertyOrMethodInfo.setIsStatic(true);
808  }
809
810  static setIsReadonly(apiInfo: BasicApiInfo): void {
811    const propertyInfo: PropertyInfo = apiInfo as PropertyInfo;
812    if (propertyInfo.setIsReadOnly) {
813      propertyInfo.setIsReadOnly(true);
814    }
815  }
816
817  static setIsExport(apiInfo: BasicApiInfo): void {
818    apiInfo.setIsExport(true);
819  }
820
821  static processModifiers(modifiers: ts.NodeArray<ts.Modifier> | undefined, apiInfo: BasicApiInfo): void {
822    let definedText: string = '';
823    if (modifiers) {
824      modifiers.forEach((modifier: ts.Modifier) => {
825        if (containerApiTypes.has(apiInfo.apiType)) {
826          definedText += ` ${modifier.getText()}`;
827        }
828
829        const setModifier: ModifierProcessorInterface | undefined = modifierProcessorMap.get(modifier.kind);
830        setModifier ? setModifier(apiInfo) : undefined;
831      });
832    }
833    if (containerApiTypes.has(apiInfo.apiType)) {
834      definedText += ` ${apiInfo.getApiType().toLowerCase()} ${apiInfo.getApiName()}`;
835      apiInfo.setDefinedText(definedText);
836    }
837  }
838}
839
840export const nodeProcessorMap: Map<ts.SyntaxKind, NodeProcessorInterface> = new Map([
841  [ts.SyntaxKind.ExportAssignment, NodeProcessorHelper.processExportAssignment],
842  [ts.SyntaxKind.ExportDeclaration, NodeProcessorHelper.processExportDeclaration],
843  // [ts.SyntaxKind.ImportEqualsDeclaration, NodeProcessorHelper.processImportEqualsDeclaration],
844  [ts.SyntaxKind.ImportDeclaration, NodeProcessorHelper.processImportInfo],
845  [ts.SyntaxKind.VariableStatement, NodeProcessorHelper.processVariableStat],
846  [ts.SyntaxKind.MethodDeclaration, NodeProcessorHelper.processMethod],
847  [ts.SyntaxKind.MethodSignature, NodeProcessorHelper.processMethod],
848  [ts.SyntaxKind.FunctionDeclaration, NodeProcessorHelper.processMethod],
849  [ts.SyntaxKind.Constructor, NodeProcessorHelper.processMethod],
850  [ts.SyntaxKind.ConstructSignature, NodeProcessorHelper.processMethod],
851  [ts.SyntaxKind.CallSignature, NodeProcessorHelper.processMethod],
852  [ts.SyntaxKind.PropertyDeclaration, NodeProcessorHelper.processPropertySigAndDec],
853  [ts.SyntaxKind.PropertySignature, NodeProcessorHelper.processPropertySigAndDec],
854  [ts.SyntaxKind.EnumMember, NodeProcessorHelper.processEnumValue],
855  [ts.SyntaxKind.EnumDeclaration, NodeProcessorHelper.processEnum],
856  [ts.SyntaxKind.TypeAliasDeclaration, NodeProcessorHelper.processTypeAlias],
857  [ts.SyntaxKind.ClassDeclaration, NodeProcessorHelper.processClass],
858  [ts.SyntaxKind.InterfaceDeclaration, NodeProcessorHelper.processInterface],
859  [ts.SyntaxKind.ModuleDeclaration, NodeProcessorHelper.processBaseModule],
860  [ts.SyntaxKind.StructDeclaration, NodeProcessorHelper.processStruct],
861]);
862
863export const modifierProcessorMap: Map<ts.SyntaxKind, ModifierProcessorInterface> = new Map([
864  [ts.SyntaxKind.ConstKeyword, ModifierHelper.setIsReadonly],
865  [ts.SyntaxKind.ReadonlyKeyword, ModifierHelper.setIsReadonly],
866  [ts.SyntaxKind.StaticKeyword, ModifierHelper.setIsStatic],
867  [ts.SyntaxKind.ExportKeyword, ModifierHelper.setIsExport],
868]);
869
870export const typeMap: Map<ts.SyntaxKind, string> = new Map([
871  [ts.SyntaxKind.StringLiteral, 'string'],
872  [ts.SyntaxKind.NumericLiteral, 'number'],
873]);
874