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