diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index 5bc997f00867660ec064693b3c03d3a9d6bec0bd..54bce94e7ffe340b9a2e9a5a0789f46116901bfb 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -4830,13 +4830,31 @@ export class Autofixer { } } } - return fixes; } + private tryGetContextualAutofix(node: ts.NewExpression): Autofix[] | undefined { + const contextualType = this.typeChecker.getContextualType(node); + if (!contextualType) { + return undefined; + } + + const typeArgs = Autofixer.getTypeArgumentsFromType(contextualType); + if (typeArgs.length === 0) { + return undefined; + } + const reference = typeArgs.map((arg) => { + return ts.factory.createTypeReferenceNode(this.typeChecker.typeToString(arg)); + }); + return this.createAutofix(node, reference); + } + fixGenericCallNoTypeArgs(node: ts.NewExpression): Autofix[] | undefined { const typeNode = this.getTypeNodeForNewExpression(node); - if (!typeNode || !ts.isTypeReferenceNode(typeNode) || typeNode.typeName.getText() !== node.expression.getText()) { + if (!typeNode) { + return this.tryGetContextualAutofix(node); + } + if (!ts.isTypeReferenceNode(typeNode) || typeNode.typeName.getText() !== node.expression.getText()) { return undefined; } @@ -4852,6 +4870,35 @@ export class Autofixer { return [{ start: node.getStart(), end: node.getEnd(), replacementText: text }]; } + private createAutofix(node: ts.NewExpression, typeArgs: ts.TypeReferenceNode[]): Autofix[] | undefined { + const srcFile = node.getSourceFile(); + const identifier = node.expression; + const args = node.arguments; + const hasValidArgs = typeArgs.some((arg) => { + return arg?.typeName && ts.isIdentifier(arg.typeName); + }); + if (!hasValidArgs) { + return undefined; + } + const hasAnyType = typeArgs.some((arg) => { + return ts.isIdentifier(arg?.typeName) && arg.typeName.text === 'any'; + }); + if (hasAnyType) { + return undefined; + } + const newExpression = ts.factory.createNewExpression(identifier, typeArgs, args); + const text = this.printer.printNode(ts.EmitHint.Unspecified, newExpression, srcFile); + return [{ start: node.getStart(), end: node.getEnd(), replacementText: text }]; + } + + static getTypeArgumentsFromType(type: ts.Type): ts.Type[] { + const typeReference = type as ts.TypeReference; + if (typeReference.typeArguments) { + return [...typeReference.typeArguments]; + } + return []; + } + private getTypeNodeForNewExpression(node: ts.NewExpression): ts.TypeNode | undefined { if (ts.isVariableDeclaration(node.parent) || ts.isPropertyDeclaration(node.parent)) { return node.parent.type; diff --git a/ets2panda/linter/test/main/func_inferred_type_args_2.ets b/ets2panda/linter/test/main/func_inferred_type_args_2.ets index 636e016aeadd253445251567c7f09fa7da3bd996..1b6f78ae1459a3f3adf55b0ce610ea3d2f49e97f 100644 --- a/ets2panda/linter/test/main/func_inferred_type_args_2.ets +++ b/ets2panda/linter/test/main/func_inferred_type_args_2.ets @@ -72,3 +72,6 @@ class MyClassB { return new Set(); } } +let a : Array = new Array(); +function foo(arr:Array) { } +foo(new Array()); \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_2.ets.arkts2.json b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.arkts2.json index 10523de7b5e1276e0e5c2da57fadc4ae7c4b59b4..fd18d0b65c8176e76795148c784cb64d7c5f5d94 100644 --- a/ets2panda/linter/test/main/func_inferred_type_args_2.ets.arkts2.json +++ b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.arkts2.json @@ -453,6 +453,26 @@ "suggest": "", "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" + }, + { + "line": 75, + "column": 25, + "endLine": 75, + "endColumn": 36, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 77, + "column": 5, + "endLine": 77, + "endColumn": 16, + "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_2.ets.autofix.json b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.autofix.json index 08fe89b9bc8a0dafe7c366644d88f0da1e2b61b5..a1291e109b7b705cfbcb5e735249564a739b51ee 100644 --- a/ets2panda/linter/test/main/func_inferred_type_args_2.ets.autofix.json +++ b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.autofix.json @@ -618,6 +618,48 @@ "suggest": "", "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" + }, + { + "line": 75, + "column": 25, + "endLine": 75, + "endColumn": 36, + "problem": "GenericCallNoTypeArgs", + "autofix": [ + { + "start": 2049, + "end": 2060, + "replacementText": "new Array()", + "line": 75, + "column": 25, + "endLine": 75, + "endColumn": 36 + } + ], + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 77, + "column": 5, + "endLine": 77, + "endColumn": 16, + "problem": "GenericCallNoTypeArgs", + "autofix": [ + { + "start": 2102, + "end": 2113, + "replacementText": "new Array()", + "line": 77, + "column": 5, + "endLine": 77, + "endColumn": 16 + } + ], + "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_2.ets.migrate.ets b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.migrate.ets index 01a5d89f97c06ce79226ada89136f658d4d19bdb..680f872af762020865a6c725184564adb9220f6a 100644 --- a/ets2panda/linter/test/main/func_inferred_type_args_2.ets.migrate.ets +++ b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.migrate.ets @@ -72,3 +72,6 @@ class MyClassB { return new Set(); } } +let a : Array = new Array(); +function foo(arr:Array) { } +foo(new Array()); \ No newline at end of file