From 0f85e680637a40b6c26a3c7b0fc1377c968c7d54 Mon Sep 17 00:00:00 2001 From: Fouckttt Date: Thu, 21 Aug 2025 21:39:54 +0800 Subject: [PATCH] arkts-no-super-call-in-static-context Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICU4US Signed-off-by: Fouckttt --- ets2panda/linter/rule-config.json | 3 +- ets2panda/linter/src/lib/CookBookMsg.ts | 1 + ets2panda/linter/src/lib/FaultAttrs.ts | 1 + ets2panda/linter/src/lib/Problems.ts | 1 + ets2panda/linter/src/lib/TypeScriptLinter.ts | 60 ++++++++++--- ...-super-call-in-static-context-negative.ets | 34 +++++++ ...l-in-static-context-negative.ets.args.json | 19 ++++ ...in-static-context-negative.ets.arkts2.json | 88 +++++++++++++++++++ ...r-call-in-static-context-negative.ets.json | 78 ++++++++++++++++ ...-super-call-in-static-context-positive.ets | 81 +++++++++++++++++ ...l-in-static-context-positive.ets.args.json | 19 ++++ ...in-static-context-positive.ets.arkts2.json | 28 ++++++ ...r-call-in-static-context-positive.ets.json | 17 ++++ 13 files changed, 416 insertions(+), 14 deletions(-) create mode 100644 ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets create mode 100644 ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.args.json create mode 100644 ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.arkts2.json create mode 100644 ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.json create mode 100644 ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets create mode 100644 ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.args.json create mode 100644 ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.arkts2.json create mode 100644 ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.json diff --git a/ets2panda/linter/rule-config.json b/ets2panda/linter/rule-config.json index 673ad51d19..2215e97ed7 100644 --- a/ets2panda/linter/rule-config.json +++ b/ets2panda/linter/rule-config.json @@ -80,7 +80,8 @@ "arkts-not-support-tuple-generic-validation", "arkts-no-optional-tuple-type", "arkts-no-large-numeric-literal", - "arkts-no-instanceof-func" + "arkts-no-instanceof-func", + "arkts-no-super-call-in-static-context" ], "interop": [ "arkts-interop-js2s-inherit-js-class", diff --git a/ets2panda/linter/src/lib/CookBookMsg.ts b/ets2panda/linter/src/lib/CookBookMsg.ts index 7f1377fa3c..1f7c31a63b 100644 --- a/ets2panda/linter/src/lib/CookBookMsg.ts +++ b/ets2panda/linter/src/lib/CookBookMsg.ts @@ -437,6 +437,7 @@ cookBookTag[408] = 'The property of IteratorResult is not supported (arkts-built cookBookTag[409] = 'No optional tuple type (arkts-no-optional-tuple-type)'; cookBookTag[410] = 'Numeric literal exceeds allowed range (arkts-no-large-numeric-literal)'; cookBookTag[411] = '"instanceof" operator can\'t be applied to function (arkts-no-instanceof-func)'; +cookBookTag[412] = 'Subclass can\'t call members of super class in static context (arkts-no-super-call-in-static-context)'; for (let i = 0; i <= cookBookTag.length; i++) { cookBookMsg[i] = ''; } diff --git a/ets2panda/linter/src/lib/FaultAttrs.ts b/ets2panda/linter/src/lib/FaultAttrs.ts index aa48bb969b..78f355cc5d 100644 --- a/ets2panda/linter/src/lib/FaultAttrs.ts +++ b/ets2panda/linter/src/lib/FaultAttrs.ts @@ -309,3 +309,4 @@ faultsAttrs[FaultID.BuiltinIteratorResultValue] = new FaultAttributes(408); faultsAttrs[FaultID.OptionalTupleType] = new FaultAttributes(409); faultsAttrs[FaultID.LargeNumericLiteral] = new FaultAttributes(410); faultsAttrs[FaultID.InstanceOfFunction] = new FaultAttributes(411); +faultsAttrs[FaultID.SupperInStaticContext] = new FaultAttributes(412); diff --git a/ets2panda/linter/src/lib/Problems.ts b/ets2panda/linter/src/lib/Problems.ts index e9908007e0..32bb35c8c6 100644 --- a/ets2panda/linter/src/lib/Problems.ts +++ b/ets2panda/linter/src/lib/Problems.ts @@ -298,6 +298,7 @@ export enum FaultID { OptionalTupleType, LargeNumericLiteral, InstanceOfFunction, + SupperInStaticContext, // this should always be last enum LAST_ID } diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index cd5d1f7dc8..29a7937c47 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -1914,6 +1914,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.handlePropertyDeclarationForProp(node); this.handleSdkGlobalApi(node); this.handleObjectLiteralAssignmentToClass(node); + this.handleSupperInStaticContext(node); } private handleSendableClassProperty(node: ts.PropertyDeclaration): void { @@ -1935,6 +1936,17 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } + private handleSupperInStaticContext(node: ts.PropertyDeclaration): void { + if (node.modifiers) { + for (const mod of node.modifiers) { + if (mod.kind === ts.SyntaxKind.StaticKeyword && !!node.initializer) { + this.reportThisSuperKeywordsInStaticContext(node.initializer); + return; + } + } + } + } + private handlePropertyAssignment(node: ts.PropertyAssignment): void { this.handleDollarBind(node); this.handlePropertyAssignmentForProp(node); @@ -2163,7 +2175,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.incrementCounters(funcExpr, FaultID.GeneratorFunction); } if (!hasPredecessor(funcExpr, TypeScriptLinter.isClassLikeOrIface)) { - this.reportThisKeywordsInScope(funcExpr.body); + this.reportThisSuperKeywordsInStaticContext(funcExpr.body); } if (hasUnfixableReturnType) { this.incrementCounters(funcExpr, FaultID.LimitedReturnTypeInference); @@ -2174,7 +2186,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private handleArrowFunction(node: ts.Node): void { const arrowFunc = node as ts.ArrowFunction; if (!hasPredecessor(arrowFunc, TypeScriptLinter.isClassLikeOrIface)) { - this.reportThisKeywordsInScope(arrowFunc.body); + this.reportThisSuperKeywordsInStaticContext(arrowFunc.body); } const contextType = this.tsTypeChecker.getContextualType(arrowFunc); if (!(contextType && this.tsUtils.isLibraryType(contextType))) { @@ -2204,7 +2216,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.countDeclarationsWithDuplicateName(tsFunctionDeclaration.name, tsFunctionDeclaration); } if (tsFunctionDeclaration.body) { - this.reportThisKeywordsInScope(tsFunctionDeclaration.body); + this.reportThisSuperKeywordsInStaticContext(tsFunctionDeclaration.body); } if (this.options.arkts2) { this.handleParamType(tsFunctionDeclaration); @@ -3895,7 +3907,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.handleParamType(tsMethodDecl); } if (tsMethodDecl.body && isStatic) { - this.reportThisKeywordsInScope(tsMethodDecl.body); + this.reportThisSuperKeywordsInStaticContext(tsMethodDecl.body); } if (!tsMethodDecl.type) { this.handleMissingReturnType(tsMethodDecl); @@ -4669,7 +4681,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!ts.isClassDeclaration(classStaticBlockDecl.parent)) { return; } - this.reportThisKeywordsInScope(classStaticBlockDecl.body); + this.reportThisSuperKeywordsInStaticContext(classStaticBlockDecl.body); } private handleIdentifier(node: ts.Node): void { @@ -7247,19 +7259,41 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.incrementCounters(entry.range as ts.CommentRange, FaultID.ErrorSuppression); } - private reportThisKeywordsInScope(scope: ts.Block | ts.Expression): void { - const callback = (node: ts.Node): void => { - if (node.kind === ts.SyntaxKind.ThisKeyword) { - this.incrementCounters(node, FaultID.FunctionContainsThis); - } - }; + private reportThisSuperKeywordsInStaticContext(node: ts.Block | ts.Expression): void { + if (!node.parent) { + return; + } + let callback: (node: ts.Node) => void; + if (ts.isFunctionDeclaration(node.parent)) { + callback = (node: ts.Node): void => { + if (node.kind === ts.SyntaxKind.ThisKeyword) { + this.incrementCounters(node, FaultID.FunctionContainsThis); + } + }; + } else if (ts.isPropertyDeclaration(node.parent)) { + callback = (node: ts.Node): void => { + if (node.kind === ts.SyntaxKind.SuperKeyword) { + this.incrementCounters(node, FaultID.SupperInStaticContext); + } + }; + } else { + callback = (node: ts.Node): void => { + if (node.kind === ts.SyntaxKind.ThisKeyword) { + this.incrementCounters(node, FaultID.FunctionContainsThis); + } + if (node.kind === ts.SyntaxKind.SuperKeyword) { + this.incrementCounters(node, FaultID.SupperInStaticContext); + } + }; + } + const stopCondition = (node: ts.Node): boolean => { const isClassLike = ts.isClassDeclaration(node) || ts.isClassExpression(node); const isFunctionLike = ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node); const isModuleDecl = ts.isModuleDeclaration(node); return isClassLike || isFunctionLike || isModuleDecl; }; - forEachNodeInSubtree(scope, callback, stopCondition); + forEachNodeInSubtree(node, callback, stopCondition); } private handleConstructorDeclaration(node: ts.Node): void { @@ -11418,7 +11452,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { handleInstanceOfFunction(node: ts.BinaryExpression): void { const right = node.right; - let symbol = this.tsUtils.trueSymbolAtLocation(right); + const symbol = this.tsUtils.trueSymbolAtLocation(right); if (!symbol) { return; } diff --git a/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets new file mode 100644 index 0000000000..9cb64f1075 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + static foo() { + return 123; + } + static a: number = 1.0; +} + +class B extends A { + static x1: number = super.foo(); // report error for calling super class in static context. + static x2: number = super.a; // report error for calling super class in static context. + static foo() { + let x3: number = super.a; // report error for calling super class in static method. + return super.foo() + 456; // report error for calling super class in static method. + } + static { + let x4: number = super.a; // report error for calling super class in static code block. + super.foo(); // report error for calling super class in static code block. + } +} diff --git a/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.args.json b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.args.json new file mode 100644 index 0000000000..d8d3390ad9 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.args.json @@ -0,0 +1,19 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + "arkts2": "" + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.arkts2.json b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.arkts2.json new file mode 100644 index 0000000000..f5f5c02c95 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.arkts2.json @@ -0,0 +1,88 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 30, + "column": 3, + "endLine": 33, + "endColumn": 4, + "problem": "NoStaticOnClass", + "suggest": "", + "rule": "Class cannot have static codeblocks. (arkts-class-lazy-import)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 23, + "endLine": 24, + "endColumn": 28, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 23, + "endLine": 25, + "endColumn": 28, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 22, + "endLine": 27, + "endColumn": 27, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 12, + "endLine": 28, + "endColumn": 17, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 22, + "endLine": 31, + "endColumn": 27, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 5, + "endLine": 32, + "endColumn": 10, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.json b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.json new file mode 100644 index 0000000000..2c9fa13084 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-negative.ets.json @@ -0,0 +1,78 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 24, + "column": 23, + "endLine": 24, + "endColumn": 28, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 23, + "endLine": 25, + "endColumn": 28, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 22, + "endLine": 27, + "endColumn": 27, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 12, + "endLine": 28, + "endColumn": 17, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 22, + "endLine": 31, + "endColumn": 27, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 5, + "endLine": 32, + "endColumn": 10, + "problem": "SupperInStaticContext", + "suggest": "", + "rule": "Subclass can't call members of super class in static context (arkts-no-super-call-in-static-context)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets new file mode 100644 index 0000000000..4bd51f8c1a --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + static foo() { + return 123; + } +} + +class B extends A { + static foo() { + return A.foo() + 456; + } + static { + console.log('asd'); + A.foo(); + } +} + +class Animal1 { + name: string; + constructor(name: string) { + this.name = name; + } +} +class Dog1 extends Animal1 { + breed: string; + constructor(name: string, breed: string) { + super(name); + this.breed = breed; + } +} + +class Animal2 { + move(): void { + console.log("Moving..."); + } +} +class Dog2 extends Animal2 { + move(): void { + super.move(); + console.log("Running..."); + } +} + +class Base1 { + greet(): void { + console.log("Hello, world!"); + } +} +class Derived1 extends Base1 { + greet(): void { + super.greet(); + console.log("Hello from Derived class!"); + } +} + +class Base2 { + value: number; + constructor() { + this.value = 100; + } +} +class Derived2 extends Base2 { + constructor() { + super(); + this.value += 50; + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.args.json b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.args.json new file mode 100644 index 0000000000..d8d3390ad9 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.args.json @@ -0,0 +1,19 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + "arkts2": "" + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.arkts2.json b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.arkts2.json new file mode 100644 index 0000000000..65e7c7a06a --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.arkts2.json @@ -0,0 +1,28 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 26, + "column": 3, + "endLine": 29, + "endColumn": 4, + "problem": "NoStaticOnClass", + "suggest": "", + "rule": "Class cannot have static codeblocks. (arkts-class-lazy-import)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.json b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.json new file mode 100644 index 0000000000..ca88f857e9 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-super-call-in-static-context-positive.ets.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} \ No newline at end of file -- Gitee