refactorConvertToEs6Module: Preserve quote style of imports (#22929)

This commit is contained in:
Andy
2018-03-27 17:01:31 -07:00
committed by GitHub
parent 07a890dbbb
commit b9f48c1d5d
3 changed files with 23 additions and 14 deletions

View File

@@ -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<Node> {
function convertPropertyAccessImport(name: BindingName, propertyName: string, moduleSpecifier: StringLiteralLike, identifiers: Identifiers): ReadonlyArray<Node> {
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<Node> {
function convertSingleIdentifierImport(file: SourceFile, name: Identifier, moduleSpecifier: StringLiteralLike, changes: textChanges.ChangeTracker, checker: TypeChecker, identifiers: Identifiers): ReadonlyArray<Node> {
const nameSymbol = checker.getSymbolAtLocation(name);
// Maps from module property name to name actually used. (The same if there isn't shadowing.)
const namedBindingsNames = createMap<string>();
@@ -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<ImportSpecifier> | undefined, moduleSpecifier: string): ImportDeclaration {
return makeImportDeclaration(name, namedImports, createLiteral(moduleSpecifier));
function makeImport(name: Identifier | undefined, namedImports: ReadonlyArray<ImportSpecifier> | undefined, moduleSpecifier: StringLiteralLike): ImportDeclaration {
return makeImportDeclaration(name, namedImports, moduleSpecifier);
}
export function makeImportDeclaration(name: Identifier, namedImports: ReadonlyArray<ImportSpecifier> | undefined, moduleSpecifier: Expression) {

View File

@@ -5,7 +5,7 @@
// @allowJs: true
// @Filename: /a.js
/////*a*/require/*b*/("foo");
////require("foo");
verify.codeFix({
description: "Convert to ES6 module",

View File

@@ -0,0 +1,10 @@
/// <reference path='fourslash.ts' />
// @allowJs: true
// @Filename: /a.js
////const a = require('a');
verify.codeFix({
description: "Convert to ES6 module",
newFileContent: "import a from 'a';",
});