From 880f4b26c82d5637ae1d0f144e426d98d50607ec Mon Sep 17 00:00:00 2001 From: Fouckttt Date: Tue, 19 Aug 2025 16:24:34 +0800 Subject: [PATCH] arkts-no-instanceof-func Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICTO9Y Signed-off-by: Fouckttt --- ets2panda/linter/rule-config.json | 3 +- ets2panda/linter/src/lib/CookBookMsg.ts | 2 +- ets2panda/linter/src/lib/FaultAttrs.ts | 1 + ets2panda/linter/src/lib/Problems.ts | 1 + ets2panda/linter/src/lib/TypeScriptLinter.ts | 65 ++++++- .../arkts-no-instanceof-func_negative.ets | 67 ++++++++ ...instanceof-func_negative.ets.ets.args.json | 19 +++ ...arkts-no-instanceof-func_negative.ets.json | 158 ++++++++++++++++++ .../arkts-no-instanceof-func_positive.ets | 55 ++++++ ...instanceof-func_positive.ets.ets.args.json | 19 +++ ...arkts-no-instanceof-func_positive.ets.json | 17 ++ 11 files changed, 398 insertions(+), 9 deletions(-) create mode 100644 ets2panda/linter/test/main/arkts-no-instanceof-func_negative.ets create mode 100644 ets2panda/linter/test/main/arkts-no-instanceof-func_negative.ets.ets.args.json create mode 100644 ets2panda/linter/test/main/arkts-no-instanceof-func_negative.ets.json create mode 100644 ets2panda/linter/test/main/arkts-no-instanceof-func_positive.ets create mode 100644 ets2panda/linter/test/main/arkts-no-instanceof-func_positive.ets.ets.args.json create mode 100644 ets2panda/linter/test/main/arkts-no-instanceof-func_positive.ets.json diff --git a/ets2panda/linter/rule-config.json b/ets2panda/linter/rule-config.json index d064920bc6..673ad51d19 100644 --- a/ets2panda/linter/rule-config.json +++ b/ets2panda/linter/rule-config.json @@ -79,7 +79,8 @@ "arkts-no-esobject-support", "arkts-not-support-tuple-generic-validation", "arkts-no-optional-tuple-type", - "arkts-no-large-numeric-literal" + "arkts-no-large-numeric-literal", + "arkts-no-instanceof-func" ], "interop": [ "arkts-interop-js2s-inherit-js-class", diff --git a/ets2panda/linter/src/lib/CookBookMsg.ts b/ets2panda/linter/src/lib/CookBookMsg.ts index 2a49273753..7f1377fa3c 100644 --- a/ets2panda/linter/src/lib/CookBookMsg.ts +++ b/ets2panda/linter/src/lib/CookBookMsg.ts @@ -436,7 +436,7 @@ cookBookTag[407] = 'API has been disabled (arkts-builtin-disable-api)'; cookBookTag[408] = 'The property of IteratorResult is not supported (arkts-builtin-iterator-result-value)'; 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)'; 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 53b081f214..aa48bb969b 100644 --- a/ets2panda/linter/src/lib/FaultAttrs.ts +++ b/ets2panda/linter/src/lib/FaultAttrs.ts @@ -308,3 +308,4 @@ faultsAttrs[FaultID.BuiltinDisableApi] = new FaultAttributes(407); faultsAttrs[FaultID.BuiltinIteratorResultValue] = new FaultAttributes(408); faultsAttrs[FaultID.OptionalTupleType] = new FaultAttributes(409); faultsAttrs[FaultID.LargeNumericLiteral] = new FaultAttributes(410); +faultsAttrs[FaultID.InstanceOfFunction] = new FaultAttributes(411); diff --git a/ets2panda/linter/src/lib/Problems.ts b/ets2panda/linter/src/lib/Problems.ts index 85947c13d6..e9908007e0 100644 --- a/ets2panda/linter/src/lib/Problems.ts +++ b/ets2panda/linter/src/lib/Problems.ts @@ -297,6 +297,7 @@ export enum FaultID { BuiltinIteratorResultValue, OptionalTupleType, LargeNumericLiteral, + InstanceOfFunction, // 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 e61b3a7a63..cd5d1f7dc8 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -215,7 +215,7 @@ import { ABILITY_LIFECYCLE_SDK } from './utils/consts/AsyncLifecycleSDK'; import { ERROR_PROP_LIST } from './utils/consts/ErrorProp'; -import { D_ETS, D_TS } from './utils/consts/TsSuffix'; +import { ETS, D_ETS, D_TS } from './utils/consts/TsSuffix'; import { arkTsBuiltInTypeName } from './utils/consts/ArkuiImportList'; import { ERROR_TASKPOOL_PROP_LIST } from './utils/consts/ErrorProp'; import { COMMON_UNION_MEMBER_ACCESS_WHITELIST } from './utils/consts/ArktsWhiteApiPaths'; @@ -2457,6 +2457,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { case ts.SyntaxKind.InstanceOfKeyword: this.processBinaryInstanceOf(node, tsLhsExpr, leftOperandType); this.handleInstanceOfExpression(tsBinaryExpr); + this.handleInstanceOfFunction(tsBinaryExpr); break; case ts.SyntaxKind.InKeyword: this.incrementCounters(tsBinaryExpr.operatorToken, FaultID.InOperator); @@ -6247,7 +6248,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.checkOnClickCallback(tsCallOrNewExpr); } -private checkOnClickCallback(tsCallOrNewExpr: ts.CallExpression | ts.NewExpression): void { + private checkOnClickCallback(tsCallOrNewExpr: ts.CallExpression | ts.NewExpression): void { if (!tsCallOrNewExpr.arguments || tsCallOrNewExpr.arguments.length === 0 && this.options.arkts2) { return; } @@ -6277,8 +6278,8 @@ private checkOnClickCallback(tsCallOrNewExpr: ts.CallExpression | ts.NewExpressi private checkAsyncOrPromiseFunction(callback: ts.ArrowFunction): void { const returnsPromise = this.checkReturnsPromise(callback); - const isAsync = callback.modifiers?.some((m) => { - return m.kind === ts.SyntaxKind.AsyncKeyword; + const isAsync = callback.modifiers?.some((m) => { + return m.kind === ts.SyntaxKind.AsyncKeyword; }); if (isAsync || returnsPromise) { @@ -6286,9 +6287,15 @@ private checkOnClickCallback(tsCallOrNewExpr: ts.CallExpression | ts.NewExpressi const endPos = callback.body.getEnd(); const errorNode = { - getStart: () => { return startPos; }, - getEnd: () => { return endPos; }, - getSourceFile: () => { return callback.getSourceFile(); } + getStart: () => { + return startPos; + }, + getEnd: () => { + return endPos; + }, + getSourceFile: () => { + return callback.getSourceFile(); + } } as ts.Node; this.incrementCounters(errorNode, FaultID.IncompationbleFunctionType); @@ -11409,6 +11416,50 @@ private checkOnClickCallback(tsCallOrNewExpr: ts.CallExpression | ts.NewExpressi this.incrementCounters(node, FaultID.InteropJsInstanceof, autofix); } + handleInstanceOfFunction(node: ts.BinaryExpression): void { + const right = node.right; + let symbol = this.tsUtils.trueSymbolAtLocation(right); + if (!symbol) { + return; + } + + const visitedSymbols = new Set(); + if (this.checkSymbolDeclarationsForInstanceOfFunction(symbol, visitedSymbols)) { + this.incrementCounters(right, FaultID.InstanceOfFunction); + } + } + + private checkSymbolDeclarationsForInstanceOfFunction(symbol: ts.Symbol, visited: Set): boolean { + if (visited.has(symbol)) { + return false; + } + visited.add(symbol); + const declarations = symbol.getDeclarations() || []; + for (const decl of declarations) { + const sourceFile = decl.getSourceFile(); + if (!sourceFile?.fileName) { + continue; + } + + if (!sourceFile.fileName.endsWith(ETS)) { + continue; + } + + if (ts.isFunctionDeclaration(decl)) { + return true; + } + + if (ts.isVariableDeclaration(decl) && decl.initializer) { + const initSymbol = this.tsUtils.trueSymbolAtLocation(decl.initializer); + if (!!initSymbol && this.checkSymbolDeclarationsForInstanceOfFunction(initSymbol, visited)) { + return true; + } + continue; + } + } + return false; + } + private checkAutoIncrementDecrement(unaryExpr: ts.PostfixUnaryExpression | ts.PrefixUnaryExpression): void { if (!this.useStatic || !this.options.arkts2) { return; diff --git a/ets2panda/linter/test/main/arkts-no-instanceof-func_negative.ets b/ets2panda/linter/test/main/arkts-no-instanceof-func_negative.ets new file mode 100644 index 0000000000..f18275a560 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-instanceof-func_negative.ets @@ -0,0 +1,67 @@ +/* + * 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. + */ + + +import foo5 from './arkts-no-instanceof-func_positive' +import {foo3} from './arkts-no-instanceof-func_positive' +import {foo3 as foo6} from './arkts-no-instanceof-func_positive' +import {BB} from './arkts-no-instanceof-func_positive' +import {BB as CC} from './arkts-no-instanceof-func_positive' + +function foo1() { + +} + +console.log('' + ((new foo1()) instanceof foo1)) // report error for instanceof a function. + +let a = foo1; +console.log('' + ((new foo1()) instanceof a)) // report error for instanceof a function which is assigned to a. + +let b = a; +let c = b; +let d = c; +console.log('' + ((new a()) instanceof d)) // report error for instanceof a function which is assigned to a b c d. + +namespace AA { + export function foo2() {} +} + +console.log('' + ((new foo1()) instanceof AA.foo2)) // report error for instanceof a namespace export function. + +let e = AA.foo2; +console.log('' + ((new foo1()) instanceof e)) // report error for instanceof a function which is assigned to e. + + +console.log('' + ((new foo1()) instanceof foo5)) // report error for instanceof a function which is default import. + +console.log('' + ((new foo1()) instanceof foo3)) // report error for instanceof a function which is import. + +console.log('' + ((new foo1()) instanceof foo6)) // report error for instanceof a function which is alias import. + +let foo7 = foo5; +console.log('' + ((new foo1()) instanceof foo7)) // report error for instanceof a function which is import and assigned to foo7. + +let foo8 = foo3; +console.log('' + ((new foo1()) instanceof foo8)) // report error for instanceof a function which is import and assigned to foo8. + +let foo9 = foo6; +console.log('' + ((new foo1()) instanceof foo9)) // report error for instanceof a function which is alias import and assigned to foo9. + +let foo10 = foo9; +console.log('' + ((new foo1()) instanceof foo10)) // report error for instanceof a function which is import and assigned to foo9 and foo10. + +console.log('' + ((new foo1()) instanceof BB.foo11)) // report error for instanceof a function which is import from namespace. + +console.log('' + ((new foo1()) instanceof CC.foo11)) // report error for instanceof a function which is import from namespace. \ No newline at end of file diff --git a/ets2panda/linter/test/main/arkts-no-instanceof-func_negative.ets.ets.args.json b/ets2panda/linter/test/main/arkts-no-instanceof-func_negative.ets.ets.args.json new file mode 100644 index 0000000000..d8d3390ad9 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-instanceof-func_negative.ets.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-instanceof-func_negative.ets.json b/ets2panda/linter/test/main/arkts-no-instanceof-func_negative.ets.json new file mode 100644 index 0000000000..29e330916d --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-instanceof-func_negative.ets.json @@ -0,0 +1,158 @@ +{ + "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": 27, + "column": 43, + "endLine": 27, + "endColumn": 47, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 43, + "endLine": 30, + "endColumn": 44, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 40, + "endLine": 35, + "endColumn": 41, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 41, + "column": 43, + "endLine": 41, + "endColumn": 50, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 43, + "endLine": 44, + "endColumn": 44, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 47, + "column": 43, + "endLine": 47, + "endColumn": 47, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 49, + "column": 43, + "endLine": 49, + "endColumn": 47, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 51, + "column": 43, + "endLine": 51, + "endColumn": 47, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 54, + "column": 43, + "endLine": 54, + "endColumn": 47, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 57, + "column": 43, + "endLine": 57, + "endColumn": 47, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 60, + "column": 43, + "endLine": 60, + "endColumn": 47, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 63, + "column": 43, + "endLine": 63, + "endColumn": 48, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 43, + "endLine": 65, + "endColumn": 51, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + }, + { + "line": 67, + "column": 43, + "endLine": 67, + "endColumn": 51, + "problem": "InstanceOfFunction", + "suggest": "", + "rule": "\"instanceof\" operator can't be applied to function (arkts-no-instanceof-func)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/arkts-no-instanceof-func_positive.ets b/ets2panda/linter/test/main/arkts-no-instanceof-func_positive.ets new file mode 100644 index 0000000000..988bc94ef6 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-instanceof-func_positive.ets @@ -0,0 +1,55 @@ +/* + * 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. + */ + +export function foo3() { + +} + +export default function foo4() { + +} + +export function foo7() { + +} + +export namespace BB { + export function foo11() { + + } +} + +class A { + +} + +let a: A = new A(); +console.log('' + (a instanceof A)); + +class Person {} +const john = new Person(); +console.log('' + (john instanceof Person)); + +class Student extends Person {} +const alice = new Student(); +console.log('' + (alice instanceof Person)); + +const arr = [1, 2, 3]; +console.log('' + (arr instanceof Array)); +console.log('' + (arr instanceof Object)); + +const regex = /abc/; +console.log('' + (regex instanceof RegExp)); + diff --git a/ets2panda/linter/test/main/arkts-no-instanceof-func_positive.ets.ets.args.json b/ets2panda/linter/test/main/arkts-no-instanceof-func_positive.ets.ets.args.json new file mode 100644 index 0000000000..d8d3390ad9 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-instanceof-func_positive.ets.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-instanceof-func_positive.ets.json b/ets2panda/linter/test/main/arkts-no-instanceof-func_positive.ets.json new file mode 100644 index 0000000000..ca88f857e9 --- /dev/null +++ b/ets2panda/linter/test/main/arkts-no-instanceof-func_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