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