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 path from "path"; 18 19import { FileUtils } from '../../utils/FileUtils'; 20import { StringConstant } from '../../utils/Constant'; 21import { Comment } from './Comment'; 22import { DecoratorInfo } from './Decorator'; 23import { JsDocProcessorHelper } from '../../coreImpl/parser/JsDocProcessor'; 24 25export enum ApiType { 26 SOURCE_FILE = 'SourceFile', 27 REFERENCE_FILE = 'Reference', 28 PROPERTY = 'Property', 29 CLASS = 'Class', 30 INTERFACE = 'Interface', 31 NAMESPACE = 'Namespace', 32 METHOD = 'Method', 33 MODULE = 'Module', 34 EXPORT = 'Export', 35 EXPORT_DEFAULT = 'ExportDefault', 36 CONSTANT = 'Constant', 37 IMPORT = 'Import', 38 DECLARE_CONST = 'DeclareConst', 39 ENUM_VALUE = 'EnumValue', 40 TYPE_ALIAS = 'TypeAlias', 41 PARAM = 'Param', 42 ENUM = 'Enum', 43 STRUCT = 'Struct', 44} 45 46export enum TypeAliasType { 47 UNION_TYPE = 'UnionType', 48 OBJECT_TYPE = 'ObjectType', 49 TUPLE_TYPE = 'TupleType', 50 REFERENCE_TYPE = 'ReferenceType', 51} 52 53export class BasicApiInfo { 54 private node: ts.Node | undefined = undefined; //astnode节点 55 filePath: string = ''; // api所在文件的路径 56 apiType: ApiType = '' as ApiType; // api的类型 57 // api的定义语句,如果为namespace、class、interface、enum等节点的话,则仅为定义的那行 58 definedText: string = ''; 59 pos: ts.LineAndCharacter = { line: -1, character: -1 }; // api所在的位置信息 60 parentApi: BasicApiInfo | undefined = undefined; // 定义api节点的父节点的api信息 61 isExport: boolean = false; // api节点是否有export关键字进行导出 62 apiName: string = ''; // api的名称 63 hierarchicalRelations: string[] = []; // api所属的层级关系 64 decorators: DecoratorInfo[] | undefined = undefined; //decorators修饰器集合 65 isStruct: boolean = false; //是否为structDeclaration内部api 66 syscap: string = ''; 67 currentVersion = '-1'; 68 jsDocText: string = ''; 69 isJoinType: boolean = false; 70 genericInfo: GenericInfo[] = []; 71 parentApiType: string = ''; 72 fileAbsolutePath: string = ''; //绝对路径 73 isSameNameFunction: boolean = false; //是否为同名API 74 75 constructor(apiType: string = '', node: ts.Node, parentApi: BasicApiInfo | undefined) { 76 this.node = node; 77 this.setParentApi(parentApi); 78 this.setParentApiType(parentApi?.getApiType()); 79 if (parentApi) { 80 this.setFilePath(parentApi.getFilePath()); 81 this.setFileAbsolutePath(parentApi.getFileAbsolutePath()); 82 this.setIsStruct(parentApi.getIsStruct()); 83 } 84 this.setApiType(apiType); 85 const sourceFile: ts.SourceFile = node.getSourceFile(); 86 const start: number = node.getStart(); 87 const pos: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(start); 88 pos.character++; 89 pos.line++; 90 this.setPos(pos); 91 if (node.decorators) { 92 node.decorators.forEach((decorator: ts.Decorator) => { 93 this.addDecorators([new DecoratorInfo(decorator)]); 94 }); 95 } 96 } 97 98 getNode(): ts.Node | undefined { 99 return this.node; 100 } 101 102 removeNode(): void { 103 this.node = undefined; 104 } 105 106 setFilePath(fileFilePath: string): void { 107 this.filePath = fileFilePath; 108 } 109 110 getFilePath(): string { 111 return this.filePath; 112 } 113 114 setFileAbsolutePath(absolutePath: string): void { 115 this.fileAbsolutePath = absolutePath; 116 } 117 118 getFileAbsolutePath(): string { 119 return this.fileAbsolutePath; 120 } 121 122 setApiType(apiType: string): void { 123 this.apiType = apiType as ApiType; 124 } 125 126 getApiType(): string { 127 return this.apiType; 128 } 129 130 setDefinedText(definedText: string): void { 131 this.definedText = definedText; 132 } 133 134 getDefinedText(): string { 135 return this.definedText; 136 } 137 138 setPos(pos: ts.LineAndCharacter): void { 139 this.pos = pos; 140 } 141 142 getPos(): ts.LineAndCharacter { 143 return this.pos; 144 } 145 146 setParentApi(parentApi: BasicApiInfo | undefined): void { 147 this.parentApi = parentApi; 148 } 149 150 getParentApi(): BasicApiInfo | undefined { 151 return this.parentApi; 152 } 153 154 setParentApiType(parentApiType: string | undefined): void { 155 if (parentApiType) { 156 this.parentApiType = parentApiType; 157 } 158 } 159 160 getParentApiType(): string { 161 return this.parentApiType; 162 } 163 164 setIsExport(isExport: boolean): void { 165 this.isExport = isExport; 166 } 167 168 getIsExport(): boolean { 169 return this.isExport; 170 } 171 172 setApiName(apiName: string): void { 173 this.apiName = apiName; 174 if (this.parentApi) { 175 this.setHierarchicalRelations(this.parentApi.getHierarchicalRelations()); 176 } 177 this.addHierarchicalRelation([apiName]); 178 } 179 180 getApiName(): string { 181 return this.apiName; 182 } 183 184 setHierarchicalRelations(hierarchicalRelations: string[]): void { 185 this.hierarchicalRelations = [...hierarchicalRelations]; 186 } 187 188 getHierarchicalRelations(): string[] { 189 return this.hierarchicalRelations; 190 } 191 192 addHierarchicalRelation(hierarchicalRelation: string[]): void { 193 this.hierarchicalRelations.push(...hierarchicalRelation); 194 } 195 196 setDecorators(decorators: DecoratorInfo[]): void { 197 this.decorators = decorators; 198 } 199 200 addDecorators(decorators: DecoratorInfo[]): void { 201 if (!this.decorators) { 202 this.decorators = []; 203 } 204 this.decorators.push(...decorators); 205 } 206 207 getDecorators(): DecoratorInfo[] | undefined { 208 return this.decorators; 209 } 210 211 setIsStruct(isStruct: boolean): void { 212 this.isStruct = isStruct; 213 } 214 215 getIsStruct(): boolean { 216 return this.isStruct; 217 } 218 219 setSyscap(syscap: string): void { 220 this.syscap = syscap; 221 } 222 223 getSyscap(): string { 224 return this.syscap; 225 } 226 227 setCurrentVersion(version: string): void { 228 this.currentVersion = version; 229 } 230 231 getCurrentVersion(): string { 232 return this.currentVersion; 233 } 234 235 setJsDocText(jsDocText: string): void { 236 this.jsDocText = jsDocText; 237 } 238 239 getJsDocText(): string { 240 return this.jsDocText; 241 } 242 243 setIsJoinType(jsJoinType: boolean): void { 244 this.isJoinType = jsJoinType; 245 } 246 247 getIsJoinType(): boolean { 248 return this.isJoinType; 249 } 250 251 setGenericInfo(genericInfo: GenericInfo): void { 252 this.genericInfo.push(genericInfo); 253 } 254 255 getGenericInfo(): GenericInfo[] { 256 return this.genericInfo; 257 } 258 259 setIsSameNameFunction(isSameNameFunction: boolean): void { 260 this.isSameNameFunction = isSameNameFunction; 261 } 262 263 getIsSameNameFunction(): boolean { 264 return this.isSameNameFunction; 265 } 266} 267 268export class ExportDefaultInfo extends BasicApiInfo { } 269 270export class ReferenceInfo extends BasicApiInfo { 271 pathName: string = ''; 272 273 setPathName(pathName: string): ReferenceInfo { 274 this.pathName = pathName; 275 return this; 276 } 277 278 getPathName(): string { 279 return this.pathName; 280 } 281} 282 283export class ExportDeclareInfo extends BasicApiInfo { 284 exportValues: Array<ExportImportValue> = []; 285 286 addExportValues(name: string, type: string): void { 287 this.exportValues.push({ key: name, value: type || name }); 288 } 289 290 getExportValues(): Array<ExportImportValue> { 291 return this.exportValues; 292 } 293} 294 295/** 296 * import导入的信息,包含导入的值和路径信息 297 */ 298export class ImportInfo extends BasicApiInfo { 299 importValues: Array<ExportImportValue> = []; 300 importPath: string = ''; 301 302 addImportValue(name: string, type: string): void { 303 this.importValues.push({ key: name, value: type || name }); 304 } 305 306 getImportValues(): Array<ExportImportValue> { 307 return this.importValues; 308 } 309 310 setImportPath(importPath: string): void { 311 this.importPath = importPath; 312 } 313 314 getImportPath(): string { 315 return this.importPath; 316 } 317} 318 319export class ApiInfo extends BasicApiInfo { 320 jsDocInfos: Comment.JsDocInfo[] = []; // 所有的JsDoc信息 321 322 constructor(apiType: string = '', node: ts.Node, parentApi: BasicApiInfo | undefined) { 323 super(apiType, node, parentApi); 324 let parentKitInfo: string = 'NA'; 325 let parentFileTagContent: string = 'NA'; 326 if (parentApi) { 327 parentKitInfo = this.getKitInfoFromParent(parentApi).kitInfo; 328 parentFileTagContent = this.getKitInfoFromParent(parentApi).fileTagContent; 329 } 330 const jsDocInfos: Comment.JsDocInfo[] = JsDocProcessorHelper.processJsDocInfos( 331 node, 332 apiType, 333 parentKitInfo, 334 parentFileTagContent 335 ); 336 const jsDocText: string = node 337 .getFullText() 338 .substring(0, node.getFullText().length - node.getText().length) 339 .trim(); 340 this.setJsDocText(jsDocText); 341 this.addJsDocInfos(jsDocInfos); 342 } 343 344 getKitInfoFromParent(parentApi: BasicApiInfo): FileTag { 345 const parentApiInfo = parentApi as ApiInfo; 346 const jsDocInfos: Comment.JsDocInfo[] = parentApiInfo.getJsDocInfos(); 347 let kitInfo: string | undefined = ''; 348 let fileTagContent: string = 'NA'; 349 jsDocInfos.forEach((jsDocInfo: Comment.JsDocInfo) => { 350 kitInfo = jsDocInfo.getKit(); 351 fileTagContent = jsDocInfo.getFileTagContent(); 352 }); 353 return { kitInfo, fileTagContent }; 354 } 355 356 getJsDocInfos(): Comment.JsDocInfo[] { 357 return this.jsDocInfos; 358 } 359 360 getLastJsDocInfo(): Comment.JsDocInfo | undefined { 361 const length: number = this.jsDocInfos.length; 362 if (length === 0) { 363 return undefined; 364 } 365 return this.jsDocInfos[length - 1]; 366 } 367 368 getPenultimateJsDocInfo(): Comment.JsDocInfo | undefined { 369 const length: number = this.jsDocInfos.length; 370 if (length === 0) { 371 return undefined; 372 } 373 return this.jsDocInfos[length - 2]; 374 } 375 376 addJsDocInfos(jsDocInfos: Comment.JsDocInfo[]): void { 377 if (jsDocInfos.length > 0) { 378 this.setCurrentVersion(jsDocInfos[jsDocInfos.length - 1]?.getSince()); 379 } 380 this.jsDocInfos.push(...jsDocInfos); 381 } 382 383 addJsDocInfo(jsDocInfo: Comment.JsDocInfo): void { 384 this.setCurrentVersion(jsDocInfo.getSince()); 385 this.jsDocInfos.push(jsDocInfo); 386 } 387} 388 389export class ClassInfo extends ApiInfo { 390 parentClasses: ParentClass[] = []; // 继承的父类 391 childApis: BasicApiInfo[] = []; // 子节点的信息 392 393 setParentClasses(parentClass: ParentClass): void { 394 this.parentClasses.push(parentClass); 395 } 396 397 getParentClasses(): ParentClass[] { 398 return this.parentClasses; 399 } 400 401 addChildApis(childApis: BasicApiInfo[]): void { 402 this.childApis.push(...childApis); 403 } 404 405 addChildApi(childApi: BasicApiInfo): void { 406 this.childApis.push(childApi); 407 } 408 409 getChildApis(): BasicApiInfo[] { 410 return this.childApis; 411 } 412} 413 414export class InterfaceInfo extends ApiInfo { 415 parentClasses: ParentClass[] = []; // 继承的父类 416 childApis: BasicApiInfo[] = []; // 子节点的信息 417 418 setParentClasses(parentClass: ParentClass): void { 419 this.parentClasses.push(parentClass); 420 } 421 422 getParentClasses(): ParentClass[] { 423 return this.parentClasses; 424 } 425 426 addChildApis(childApis: BasicApiInfo[]): void { 427 this.childApis.push(...childApis); 428 } 429 430 addChildApi(childApi: BasicApiInfo): void { 431 this.childApis.push(childApi); 432 } 433 434 getChildApis(): BasicApiInfo[] { 435 return this.childApis; 436 } 437} 438 439export class NamespaceInfo extends ApiInfo { 440 childApis: BasicApiInfo[] = []; 441 442 addChildApis(childApis: BasicApiInfo[]): void { 443 this.childApis.push(...childApis); 444 } 445 446 addChildApi(childApi: BasicApiInfo): void { 447 this.childApis.push(childApi); 448 } 449 450 getChildApis(): BasicApiInfo[] { 451 return this.childApis; 452 } 453} 454 455export class StructInfo extends ApiInfo { 456 childApis: BasicApiInfo[] = []; 457 458 addChildApis(childApis: BasicApiInfo[]): void { 459 this.childApis.push(...childApis); 460 } 461 462 addChildApi(childApi: BasicApiInfo): void { 463 this.childApis.push(childApi); 464 } 465 466 getChildApis(): BasicApiInfo[] { 467 return this.childApis; 468 } 469} 470 471export class ModuleInfo extends ApiInfo { 472 childApis: BasicApiInfo[] = []; 473 474 addChildApis(childApis: BasicApiInfo[]): void { 475 this.childApis.push(...childApis); 476 } 477 478 addChildApi(childApi: BasicApiInfo): void { 479 this.childApis.push(childApi); 480 } 481 482 getChildApis(): BasicApiInfo[] { 483 return this.childApis; 484 } 485} 486 487export class EnumInfo extends ApiInfo { 488 childApis: BasicApiInfo[] = []; 489 490 addChildApis(childApis: BasicApiInfo[]): void { 491 this.childApis.push(...childApis); 492 } 493 494 addChildApi(childApi: BasicApiInfo): void { 495 this.childApis.push(childApi); 496 } 497 498 getChildApis(): BasicApiInfo[] { 499 return this.childApis; 500 } 501} 502 503/** 504 * 属性会包含declare const定义的节点 505 */ 506export class PropertyInfo extends ApiInfo { 507 type: string[] = []; // 属性的类型,数组是由于可能为联合类型 508 isReadOnly: boolean = false; // 属性是否为只读 509 isRequired: boolean = false; // 属性是否为必选 510 isStatic: boolean = false; // 属性是否为静态 511 typeKind: ts.SyntaxKind = ts.SyntaxKind.Unknown; //type类型的kind值 512 typeLocations: ApiInfo[] = []; // 参数、返回值的JsDoc信息 513 objLocations: PropertyInfo[] = []; // 匿名类型的JsDoc信息 514 515 constructor(apiType: string = '', node: ts.Node, parentApi: BasicApiInfo | undefined) { 516 super(apiType, node, parentApi); 517 let propertyNode: PropertyNode = node as PropertyNode; 518 this.setTypeKind(propertyNode.type ? propertyNode.type.kind : ts.SyntaxKind.Unknown); 519 } 520 521 addType(type: string[]): void { 522 this.type.push(...type); 523 } 524 525 getType(): string[] { 526 return this.type; 527 } 528 529 setIsReadOnly(isReadOnly: boolean): void { 530 this.isReadOnly = isReadOnly; 531 } 532 533 getIsReadOnly(): boolean { 534 return this.isReadOnly; 535 } 536 537 setIsRequired(isRequired: boolean): void { 538 this.isRequired = isRequired; 539 } 540 541 getIsRequired(): boolean { 542 return this.isRequired; 543 } 544 545 setIsStatic(isStatic: boolean): void { 546 this.isStatic = isStatic; 547 } 548 549 getIsStatic(): boolean { 550 return this.isStatic; 551 } 552 553 setTypeKind(typeKind: ts.SyntaxKind | undefined): void { 554 this.typeKind = typeKind ? typeKind : ts.SyntaxKind.Unknown; 555 } 556 557 getTypeKind(): ts.SyntaxKind { 558 return this.typeKind; 559 } 560 561 addTypeLocations(typeLocation: ApiInfo): void { 562 this.typeLocations.push(typeLocation); 563 } 564 565 getTypeLocations(): ApiInfo[] { 566 return this.typeLocations; 567 } 568 569 setTypeLocations(apiInfos: ApiInfo[]): void { 570 this.typeLocations = apiInfos; 571 } 572 573 addObjLocations(ObjLocation: PropertyInfo): void { 574 this.objLocations.push(ObjLocation); 575 } 576 577 getObjLocations(): PropertyInfo[] { 578 return this.objLocations; 579 } 580 581 setObjLocations(objLocations: PropertyInfo[]): void { 582 this.objLocations = objLocations; 583 } 584} 585 586export class ConstantInfo extends ApiInfo { 587 value: string = ''; // 常量的取值 588 589 setValue(value: string): void { 590 this.value = value; 591 } 592 593 getValue(): string { 594 return this.value; 595 } 596} 597 598/** 599 * 使用type关键字定义的节点,归为自定义类型的范畴 600 */ 601export class TypeAliasInfo extends ApiInfo { 602 type: string[] = []; // type定义的类型 603 typeName: TypeAliasType = '' as TypeAliasType; //type的类型 604 returnType: string[] = []; //type类型为function时的返回值 605 paramInfos: ParamInfo[] = []; //type类型为function时的参数名和参数类型 606 typeIsFunction: boolean = false; //type类型是否为function 607 typeLiteralApiInfos: PropertyInfo[] = [];//type类型为匿名对象时的属性数据 608 typeIsObject: boolean = false;//type类型是否为匿名对象 609 addType(type: string[]): void { 610 this.type.push(...type); 611 } 612 613 getType(): string[] { 614 return this.type; 615 } 616 617 setTypeName(typeName: string): TypeAliasInfo { 618 this.typeName = typeName as TypeAliasType; 619 return this; 620 } 621 622 getTypeName(): string { 623 return this.typeName; 624 } 625 626 setReturnType(returnValue: string[]): void { 627 this.returnType.push(...returnValue); 628 } 629 630 getReturnType(): string[] { 631 return this.returnType; 632 } 633 634 setParamInfos(paramInfo: ParamInfo): TypeAliasInfo { 635 this.paramInfos.push(paramInfo); 636 return this; 637 } 638 639 getParamInfos(): ParamInfo[] { 640 return this.paramInfos; 641 } 642 643 setTypeIsFunction(typeIsFunction: boolean): TypeAliasInfo { 644 this.typeIsFunction = typeIsFunction; 645 return this; 646 } 647 648 getTypeIsFunction(): boolean { 649 return this.typeIsFunction; 650 } 651 652 setTypeLiteralApiInfos(propertyInfo: PropertyInfo): TypeAliasInfo { 653 this.typeLiteralApiInfos.push(propertyInfo); 654 return this; 655 } 656 657 getTypeLiteralApiInfos(): PropertyInfo[] { 658 return this.typeLiteralApiInfos; 659 } 660 661 setTypeIsObject(typeIsObject: boolean): TypeAliasInfo { 662 this.typeIsObject = typeIsObject; 663 return this; 664 } 665 666 getTypeIsObject(): boolean { 667 return this.typeIsObject; 668 } 669} 670 671/** 672 * type自定义类型为function时,解析参数 673 */ 674export class TypeParamInfo { 675 //type类型为function时的参数名 676 paramName: string = ''; 677 //type类型为function时的参数类型 678 paramType: string = ''; 679 680 setParamName(paramName: string): TypeParamInfo { 681 this.paramName = paramName; 682 return this; 683 } 684 685 getParamName(): string { 686 return this.paramName; 687 } 688 689 setParamType(paramType: string | undefined): TypeParamInfo { 690 if (!paramType) { 691 return this; 692 } 693 this.paramType = paramType; 694 return this; 695 } 696 697 getParamType(): string { 698 return this.paramType; 699 } 700} 701 702export class EnumValueInfo extends ApiInfo { 703 value: string = ''; // 枚举值 704 705 setValue(value: string): void { 706 this.value = value; 707 } 708 709 getValue(): string { 710 return this.value; 711 } 712} 713 714export class MethodInfo extends ApiInfo { 715 callForm: string = ''; // 方法的调用形式 716 params: ParamInfo[] = []; // 方法的参数列表 717 returnValue: string[] = []; // 方法的返回值类型 718 isStatic: boolean = false; // 方法是否是静态 719 sync: string = ''; //同步函数标志 720 returnValueType: ts.SyntaxKind = ts.SyntaxKind.Unknown; 721 typeLocations: ApiInfo[] = []; // 参数、返回值的JsDoc信息 722 objLocations: PropertyInfo[] = []; // 匿名类型的JsDoc信息 723 isRequired: boolean = false; 724 725 setCallForm(callForm: string): void { 726 this.callForm = callForm; 727 } 728 729 getCallForm(): string { 730 return this.callForm; 731 } 732 733 addParam(paramInfo: ParamInfo): void { 734 this.params.push(paramInfo); 735 } 736 737 getParams(): ParamInfo[] { 738 return this.params; 739 } 740 741 setReturnValue(returnValue: string[]): void { 742 this.returnValue.push(...returnValue); 743 } 744 745 getReturnValue(): string[] { 746 return this.returnValue; 747 } 748 749 setReturnValueType(returnValueType: ts.SyntaxKind): void { 750 this.returnValueType = returnValueType; 751 } 752 753 getReturnValueType(): ts.SyntaxKind { 754 return this.returnValueType; 755 } 756 757 setIsStatic(isStatic: boolean): void { 758 this.isStatic = isStatic; 759 } 760 761 getIsStatic(): boolean { 762 return this.isStatic; 763 } 764 765 addTypeLocations(typeLocation: ApiInfo): void { 766 this.typeLocations.push(typeLocation); 767 } 768 769 getTypeLocations(): ApiInfo[] { 770 return this.typeLocations; 771 } 772 773 setTypeLocations(apiInfos: ApiInfo[]): void { 774 this.typeLocations = apiInfos; 775 } 776 777 addObjLocations(ObjLocation: PropertyInfo): void { 778 this.objLocations.push(ObjLocation); 779 } 780 781 getObjLocations(): PropertyInfo[] { 782 return this.objLocations; 783 } 784 785 setObjLocations(objLocations: PropertyInfo[]): void { 786 this.objLocations = objLocations; 787 } 788 789 setSync(sync: string): void { 790 this.sync = sync; 791 } 792 793 getSync(): string { 794 return this.sync; 795 } 796 797 setIsRequired(isRequired: boolean): void { 798 this.isRequired = isRequired; 799 } 800 801 getIsRequired(): boolean { 802 return this.isRequired; 803 } 804} 805 806export class TypeLocationInfo extends Comment.JsDocInfo { 807 typeName: string = '';//当前类型名称 808 809 getTypeName(): string { 810 return this.typeName; 811 } 812 813 setTypeName(typeName: string): void { 814 this.typeName = typeName; 815 } 816} 817 818export class ParamInfo { 819 apiType: string = ''; // api的类型为方法参数 820 apiName: string = ''; // 参数名 821 paramType: ts.SyntaxKind = ts.SyntaxKind.Unknown; // 参数类型的kind 822 type: string[] = []; // 参数的类型 823 isRequired: boolean = false; // 参数是否必选 824 definedText: string = ''; 825 methodApiInfo: MethodInfo | undefined; 826 typeLocations: ApiInfo[] = []; // 参数、返回值的JsDoc信息 827 objLocations: PropertyInfo[] = []; // 匿名类型的JsDoc信息 828 typeIsObject: boolean = false;//type类型是否为匿名对象 829 830 constructor(apiType: string) { 831 this.apiType = apiType; 832 } 833 834 getApiType(): string { 835 return this.apiType; 836 } 837 838 setApiName(apiName: string): void { 839 this.apiName = apiName; 840 } 841 842 getApiName(): string { 843 return this.apiName; 844 } 845 846 setType(type: string[]): void { 847 this.type.push(...type); 848 } 849 850 getParamType(): ts.SyntaxKind { 851 return this.paramType; 852 } 853 854 setParamType(paramType: ts.SyntaxKind | undefined): void { 855 this.paramType = paramType ? paramType : ts.SyntaxKind.Unknown; 856 } 857 858 getType(): string[] { 859 return this.type; 860 } 861 862 setIsRequired(isRequired: boolean): void { 863 this.isRequired = isRequired; 864 } 865 866 getIsRequired(): boolean { 867 return this.isRequired; 868 } 869 870 setDefinedText(definedText: string): void { 871 this.definedText = definedText; 872 } 873 874 getDefinedText(): string { 875 return this.definedText; 876 } 877 878 addTypeLocations(typeLocation: ApiInfo): void { 879 this.typeLocations.push(typeLocation); 880 } 881 882 getTypeLocations(): ApiInfo[] { 883 return this.typeLocations; 884 } 885 886 setTypeLocations(apiInfos: ApiInfo[]): void { 887 this.typeLocations = apiInfos; 888 } 889 890 addObjLocations(ObjLocation: PropertyInfo): void { 891 this.objLocations.push(ObjLocation); 892 } 893 894 getObjLocations(): PropertyInfo[] { 895 return this.objLocations; 896 } 897 898 setObjLocations(objLocations: PropertyInfo[]): void { 899 this.objLocations = objLocations; 900 } 901 902 setMethodApiInfo(methodApiInfo: MethodInfo | undefined): void { 903 this.methodApiInfo = methodApiInfo; 904 } 905 906 getMethodApiInfo(): MethodInfo | undefined { 907 return this.methodApiInfo; 908 } 909 910 911} 912 913export class GenericInfo { 914 isGenericity: boolean = false; 915 genericContent: string = ''; 916 917 setIsGenericity(isGenericity: boolean): void { 918 this.isGenericity = isGenericity; 919 } 920 getIsGenericity(): boolean { 921 return this.isGenericity; 922 } 923 924 setGenericContent(genericContent: string): void { 925 this.genericContent = genericContent; 926 } 927 928 getGenericContent(): string { 929 return this.genericContent; 930 } 931} 932 933export class ParentClass { 934 extendClass: string = ''; 935 implementClass: string = ''; 936 937 setExtendClass(extendClass: string): void { 938 this.extendClass = extendClass; 939 } 940 941 getExtendClass(): string { 942 return this.extendClass; 943 } 944 945 setImplementClass(implementClass: string): void { 946 this.implementClass = implementClass; 947 } 948 949 getImplementClass(): string { 950 return this.implementClass; 951 } 952} 953 954export class ParserParam { 955 fileDir: string = ''; 956 filePath: string = ''; 957 libPath: string = ''; 958 sdkPath: string = ''; 959 rootNames: string[] = []; 960 tsProgram: ts.Program = ts.createProgram({ 961 rootNames: [], 962 options: {}, 963 }); 964 compilerHost: ts.CompilerHost = ts.createCompilerHost({}); 965 constructor() { } 966 967 getFileDir(): string { 968 return this.fileDir; 969 } 970 971 setFileDir(fileDir: string): void { 972 this.fileDir = fileDir; 973 } 974 975 getFilePath(): string { 976 return this.filePath; 977 } 978 979 setFilePath(filePath: string): void { 980 this.filePath = filePath; 981 } 982 983 getLibPath(): string { 984 return this.libPath; 985 } 986 987 setLibPath(libPath: string): void { 988 this.libPath = libPath; 989 } 990 991 getSdkPath(): string { 992 return this.sdkPath; 993 } 994 995 setSdkPath(sdkPath: string): void { 996 this.sdkPath = sdkPath; 997 } 998 999 getRootNames(): string[] { 1000 return this.rootNames; 1001 } 1002 1003 setRootNames(rootNames: string[]): void { 1004 this.rootNames = rootNames; 1005 } 1006 1007 getTsProgram(): ts.Program { 1008 return this.tsProgram; 1009 } 1010 1011 getETSOptions(componentLibs: Array<string>): any { 1012 const tsconfig = require('../../config/tsconfig.json'); 1013 const etsConfig = tsconfig.compilerOptions.ets; 1014 etsConfig.libs = [...componentLibs]; 1015 return etsConfig; 1016 } 1017 1018 setProgram(): void { 1019 const apiLibs: Array<string> = FileUtils.readFilesInDir(this.sdkPath, (name) => { 1020 return name.endsWith(StringConstant.DTS_EXTENSION) || name.endsWith(StringConstant.DETS_EXTENSION); 1021 }); 1022 const esLibs: Array<string> = FileUtils.readFilesInDir(this.libPath, (name) => { 1023 return name.endsWith(StringConstant.DTS_EXTENSION) || name.endsWith(StringConstant.DETS_EXTENSION); 1024 }); 1025 const compilerOption: ts.CompilerOptions = { 1026 target: ts.ScriptTarget.ES2017, 1027 ets: this.getETSOptions([]), 1028 allowJs: false, 1029 lib: [...apiLibs, ...esLibs], 1030 module: ts.ModuleKind.CommonJS, 1031 baseUrl: "./", 1032 paths: { 1033 "@/*": ["./*"] 1034 }, 1035 }; 1036 this.compilerHost = ts.createCompilerHost(compilerOption); 1037 // 设置别名 1038 this.compilerHost.resolveModuleNames = (moduleNames: string[], containingFile: string, 1039 reusedNames: string[] | undefined, redirectedReference: ts.ResolvedProjectReference | undefined, 1040 compilerOptions: ts.CompilerOptions): (ts.ResolvedModule | undefined)[] => { 1041 return moduleNames.map(moduleName => { 1042 if (process.env.IS_OH === 'true') { 1043 return ts.resolveModuleName(moduleName, containingFile, compilerOptions, this.compilerHost).resolvedModule; 1044 } 1045 const value: ts.ResolvedModule = { 1046 resolvedFileName: '', 1047 isExternalLibraryImport: false 1048 }; 1049 const alias: { [key: string]: string; } = { 1050 "^(@ohos\\.inner\\.)(.*)$": "../../../base/ets/api/", 1051 "^(@ohos\\.)(.*)$": "../../../base/ets/api/", 1052 }; 1053 for (const key in alias) { 1054 const regex = new RegExp(key); 1055 if (regex.test(moduleName)) { 1056 moduleName = moduleName.replace(regex, ($0, $1, $2) => { 1057 let realPath = ''; 1058 switch ($1) { 1059 case "@ohos.": 1060 realPath = alias[key] + $1 + $2; 1061 break; 1062 case "@ohos\.inner\.": 1063 realPath = alias[key] + $2.replace(/\./g, '/'); 1064 break; 1065 default: 1066 realPath = ''; 1067 break; 1068 } 1069 return realPath; 1070 }); 1071 break; 1072 } 1073 } 1074 const resolvedFileName: string | undefined = ts.resolveModuleName(moduleName, containingFile, compilerOptions, 1075 this.compilerHost).resolvedModule?.resolvedFileName; 1076 if (resolvedFileName) { 1077 value.resolvedFileName = resolvedFileName; 1078 value.isExternalLibraryImport = true; 1079 } else { 1080 return undefined; 1081 } 1082 return value; 1083 }); 1084 }; 1085 this.tsProgram = ts.createProgram({ 1086 rootNames: [...this.rootNames], 1087 options: compilerOption, 1088 host: this.compilerHost 1089 }); 1090 } 1091} 1092 1093export type ExportImportValue = { key: string; value: string; }; 1094export interface NodeProcessorInterface { 1095 (node: ts.Node, parentApiInfo: BasicApiInfo): BasicApiInfo; 1096} 1097 1098export type PropertyNode = ts.PropertyDeclaration | ts.PropertySignature; 1099export type PropertyTypeNode = ts.TypeNode | ts.Expression | undefined; 1100 1101export interface ModifierProcessorInterface { 1102 (propertyInfo: BasicApiInfo): void; 1103} 1104 1105export interface FileTag { 1106 kitInfo: string; 1107 fileTagContent: string; 1108} 1109 1110/** 1111 * ts中所有方法节点 1112 */ 1113export type MethodType = 1114 | ts.MethodDeclaration 1115 | ts.MethodSignature 1116 | ts.FunctionDeclaration 1117 | ts.CallSignatureDeclaration 1118 | ts.ConstructorDeclaration 1119 | ts.ConstructSignatureDeclaration; 1120 1121/** 1122 * 拥有子节点的class,处理数据时需要addChildApi,获取数据时可以getChildApis 1123 */ 1124export type ContainerApiInfo = NamespaceInfo | ClassInfo | InterfaceInfo | EnumInfo | ModuleInfo | StructInfo; 1125 1126/** 1127 * 拥有引用类型或者匿名对象的class,输出json文件时需要特殊编队objLocations和typeLocations,去除其中的node和parent节点 1128 */ 1129export type LocationsAPIType = ParamInfo | PropertyInfo | MethodInfo; 1130 1131/** 1132 * 将节点强制转换为ContainerApiInfo节点时需要根据ApiType来判断哪些apiInfo节点有childApi 1133 */ 1134export const containerApiTypes: Set<string> = new Set([ 1135 ApiType.NAMESPACE, 1136 ApiType.CLASS, 1137 ApiType.INTERFACE, 1138 ApiType.ENUM, 1139 ApiType.MODULE, 1140 ApiType.STRUCT, 1141]); 1142 1143/** 1144 * 不存在jsdoc信息的节点 1145 */ 1146export const notJsDocApiTypes: Set<string> = new Set([ 1147 ApiType.SOURCE_FILE, 1148 ApiType.IMPORT, 1149 ApiType.EXPORT, 1150 ApiType.EXPORT_DEFAULT, 1151 ApiType.MODULE, 1152 ApiType.REFERENCE_FILE, 1153]); 1154