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