From e11cd25e54cc84a828237a81e7ee42ddcc375414 Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Mon, 14 Jul 2025 11:44:26 +0800 Subject: [PATCH] Fix for GenericCallNoTypeArgs Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICJQD9 Test scenarios: fix bug Signed-off-by: ZhongNing --- .../linter/src/lib/autofixes/Autofixer.ts | 97 +++++++++++++---- .../test/main/func_inferred_type_args_3.ets | 43 ++++++++ .../func_inferred_type_args_3.ets.args.json | 21 ++++ .../func_inferred_type_args_3.ets.arkts2.json | 68 ++++++++++++ ...func_inferred_type_args_3.ets.autofix.json | 101 ++++++++++++++++++ .../main/func_inferred_type_args_3.ets.json | 17 +++ .../func_inferred_type_args_3.ets.migrate.ets | 43 ++++++++ ...func_inferred_type_args_3.ets.migrate.json | 38 +++++++ .../test/main/func_inferred_type_args_ts.ts | 21 ++++ .../main/func_inferred_type_args_ts.ts.json | 17 +++ .../test/main/func_inferred_type_args_ts2.ts | 24 +++++ .../main/func_inferred_type_args_ts2.ts.json | 17 +++ 12 files changed, 489 insertions(+), 18 deletions(-) create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.args.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.arkts2.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.autofix.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.ets create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_ts.ts create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_ts.ts.json create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_ts2.ts create mode 100644 ets2panda/linter/test/main/func_inferred_type_args_ts2.ts.json diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index bca8d8304e..db2c5749d5 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -62,6 +62,8 @@ import { IS_INSTANCE_OF } from '../utils/consts/InteropAPI'; import { ESLIB_SHAREDARRAYBUFFER } from '../utils/consts/ConcurrentAPI'; +import path from 'node:path'; +import { isStdLibrarySymbol } from '../utils/functions/IsStdLibrary'; const UNDEFINED_NAME = 'undefined'; @@ -4906,12 +4908,10 @@ export class Autofixer { } const srcFile = node.getSourceFile(); - const typeArgsText = `<${typeNode.typeArguments?. - map((arg) => { - return this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, arg, srcFile); - }). - join(', ')}>`; - // Insert the type arguments immediately after the constructor name + const typeArgsText = this.printGenericCallTypeArgs(srcFile, typeNode.typeArguments); + if (!typeArgsText) { + return undefined; + } const insertPos = node.expression.getEnd(); return [{ start: insertPos, end: insertPos, replacementText: typeArgsText }]; } @@ -4922,7 +4922,10 @@ export class Autofixer { ): Autofix[] | undefined { const elementTypeNode = arrayTypeNode.elementType; const srcFile = node.getSourceFile(); - const typeArgsText = `<${this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, elementTypeNode, srcFile)}>`; + const typeArgsText = this.printGenericCallTypeArgs(srcFile, elementTypeNode); + if (!typeArgsText) { + return undefined; + } const insertPos = node.expression.getEnd(); return [{ start: insertPos, end: insertPos, replacementText: typeArgsText }]; } @@ -4939,12 +4942,10 @@ export class Autofixer { const matchingType = matchingTypes[0]; if (matchingType.typeArguments) { const srcFile = node.getSourceFile(); - const typeArgsText = `<${matchingType.typeArguments. - map((arg) => { - return this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, arg, srcFile); - }). - join(', ')}>`; - + const typeArgsText = this.printGenericCallTypeArgs(srcFile, matchingType.typeArguments); + if (!typeArgsText) { + return undefined; + } const insertPos = node.expression.getEnd(); return [{ start: insertPos, end: insertPos, replacementText: typeArgsText }]; } @@ -4952,6 +4953,67 @@ export class Autofixer { return undefined; } + private printGenericCallTypeArgs( + sourceFile: ts.SourceFile, + typeArg: ts.TypeNode | readonly ts.Node[] | undefined + ): string | undefined { + if (Array.isArray(typeArg)) { + if ( + typeArg.some((arg) => { + return !this.isTypeArgumentAccessible(sourceFile, arg as ts.TypeNode); + }) + ) { + return undefined; + } + return `<${typeArg. + map((arg) => { + return this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, arg, sourceFile); + }). + join(', ')}>`; + } + if (!typeArg || !this.isTypeArgumentAccessible(sourceFile, typeArg as ts.TypeNode)) { + return undefined; + } + + return `<${this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, typeArg as ts.TypeNode, sourceFile)}>`; + } + + private isTypeArgumentAccessible(sourceFile: ts.SourceFile, arg: ts.TypeNode): boolean { + const type = this.typeChecker.getTypeFromTypeNode(arg); + const symbol = type.symbol || type.aliasSymbol; + const decl = TsUtils.getDeclaration(symbol); + const fileName = decl?.getSourceFile().fileName; + const isStdLib = isStdLibrarySymbol(symbol); + const isMatchPathOnSourceAndDecl = decl && path.normalize(sourceFile.fileName) === path.normalize(fileName!); + if (!decl || isMatchPathOnSourceAndDecl || isStdLib) { + return true; + } + let result = false; + ts.forEachChild(sourceFile, (node) => { + if (ts.isImportDeclaration(node)) { + if (node.importClause?.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) { + node.importClause.namedBindings.elements.some((element) => { + result = this.isTypeArgImport(arg, element.name, symbol); + return result; + }); + } + if (node.importClause?.name) { + result = this.isTypeArgImport(arg, node.importClause.name, symbol); + } + } + return result; + }); + return result; + } + + private isTypeArgImport(arg: ts.Node, importName: ts.Identifier, typeArgSym: ts.Symbol): boolean { + if (arg.getText() !== importName.text) { + return false; + } + const importSym = this.utils.trueSymbolAtLocation(importName); + return importSym === typeArgSym; + } + private generateGenericTypeArgumentsAutofix( node: ts.NewExpression, typeArgs: ts.TypeReferenceNode[] @@ -4970,11 +5032,10 @@ export class Autofixer { if (hasAnyType) { return undefined; } - const typeArgsText = `<${typeArgs?. - map((arg) => { - return this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, arg, srcFile); - }). - join(', ')}>`; + const typeArgsText = this.printGenericCallTypeArgs(srcFile, typeArgs); + if (!typeArgsText) { + return undefined; + } return [{ start: identifier.getEnd(), end: identifier.getEnd(), replacementText: typeArgsText }]; } diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets b/ets2panda/linter/test/main/func_inferred_type_args_3.ets new file mode 100644 index 0000000000..0425eba064 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets @@ -0,0 +1,43 @@ +/* + * 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 {A} from './func_inferred_type_args_ts'; +import B from './func_inferred_type_args_ts' +import A2 from './func_inferred_type_args_ts2' +import {A3} from './func_inferred_type_args_ts2' +import { HashMap } from '@kit.ArkTS'; + +function test() { + const a = new A(); + a.map = new Map(); //error +} +function test2() { + const a = new A2(); + a.map = new Map(); //error +} +function test3() { + const a = new A3(); + a.map = new Map(); //error +} + +class A4 { + id?: string; + map?: HashMap; +} +class Demo{} + +function test4() { + const a = new A4(); + a.map = new HashMap(); //error +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.args.json b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.args.json new file mode 100644 index 0000000000..30973c00a2 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.args.json @@ -0,0 +1,21 @@ +{ + "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": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.arkts2.json b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.arkts2.json new file mode 100644 index 0000000000..868ccdbc43 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.arkts2.json @@ -0,0 +1,68 @@ +{ + "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": 23, + "column": 11, + "endLine": 23, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 11, + "endLine": 27, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 11, + "endLine": 31, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 15, + "endLine": 42, + "endColumn": 22, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 11, + "endLine": 42, + "endColumn": 24, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.autofix.json b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.autofix.json new file mode 100644 index 0000000000..6c9b2975d9 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.autofix.json @@ -0,0 +1,101 @@ +{ + "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": 23, + "column": 11, + "endLine": 23, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "autofix": [ + { + "start": 888, + "end": 888, + "replacementText": "", + "line": 23, + "column": 11, + "endLine": 23, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 11, + "endLine": 27, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 11, + "endLine": 31, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "autofix": [ + { + "start": 1032, + "end": 1032, + "replacementText": "", + "line": 31, + "column": 11, + "endLine": 31, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 15, + "endLine": 42, + "endColumn": 22, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 11, + "endLine": 42, + "endColumn": 24, + "problem": "GenericCallNoTypeArgs", + "autofix": [ + { + "start": 1183, + "end": 1183, + "replacementText": "", + "line": 42, + "column": 11, + "endLine": 42, + "endColumn": 24 + } + ], + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.json b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.json new file mode 100644 index 0000000000..b7a8809e02 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.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 diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.ets b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.ets new file mode 100644 index 0000000000..c038713ec9 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.ets @@ -0,0 +1,43 @@ +/* + * 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 {A} from './func_inferred_type_args_ts'; +import B from './func_inferred_type_args_ts' +import A2 from './func_inferred_type_args_ts2' +import {A3} from './func_inferred_type_args_ts2' +import { HashMap } from '@kit.ArkTS'; + +function test() { + const a = new A(); + a.map = new Map(); //error +} +function test2() { + const a = new A2(); + a.map = new Map(); //error +} +function test3() { + const a = new A3(); + a.map = new Map(); //error +} + +class A4 { + id?: string; + map?: HashMap; +} +class Demo{} + +function test4() { + const a = new A4(); + a.map = new HashMap(); //error +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.json b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.json new file mode 100644 index 0000000000..f7a8d2c4bd --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_3.ets.migrate.json @@ -0,0 +1,38 @@ +{ + "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": 11, + "endLine": 27, + "endColumn": 20, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 15, + "endLine": 42, + "endColumn": 22, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_ts.ts b/ets2panda/linter/test/main/func_inferred_type_args_ts.ts new file mode 100644 index 0000000000..59435fad58 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_ts.ts @@ -0,0 +1,21 @@ +/* + * 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 class A { + id?: string; + map?: Map; +} + +export default class B {} +export class C {} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_ts.ts.json b/ets2panda/linter/test/main/func_inferred_type_args_ts.ts.json new file mode 100644 index 0000000000..b7a8809e02 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_ts.ts.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 diff --git a/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts b/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts new file mode 100644 index 0000000000..aedcb256cb --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts @@ -0,0 +1,24 @@ +/* + * 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 {C} from './func_inferred_type_args_ts' +import B from './func_inferred_type_args_ts' +export default class A2 { + id?: string; + map?: Map; +} +export class A3 { + id?: string; + map?: Map; +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts.json b/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts.json new file mode 100644 index 0000000000..b7a8809e02 --- /dev/null +++ b/ets2panda/linter/test/main/func_inferred_type_args_ts2.ts.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