diff --git a/src/services/codefixes/convertToEs6Module.ts b/src/services/codefixes/convertToEs6Module.ts index b39f22be177af..23444af22ffad 100644 --- a/src/services/codefixes/convertToEs6Module.ts +++ b/src/services/codefixes/convertToEs6Module.ts @@ -20,8 +20,7 @@ namespace ts.codefix { function fixImportOfModuleExports(importingFile: SourceFile, exportingFile: SourceFile, changes: textChanges.ChangeTracker) { for (const moduleSpecifier of importingFile.imports) { - const { text } = moduleSpecifier; - const imported = getResolvedModule(importingFile, text); + const imported = getResolvedModule(importingFile, moduleSpecifier.text); if (!imported || imported.resolvedFileName !== exportingFile.fileName) { continue; } @@ -29,7 +28,7 @@ namespace ts.codefix { const importNode = importFromModuleSpecifier(moduleSpecifier); switch (importNode.kind) { case SyntaxKind.ImportEqualsDeclaration: - changes.replaceNode(importingFile, importNode, makeImport(importNode.name, /*namedImports*/ undefined, text)); + changes.replaceNode(importingFile, importNode, makeImport(importNode.name, /*namedImports*/ undefined, moduleSpecifier)); break; case SyntaxKind.CallExpression: if (isRequireCall(importNode, /*checkArgumentIsStringLiteralLike*/ false)) { @@ -111,7 +110,7 @@ namespace ts.codefix { case SyntaxKind.CallExpression: { if (isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true)) { // For side-effecting require() call, just make a side-effecting import. - changes.replaceNode(sourceFile, statement, makeImport(/*name*/ undefined, /*namedImports*/ undefined, expression.arguments[0].text)); + changes.replaceNode(sourceFile, statement, makeImport(/*name*/ undefined, /*namedImports*/ undefined, expression.arguments[0])); } return false; } @@ -139,11 +138,11 @@ namespace ts.codefix { } if (isRequireCall(initializer, /*checkArgumentIsStringLiteralLike*/ true)) { foundImport = true; - return convertSingleImport(sourceFile, name, initializer.arguments[0].text, changes, checker, identifiers, target); + return convertSingleImport(sourceFile, name, initializer.arguments[0], changes, checker, identifiers, target); } else if (isPropertyAccessExpression(initializer) && isRequireCall(initializer.expression, /*checkArgumentIsStringLiteralLike*/ true)) { foundImport = true; - return convertPropertyAccessImport(name, initializer.name.text, initializer.expression.arguments[0].text, identifiers); + return convertPropertyAccessImport(name, initializer.name.text, initializer.expression.arguments[0], identifiers); } else { // Move it out to its own variable statement. @@ -157,7 +156,7 @@ namespace ts.codefix { } /** Converts `const name = require("moduleSpecifier").propertyName` */ - function convertPropertyAccessImport(name: BindingName, propertyName: string, moduleSpecifier: string, identifiers: Identifiers): ReadonlyArray { + function convertPropertyAccessImport(name: BindingName, propertyName: string, moduleSpecifier: StringLiteralLike, identifiers: Identifiers): ReadonlyArray { switch (name.kind) { case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: { @@ -340,7 +339,7 @@ namespace ts.codefix { function convertSingleImport( file: SourceFile, name: BindingName, - moduleSpecifier: string, + moduleSpecifier: StringLiteralLike, changes: textChanges.ChangeTracker, checker: TypeChecker, identifiers: Identifiers, @@ -362,7 +361,7 @@ namespace ts.codefix { import x from "x"; const [a, b, c] = x; */ - const tmp = makeUniqueName(moduleSpecifierToValidIdentifier(moduleSpecifier, target), identifiers); + const tmp = makeUniqueName(moduleSpecifierToValidIdentifier(moduleSpecifier.text, target), identifiers); return [ makeImport(createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier), makeConst(/*modifiers*/ undefined, getSynthesizedDeepClone(name), createIdentifier(tmp)), @@ -379,7 +378,7 @@ namespace ts.codefix { * Convert `import x = require("x").` * Also converts uses like `x.y()` to `y()` and uses a named import. */ - function convertSingleIdentifierImport(file: SourceFile, name: Identifier, moduleSpecifier: string, changes: textChanges.ChangeTracker, checker: TypeChecker, identifiers: Identifiers): ReadonlyArray { + function convertSingleIdentifierImport(file: SourceFile, name: Identifier, moduleSpecifier: StringLiteralLike, changes: textChanges.ChangeTracker, checker: TypeChecker, identifiers: Identifiers): ReadonlyArray { const nameSymbol = checker.getSymbolAtLocation(name); // Maps from module property name to name actually used. (The same if there isn't shadowing.) const namedBindingsNames = createMap(); @@ -486,14 +485,14 @@ namespace ts.codefix { getSynthesizedDeepClones(cls.members)); } - function makeSingleImport(localName: string, propertyName: string, moduleSpecifier: string): ImportDeclaration { + function makeSingleImport(localName: string, propertyName: string, moduleSpecifier: StringLiteralLike): ImportDeclaration { return propertyName === "default" ? makeImport(createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier) : makeImport(/*name*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier); } - function makeImport(name: Identifier | undefined, namedImports: ReadonlyArray | undefined, moduleSpecifier: string): ImportDeclaration { - return makeImportDeclaration(name, namedImports, createLiteral(moduleSpecifier)); + function makeImport(name: Identifier | undefined, namedImports: ReadonlyArray | undefined, moduleSpecifier: StringLiteralLike): ImportDeclaration { + return makeImportDeclaration(name, namedImports, moduleSpecifier); } export function makeImportDeclaration(name: Identifier, namedImports: ReadonlyArray | undefined, moduleSpecifier: Expression) { diff --git a/tests/cases/fourslash/refactorConvertToEs6Module_import_sideEffect.ts b/tests/cases/fourslash/refactorConvertToEs6Module_import_sideEffect.ts index f729f0a9815ad..28caeaf241179 100644 --- a/tests/cases/fourslash/refactorConvertToEs6Module_import_sideEffect.ts +++ b/tests/cases/fourslash/refactorConvertToEs6Module_import_sideEffect.ts @@ -5,7 +5,7 @@ // @allowJs: true // @Filename: /a.js -/////*a*/require/*b*/("foo"); +////require("foo"); verify.codeFix({ description: "Convert to ES6 module", diff --git a/tests/cases/fourslash/refactorConvertToEs6Module_preserveQuotes.ts b/tests/cases/fourslash/refactorConvertToEs6Module_preserveQuotes.ts new file mode 100644 index 0000000000000..5260dc14fbc89 --- /dev/null +++ b/tests/cases/fourslash/refactorConvertToEs6Module_preserveQuotes.ts @@ -0,0 +1,10 @@ +/// + +// @allowJs: true +// @Filename: /a.js +////const a = require('a'); + +verify.codeFix({ + description: "Convert to ES6 module", + newFileContent: "import a from 'a';", +});