• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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