diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index 5bc997f00867660ec064693b3c03d3a9d6bec0bd..11fe7370af480db23236519b586847ce7578352f 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -804,9 +804,9 @@ export class Autofixer { propAccessExpr ); // Create statement for the assignment expression, with or without parentheses based on the flag - const statement = needParentheses[index] - ? ts.factory.createExpressionStatement(ts.factory.createParenthesizedExpression(assignmentExpr)) - : ts.factory.createExpressionStatement(assignmentExpr); + const statement = needParentheses[index] ? + ts.factory.createExpressionStatement(ts.factory.createParenthesizedExpression(assignmentExpr)) : + ts.factory.createExpressionStatement(assignmentExpr); // Append the generated text for the destructuring assignment destructElementText += @@ -1081,7 +1081,7 @@ export class Autofixer { const moduleName = TsUtils.getModuleName(importDeclNode); const newPathParts = [moduleName ?? DEFAULT_MODULE_NAME, SRC_AND_MAIN, ...parts]; const newPath = newPathParts.join(PATH_SEPARATOR); - const newPathString = "'" + newPath + "'"; + const newPathString = '\'' + newPath + '\''; return [{ start: moduleSpecifier.getStart(), end: moduleSpecifier.getEnd(), replacementText: newPathString }]; } @@ -1095,7 +1095,7 @@ export class Autofixer { const newPathParts = [...beforeEts, SRC_AND_MAIN, ...afterEts]; const newPath = newPathParts.join(PATH_SEPARATOR); - const newPathString = "'" + newPath + "'"; + const newPathString = '\'' + newPath + '\''; return [{ start: moduleSpecifier.getStart(), end: moduleSpecifier.getEnd(), replacementText: newPathString }]; } @@ -1394,9 +1394,9 @@ export class Autofixer { fixVarDeclaration(node: ts.VariableDeclarationList): Autofix[] | undefined { const newNode = ts.factory.createVariableDeclarationList(node.declarations, ts.NodeFlags.Let); const text = this.printer.printNode(ts.EmitHint.Unspecified, newNode, node.getSourceFile()); - return this.canAutofixNoVar(node) - ? [{ start: node.getStart(), end: node.getEnd(), replacementText: text }] - : undefined; + return this.canAutofixNoVar(node) ? + [{ start: node.getStart(), end: node.getEnd(), replacementText: text }] : + undefined; } private getFixReturnTypeArrowFunction(funcLikeDecl: ts.FunctionLikeDeclaration, typeNode: ts.TypeNode): string { @@ -1517,14 +1517,15 @@ export class Autofixer { private static getReturnTypePosition(funcLikeDecl: ts.FunctionLikeDeclaration): number { if (funcLikeDecl.body) { + /* * Find position of the first node or token that follows parameters. * After that, iterate over child nodes in reverse order, until found * first closing parenthesis. */ - const postParametersPosition = ts.isArrowFunction(funcLikeDecl) - ? funcLikeDecl.equalsGreaterThanToken.getStart() - : funcLikeDecl.body.getStart(); + const postParametersPosition = ts.isArrowFunction(funcLikeDecl) ? + funcLikeDecl.equalsGreaterThanToken.getStart() : + funcLikeDecl.body.getStart(); const children = funcLikeDecl.getChildren(); for (let i = children.length - 1; i >= 0; i--) { @@ -1549,8 +1550,8 @@ export class Autofixer { ts.isTypeOfExpression(parent) || ts.isVoidExpression(parent) || ts.isAwaitExpression(parent) || - (ts.isCallExpression(parent) && node === parent.expression) || - (ts.isBinaryExpression(parent) && !isAssignmentOperator(parent.operatorToken)) + ts.isCallExpression(parent) && node === parent.expression || + ts.isBinaryExpression(parent) && !isAssignmentOperator(parent.operatorToken) ); } @@ -1886,6 +1887,7 @@ export class Autofixer { objectLiteralType: ts.Type | undefined ): Autofix[] | undefined { if (objectLiteralType) { + /* * Special case for object literal of Record type: fix object's property names * by replacing identifiers with string literals. @@ -2017,6 +2019,7 @@ export class Autofixer { newInterfaceName: string, objectLiteralExpr: ts.ObjectLiteralExpression ): Autofix { + /* * If object literal is initializing a variable or property, * then simply add new 'contextual' type to the declaration. @@ -2271,7 +2274,7 @@ export class Autofixer { } const typeDecl = TsUtils.getDeclaration(objectLiteralType.getSymbol()); - if (!typeDecl || (!ts.isClassDeclaration(typeDecl) && !ts.isInterfaceDeclaration(typeDecl)) || !typeDecl.name) { + if (!typeDecl || !ts.isClassDeclaration(typeDecl) && !ts.isInterfaceDeclaration(typeDecl) || !typeDecl.name) { return undefined; } @@ -3398,7 +3401,7 @@ export class Autofixer { replacement = ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression(callee.expression, ts.factory.createIdentifier(INVOKE_METHOD)), undefined, - [ts.factory.createStringLiteral(callee.name.getText()), ...(args || [])] + [ts.factory.createStringLiteral(callee.name.getText()), ...args || []] ); } else if (ts.isIdentifier(callee)) { // For expressions like foo() or bar(123) => foo.invoke(...) or bar.invoke(...) @@ -3543,11 +3546,11 @@ export class Autofixer { collectExistingNames(parentEnum: ts.EnumDeclaration, tsEnumMember: ts.EnumMember): Set { void this; return new Set( - parentEnum.members - .filter((m) => { + parentEnum.members. + filter((m) => { return m !== tsEnumMember; - }) - .map((m) => { + }). + map((m) => { const nameNode = m.name; if (ts.isStringLiteral(nameNode)) { const fix = this.fixLiteralAsPropertyNamePropertyName(nameNode); @@ -4176,7 +4179,7 @@ export class Autofixer { const propertyAccessExpr = node.expression as ts.PropertyAccessExpression; const newCallExpr = this.createJSInvokeCallExpression(propertyAccessExpr.expression, INVOKE_METHOD, [ ts.factory.createStringLiteral(propertyAccessExpr.name.text), - ...(newArgs || []) + ...newArgs || [] ]); if (!newCallExpr) { @@ -4185,7 +4188,7 @@ export class Autofixer { return this.printer.printNode(ts.EmitHint.Unspecified, newCallExpr, node.getSourceFile()); } default: { - const callExpr = this.createJSInvokeCallExpression(node.expression, INVOKE, [...(newArgs || [])]); + const callExpr = this.createJSInvokeCallExpression(node.expression, INVOKE, [...newArgs || []]); if (!callExpr) { return undefined; @@ -4203,7 +4206,7 @@ export class Autofixer { return `${base}.${GET_PROPERTY_BY_NAME}('${propName}')`; } else if (ts.isNewExpression(node)) { const newArgs = this.createArgs(node.arguments); - const newCallExpr = this.createJSInvokeCallExpression(node.expression, INSTANTIATE, [...(newArgs || [])]); + const newCallExpr = this.createJSInvokeCallExpression(node.expression, INSTANTIATE, [...newArgs || []]); if (!newCallExpr) { return undefined; @@ -4268,9 +4271,9 @@ export class Autofixer { this.modVarName = newVarName; } const propertyName = originalName || symbolName; - const constructDeclInfo: string[] = isLoad - ? [this.modVarName, ES_VALUE, LOAD] - : [symbolName, this.modVarName, GET_PROPERTY_BY_NAME]; + const constructDeclInfo: string[] = isLoad ? + [this.modVarName, ES_VALUE, LOAD] : + [symbolName, this.modVarName, GET_PROPERTY_BY_NAME]; const newVarDecl = Autofixer.createVariableForInteropImport( constructDeclInfo[0], constructDeclInfo[1], @@ -4655,18 +4658,18 @@ export class Autofixer { } private static createExactObjectInitializer(type: ts.TypeLiteralNode): ts.ObjectLiteralExpression { - const properties = type.members - .filter((member): member is ts.PropertySignature => { + const properties = type.members. + filter((member): member is ts.PropertySignature => { return ts.isPropertySignature(member); - }) - .map((member) => { + }). + map((member) => { const initializer = Autofixer.createInitializerForPropertySignature(member); if (initializer) { return ts.factory.createPropertyAssignment(member.name, initializer); } return null; - }) - .filter((property): property is ts.PropertyAssignment => { + }). + filter((property): property is ts.PropertyAssignment => { return property !== null; }); @@ -4840,16 +4843,16 @@ export class Autofixer { return undefined; } - const reference: ts.TypeReferenceNode[] = []; - typeNode.typeArguments?.forEach((arg) => { - return reference.push(ts.factory.createTypeReferenceNode(arg.getText())); - }); const srcFile = node.getSourceFile(); - const identifier = node.expression; - const args = node.arguments; - const newExpression = ts.factory.createNewExpression(identifier, reference, args); - const text = this.printer.printNode(ts.EmitHint.Unspecified, newExpression, srcFile); - return [{ start: node.getStart(), end: node.getEnd(), replacementText: text }]; + const typeArgsText = `<${typeNode.typeArguments?. + map((arg) => { + return this.printer.printNode(ts.EmitHint.Unspecified, arg, srcFile); + }). + join(', ')}>`; + + // Insert the type arguments immediately after the constructor name + const insertPos = node.expression.getEnd(); + return [{ start: insertPos, end: insertPos, replacementText: typeArgsText }]; } private getTypeNodeForNewExpression(node: ts.NewExpression): ts.TypeNode | undefined { @@ -4926,7 +4929,7 @@ export class Autofixer { const newCallExpr = this.createJSInvokeCallExpression(accessedProperty, INVOKE_METHOD, [ ts.factory.createStringLiteral(ident.text), - ...(newArgs || []) + ...newArgs || [] ]); if (!newCallExpr) { 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..c719ad5cbfbdd83a3c8e8997249d78758e1e0fbf 100644 --- a/ets2panda/linter/test/main/func_inferred_type_args_2.ets +++ b/ets2panda/linter/test/main/func_inferred_type_args_2.ets @@ -37,7 +37,7 @@ repairableC.repairableSet = new Set(); repairableC.repairableMap = new Map(); MyClass.repairableStaticMap = new Map(); -const promise: Promise = new Promise(()=> {return ''}); +const promise: Promise = new Promise(() => { return ''; }); function testA(): Map { return new Map(); @@ -72,3 +72,8 @@ class MyClassB { return new Set(); } } + +const testMap: Map = new Map([ + ['123', 1], // my comment 1 + ['sfe', 2] // my comment 2 +]); 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..5e8544d078b89ef267ddfb32030f0337effa8d66 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 @@ -248,7 +248,7 @@ "line": 40, "column": 34, "endLine": 40, - "endColumn": 63, + "endColumn": 67, "problem": "GenericCallNoTypeArgs", "suggest": "", "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", @@ -453,6 +453,36 @@ "suggest": "", "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" - } + }, + { + "line": 76, + "column": 38, + "endLine": 79, + "endColumn": 3, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 77, + "column": 11, + "endLine": 77, + "endColumn": 12, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 78, + "column": 11, + "endLine": 78, + "endColumn": 12, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "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..0d40aaa70a5710cb33bc82fdcfe123ece0395317 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 @@ -42,9 +42,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 676, - "end": 687, - "replacementText": "new Array()", + "start": 685, + "end": 685, + "replacementText": "", "line": 17, "column": 36, "endLine": 17, @@ -63,9 +63,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 705, - "end": 716, - "replacementText": "new Array()", + "start": 714, + "end": 714, + "replacementText": "", "line": 18, "column": 17, "endLine": 18, @@ -114,9 +114,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 796, - "end": 805, - "replacementText": "new Map()", + "start": 803, + "end": 803, + "replacementText": "", "line": 21, "column": 44, "endLine": 21, @@ -135,9 +135,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 823, - "end": 832, - "replacementText": "new Map()", + "start": 830, + "end": 830, + "replacementText": "", "line": 22, "column": 17, "endLine": 22, @@ -206,9 +206,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 994, - "end": 1003, - "replacementText": "new Map string[]>()", + "start": 1001, + "end": 1001, + "replacementText": " string[]>", "line": 27, "column": 55, "endLine": 27, @@ -227,9 +227,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 1065, - "end": 1074, - "replacementText": "new Map string[]>()", + "start": 1072, + "end": 1072, + "replacementText": " string[]>", "line": 28, "column": 61, "endLine": 28, @@ -268,9 +268,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 1215, - "end": 1228, - "replacementText": "new MyClass()", + "start": 1226, + "end": 1226, + "replacementText": "", "line": 34, "column": 38, "endLine": 34, @@ -299,9 +299,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 1298, - "end": 1307, - "replacementText": "new Set()", + "start": 1305, + "end": 1305, + "replacementText": "", "line": 36, "column": 29, "endLine": 36, @@ -320,9 +320,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 1337, - "end": 1346, - "replacementText": "new Map string[]>()", + "start": 1344, + "end": 1344, + "replacementText": " string[]>", "line": 37, "column": 29, "endLine": 37, @@ -341,9 +341,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 1378, - "end": 1387, - "replacementText": "new Map string[]>()", + "start": 1385, + "end": 1385, + "replacementText": " string[]>", "line": 38, "column": 31, "endLine": 38, @@ -358,17 +358,17 @@ "line": 40, "column": 34, "endLine": 40, - "endColumn": 63, + "endColumn": 67, "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 1423, - "end": 1452, - "replacementText": "new Promise(() => { return ''; })", + "start": 1434, + "end": 1434, + "replacementText": "", "line": 40, "column": 34, "endLine": 40, - "endColumn": 63 + "endColumn": 67 } ], "suggest": "", @@ -393,9 +393,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 1504, - "end": 1513, - "replacementText": "new Map()", + "start": 1515, + "end": 1515, + "replacementText": "", "line": 43, "column": 10, "endLine": 43, @@ -424,9 +424,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 1582, - "end": 1591, - "replacementText": "new Map()", + "start": 1593, + "end": 1593, + "replacementText": "", "line": 47, "column": 10, "endLine": 47, @@ -515,9 +515,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 1798, - "end": 1807, - "replacementText": "new Map()", + "start": 1809, + "end": 1809, + "replacementText": "", "line": 60, "column": 12, "endLine": 60, @@ -546,9 +546,9 @@ "problem": "GenericCallNoTypeArgs", "autofix": [ { - "start": 1873, - "end": 1882, - "replacementText": "new Map()", + "start": 1884, + "end": 1884, + "replacementText": "", "line": 64, "column": 12, "endLine": 64, @@ -618,6 +618,69 @@ "suggest": "", "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" - } + }, + { + "line": 76, + "column": 38, + "endLine": 79, + "endColumn": 3, + "problem": "GenericCallNoTypeArgs", + "autofix": [ + { + "start": 2074, + "end": 2074, + "replacementText": "", + "line": 76, + "column": 38, + "endLine": 79, + "endColumn": 3 + } + ], + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 77, + "column": 11, + "endLine": 77, + "endColumn": 12, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 2087, + "end": 2088, + "replacementText": "1.0", + "line": 77, + "column": 11, + "endLine": 77, + "endColumn": 12 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 78, + "column": 11, + "endLine": 78, + "endColumn": 12, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 2117, + "end": 2118, + "replacementText": "2.0", + "line": 78, + "column": 11, + "endLine": 78, + "endColumn": 12 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "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..9058cfd5c7b428d2e425646a38beeb86da3544d9 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,8 @@ class MyClassB { return new Set(); } } + +const testMap: Map = new Map([ + ['123', 1.0], // my comment 1 + ['sfe', 2.0] // my comment 2 +]);