From 8e59ee7d7a37053f0a84aa7a913ab88171187d90 Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Mon, 28 Jul 2025 09:48:17 +0800 Subject: [PATCH] fix arkts-method-inherit-rule ICJC7D Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICJC7D Test scenarios: fix bug Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 75 ++++++++++++------- .../main/method_inheritance2.ets.arkts2.json | 20 +++++ 2 files changed, 70 insertions(+), 25 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 9a0f958dd6..39c76b7fc6 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -3789,23 +3789,27 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } const methodName = node.name.text; if (allBaseTypes && allBaseTypes.length > 0) { - this.checkMethodType(allBaseTypes, methodName, node); + this.checkMethodType(allBaseTypes, methodName, node, isStatic); } } - private checkMethodType(allBaseTypes: ts.Type[], methodName: string, node: ts.MethodDeclaration): void { + private checkMethodType(allBaseTypes: ts.Type[], methodName: string, node: ts.MethodDeclaration, isStatic: boolean = false): void { for (const baseType of allBaseTypes) { - const baseMethod = baseType.getProperty(methodName); + let baseMethod: ts.Symbol | undefined; + if (isStatic) { + const constructorType = this.tsTypeChecker.getTypeOfSymbolAtLocation(baseType.getSymbol()!, node); + baseMethod = constructorType.getProperty(methodName) || + baseType.getSymbol()?.members?.get(ts.escapeLeadingUnderscores(methodName)); + } else { + baseMethod = baseType.getProperty(methodName); + } if (!baseMethod) { continue; } - - const baseMethodDecl = baseMethod.declarations?.find((d) => { - return ( - (ts.isMethodDeclaration(d) || ts.isMethodSignature(d)) && - this.tsTypeChecker.getTypeAtLocation(d.parent) === baseType - ); - }) as ts.MethodDeclaration | ts.MethodSignature; + const baseMethodDecl = baseMethod.declarations?.find(d => + (ts.isMethodDeclaration(d) || ts.isMethodSignature(d)) && + this.isSameDeclarationType(d.parent, baseType, isStatic) + ) as ts.MethodDeclaration | ts.MethodSignature; if (!baseMethodDecl) { continue; @@ -3819,6 +3823,14 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } + private isSameDeclarationType(decl: ts.Node, type: ts.Type, isStatic: boolean): boolean { + if (isStatic && ts.isClassDeclaration(decl)) { + const staticType = this.tsTypeChecker.getTypeAtLocation(decl); + return this.isSameType(staticType, type); + } + return this.tsTypeChecker.getTypeAtLocation(decl) === type; + } + private checkIncompatibleFunctionTypes(method: ts.MethodDeclaration): void { const declaredReturnType = this.getActualReturnType(method); if (!declaredReturnType) { @@ -3926,21 +3938,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private getAllBaseTypes(type: ts.Type, classDecl: ts.ClassDeclaration, isStatic?: boolean): ts.Type[] | undefined { if (isStatic) { - const baseTypes: ts.Type[] = []; - if (!classDecl.heritageClauses) { - return baseTypes; - } - for (const clause of classDecl.heritageClauses) { - if (clause.token !== ts.SyntaxKind.ExtendsKeyword) { - continue; - } - for (const typeNode of clause.types) { - const baseType = this.tsTypeChecker.getTypeAtLocation(typeNode); - baseTypes.push(baseType); - } - } - - return baseTypes; + return this.getStaticAllBaseTypes(classDecl); } const baseClasses = type.getBaseTypes() || []; @@ -3952,6 +3950,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!classDecl.heritageClauses) { return resolvedBaseClasses; } + const interfaces: ts.Type[] = []; for (const clause of classDecl.heritageClauses) { if (clause.token !== ts.SyntaxKind.ImplementsKeyword) { @@ -3973,6 +3972,32 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return [...resolvedBaseClasses, ...interfaces]; } + private getStaticAllBaseTypes(classDecl: ts.ClassDeclaration): ts.Type[] | undefined { + const baseTypes: ts.Type[] = []; + if (!classDecl.heritageClauses) { + return baseTypes; + } + + for (const clause of classDecl.heritageClauses) { + if (clause.token !== ts.SyntaxKind.ExtendsKeyword) { + continue; + } + + for (const typeNode of clause.types) { + const baseType = this.tsTypeChecker.getTypeAtLocation(typeNode); + baseTypes.push(baseType); + + const baseDecl = baseType.getSymbol()?.declarations?.[0]; + if (baseDecl && ts.isClassDeclaration(baseDecl)) { + const staticBaseType = this.tsTypeChecker.getTypeAtLocation(baseDecl); + const staticBaseTypes = this.getAllBaseTypes(staticBaseType, baseDecl, true) || []; + baseTypes.push(...staticBaseTypes); + } + } + } + return baseTypes; + } + /** * Checks method parameter compatibility * Derived parameter types must be same or wider than base (contravariance principle) diff --git a/ets2panda/linter/test/main/method_inheritance2.ets.arkts2.json b/ets2panda/linter/test/main/method_inheritance2.ets.arkts2.json index 0a8b389c11..bfb88a65c8 100755 --- a/ets2panda/linter/test/main/method_inheritance2.ets.arkts2.json +++ b/ets2panda/linter/test/main/method_inheritance2.ets.arkts2.json @@ -104,6 +104,16 @@ "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", "severity": "ERROR" }, + { + "line": 103, + "column": 18, + "endLine": 103, + "endColumn": 19, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, { "line": 108, "column": 17, @@ -113,6 +123,16 @@ "suggest": "", "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", "severity": "ERROR" + }, + { + "line": 112, + "column": 18, + "endLine": 112, + "endColumn": 19, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" } ] } \ No newline at end of file -- Gitee