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/Promise) 256 * 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