1 2import * as ts from "typescript"; 3 4import uiconfig from '../arkui_config_util' 5 6/** 7 * Analyzes the base classes of a given class declaration and collects their names recursively. 8 * 9 * @param classNode - The TypeScript class declaration node to analyze. 10 * @param sourceFile - The source file containing the class declaration. 11 * @param program - The TypeScript program instance used for type checking. 12 * 13 * @returns void 14 * 15 * This function traverses the inheritance hierarchy of the specified class declaration, 16 * extracting the names of all base classes. It uses the TypeScript type checker to resolve 17 * symbols and declarations of base classes, ensuring accurate identification of inherited types. 18 */ 19export function analyzeBaseClasses(classNode: ts.ClassDeclaration, sourceFile: ts.SourceFile, program: ts.Program) { 20 const className = classNode.name!.escapedText!; 21 const baseTypes: string[] = []; 22 const checker = program.getTypeChecker(); 23 24 25 const extractTypeName = (expr: ts.Expression): string | null => { 26 if (ts.isIdentifier(expr)) { 27 return expr.text; 28 } else if (ts.isPropertyAccessExpression(expr)) { 29 return `${extractTypeName(expr.expression)}.${expr.name.text}`; 30 } 31 return null; 32 } 33 34 const findBase = (currentClass: ts.ClassDeclaration) => { 35 if (!currentClass.heritageClauses) return; 36 37 for (const heritage of currentClass.heritageClauses) { 38 if (heritage.token === ts.SyntaxKind.ExtendsKeyword) { 39 for (const type of heritage.types) { 40 const baseName = extractTypeName(type.expression); 41 if (baseName) { 42 baseTypes.push(baseName); 43 const baseSymbol = checker.getSymbolAtLocation(type.expression); 44 if (baseSymbol) { 45 const baseDeclarations = baseSymbol.getDeclarations(); 46 if (baseDeclarations) { 47 baseDeclarations.forEach(decl => { 48 if (ts.isClassDeclaration(decl)) { 49 findBase(decl); 50 } 51 }); 52 } 53 } 54 } 55 } 56 } 57 } 58 }; 59 60 findBase(classNode); 61 return baseTypes 62} 63 64export function getBaseClassName(classNode: ts.ClassDeclaration): string | undefined { 65 if (!classNode.heritageClauses) return undefined; 66 67 for (const heritage of classNode.heritageClauses) { 68 if (heritage.token === ts.SyntaxKind.ExtendsKeyword) { 69 for (const type of heritage.types) { 70 const baseName = type.expression.getText(); 71 return baseName; 72 } 73 } 74 } 75 return undefined; 76} 77 78export function isComponentHerirage(node: ts.Node): boolean { 79 if (!ts.isClassDeclaration(node) && !ts.isInterfaceDeclaration(node)) { 80 return false; 81 } 82 return uiconfig.isUIHeritage(node.name!.escapedText!) 83} 84 85export function removeDuplicateMethods(methods: ts.MethodSignature[]): ts.MethodSignature[] { 86 const seenSignatures = new Set<string>(); 87 88 return methods.filter(method => { 89 const signatureKey = getMethodCharacteristic(method); 90 91 if (seenSignatures.has(signatureKey)) { 92 return false; 93 } 94 95 seenSignatures.add(signatureKey); 96 return true; 97 }); 98} 99 100export function getMethodCharacteristic( 101 node: ts.MethodSignature 102): string { 103 const methodName = node.name.getText(); 104 105 const params = node.parameters.map((param) => { 106 const typeNode = param.type; 107 let typeText: string; 108 109 if (typeNode) { 110 if (ts.isUnionTypeNode(typeNode)) { 111 const types = typeNode.types; 112 typeText = types.map((t) => { 113 if (ts.isTypeReferenceNode(t)) { 114 return t.getText(); 115 } 116 return t.kind.toString(); 117 }).join('|') || 'any'; 118 } else { 119 throw new Error("UnExpected type node kind"); 120 } 121 } else { 122 throw new Error("UnExpected type node kind"); 123 } 124 125 return typeText; 126 }); 127 128 return `${methodName}(${params.join(',')})`; 129} 130 131export function mergeUniqueOrdered(arr1: string[], arr2: string[]): string[] { 132 const seen = new Set<string>(); 133 const result: string[] = []; 134 for (const item of arr1) { 135 if (!seen.has(item)) { 136 seen.add(item); 137 result.push(item); 138 } 139 } 140 141 for (const item of arr2) { 142 if (!seen.has(item)) { 143 seen.add(item); 144 result.push(item); 145 } 146 } 147 148 return result; 149} 150