From 4356ba6dbff04b40b9886cc028ca1d74b59e26bc Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Tue, 5 Aug 2025 19:42:50 +0800 Subject: [PATCH] fix arkts-method-inherit-rule_ICQYZZ Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICQYZZ Test scenarios: fix bug Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 58 +++++++++++++- ...exable_type_element_access.ets.arkts2.json | 20 +++++ ...type_string_element_access.ets.arkts2.json | 13 ++- .../linter/test/main/method_inheritance3.ets | 80 +++++++++++++++++++ .../test/main/stdlib_array.ets.arkts2.json | 40 ++++++++++ 5 files changed, 208 insertions(+), 3 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index fb73dd0e1c..a1856b03a2 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -4153,7 +4153,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!this.isTypeSameOrWider(baseParamType, derivedParamType)) { this.incrementCounters(derivedParams[i], FaultID.MethodInheritRule); - } + } } } @@ -4263,7 +4263,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return true; } - if (derivedType.flags & ts.TypeFlags.Any) { + if (derivedType.flags & ts.TypeFlags.Any || baseType.flags & ts.TypeFlags.Never) { return true; } @@ -4282,6 +4282,10 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return true; } + if (this.checkTypeInheritance(derivedType, baseType, false)) { + return true; + } + const baseTypeSet = new Set(this.flattenUnionTypes(baseType)); const derivedTypeSet = new Set(this.flattenUnionTypes(derivedType)); @@ -4315,6 +4319,10 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } + if(this.checkTypeInheritance(fromType, toType)) { + return true; + } + const fromTypes = this.flattenUnionTypes(fromType); const toTypes = new Set(this.flattenUnionTypes(toType)); @@ -4326,6 +4334,52 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { }); } + private checkTypeInheritance( + sourceType: ts.Type, + targetType: ts.Type, + isSouceTotaqrget: boolean = true + ): boolean { + // Early return if either type lacks symbol information + if (!sourceType.symbol || !targetType.symbol) { + return false; + } + + // Determine which type's inheritance chain to examine based on check direction + const typeToGetChain = isSouceTotaqrget ? sourceType : targetType; + const typeToCheck = isSouceTotaqrget ? targetType : sourceType; + + // Get inheritance chain and check for relationship + const inheritanceChain = this.getTypeInheritanceChain(typeToGetChain); + return inheritanceChain.some(t => { + return t.symbol === typeToCheck.symbol; + }); + } + + private getTypeInheritanceChain(type: ts.Type): ts.Type[] { + const chain: ts.Type[] = [type]; + const declarations = type.symbol?.getDeclarations() || []; + + for (const declaration of declarations) { + if ((!ts.isClassDeclaration(declaration) && !ts.isInterfaceDeclaration(declaration)) || + !declaration.heritageClauses) { + continue; + } + + const heritageClauses = declaration.heritageClauses.filter(clause => { + return clause.token === ts.SyntaxKind.ExtendsKeyword || clause.token === ts.SyntaxKind.ImplementsKeyword; + }); + + for (const clause of heritageClauses) { + for (const typeExpr of clause.types) { + const baseType = this.tsTypeChecker.getTypeAtLocation(typeExpr.expression); + chain.push(baseType, ...this.getTypeInheritanceChain(baseType)); + } + } + } + + return chain; + } + // Check if a type string has an equivalent primitive/wrapper type in a set private static areWrapperAndPrimitiveTypesEqual(typeStr: string, typeSet: Set): boolean { const typePairs = [ diff --git a/ets2panda/linter/test/main/indexable_type_element_access.ets.arkts2.json b/ets2panda/linter/test/main/indexable_type_element_access.ets.arkts2.json index 7345e0b15f..32eb4db5dd 100644 --- a/ets2panda/linter/test/main/indexable_type_element_access.ets.arkts2.json +++ b/ets2panda/linter/test/main/indexable_type_element_access.ets.arkts2.json @@ -14,6 +14,16 @@ "limitations under the License." ], "result": [ + { + "line": 18, + "column": 12, + "endLine": 18, + "endColumn": 16, + "problem": "IncompationbleFunctionType", + "suggest": "", + "rule": "Stricter assignments into variables of function type (arkts-incompatible-function-types)", + "severity": "ERROR" + }, { "line": 23, "column": 1, @@ -33,6 +43,16 @@ "suggest": "", "rule": "Indexed access is not supported for fields (arkts-no-props-by-index)", "severity": "ERROR" + }, + { + "line": 34, + "column": 12, + "endLine": 34, + "endColumn": 16, + "problem": "IncompationbleFunctionType", + "suggest": "", + "rule": "Stricter assignments into variables of function type (arkts-incompatible-function-types)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/indexable_type_string_element_access.ets.arkts2.json b/ets2panda/linter/test/main/indexable_type_string_element_access.ets.arkts2.json index 3ee4a5b916..8e46ce7166 100644 --- a/ets2panda/linter/test/main/indexable_type_string_element_access.ets.arkts2.json +++ b/ets2panda/linter/test/main/indexable_type_string_element_access.ets.arkts2.json @@ -13,5 +13,16 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [] + "result": [ + { + "line": 17, + "column": 45, + "endLine": 17, + "endColumn": 49, + "problem": "IncompationbleFunctionType", + "suggest": "", + "rule": "Stricter assignments into variables of function type (arkts-incompatible-function-types)", + "severity": "ERROR" + } + ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/method_inheritance3.ets b/ets2panda/linter/test/main/method_inheritance3.ets index d31da9911b..d4b5b6b18e 100755 --- a/ets2panda/linter/test/main/method_inheritance3.ets +++ b/ets2panda/linter/test/main/method_inheritance3.ets @@ -60,4 +60,84 @@ class EntryAbility extends UIAbility { } catch (e) { } } +} + +class TestA { + a: number = 0 +} + +class TestD extends TestA{ + a: number = 0; + b: number = 1; +} + +class TestE implements TestI{ + +} + +class TestF extends TestE{ + +} +interface TestI{ + +} + +interface TestI2 extends TestI{ + +} +class TestBase { + foo3(obj: TestD): void { + console.log("Derived:" + obj.b) + } + + foo4(obj: TestD): TestA { + console.log("base" ); + return new TestA() + } + + foo5():TestI{ + return {} + } + + foo12(obj:never){ + + } +} + +class TestDerived extends TestBase { + override foo3(obj: TestA): void { // no error + console.log("base" ); + } + + override foo4(obj: TestA): TestD { // no error + return new TestD(); + } + + override foo5(): TestI2 { // no error + return {} + } + + override foo12(obj:TestA){ // no error + + } +} + +class CC1 {} +class CC2 extends CC1 { + public static toString(result: number): string { // no error + return ''; + } +} + +class AA{ + getData(a:T):T{ + + return a; + } +} + +class BB extends AA{ + getData(a: number): number { // no error + return 123; + } } \ No newline at end of file diff --git a/ets2panda/linter/test/main/stdlib_array.ets.arkts2.json b/ets2panda/linter/test/main/stdlib_array.ets.arkts2.json index c519ba8f63..cd5487e484 100644 --- a/ets2panda/linter/test/main/stdlib_array.ets.arkts2.json +++ b/ets2panda/linter/test/main/stdlib_array.ets.arkts2.json @@ -24,6 +24,16 @@ "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", "severity": "ERROR" }, + { + "line": 18, + "column": 48, + "endLine": 18, + "endColumn": 52, + "problem": "IncompationbleFunctionType", + "suggest": "", + "rule": "Stricter assignments into variables of function type (arkts-incompatible-function-types)", + "severity": "ERROR" + }, { "line": 21, "column": 18, @@ -34,6 +44,16 @@ "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", "severity": "ERROR" }, + { + "line": 22, + "column": 56, + "endLine": 22, + "endColumn": 60, + "problem": "IncompationbleFunctionType", + "suggest": "", + "rule": "Stricter assignments into variables of function type (arkts-incompatible-function-types)", + "severity": "ERROR" + }, { "line": 25, "column": 18, @@ -44,6 +64,16 @@ "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", "severity": "ERROR" }, + { + "line": 26, + "column": 54, + "endLine": 26, + "endColumn": 58, + "problem": "IncompationbleFunctionType", + "suggest": "", + "rule": "Stricter assignments into variables of function type (arkts-incompatible-function-types)", + "severity": "ERROR" + }, { "line": 29, "column": 18, @@ -54,6 +84,16 @@ "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", "severity": "ERROR" }, + { + "line": 30, + "column": 52, + "endLine": 30, + "endColumn": 56, + "problem": "IncompationbleFunctionType", + "suggest": "", + "rule": "Stricter assignments into variables of function type (arkts-incompatible-function-types)", + "severity": "ERROR" + }, { "line": 36, "column": 18, -- Gitee