Skip to content

Commit

Permalink
Allow qualified name for convert namespace import (#41592)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kingwl authored Dec 1, 2020
1 parent 0da5a7e commit 5581009
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 9 deletions.
25 changes: 16 additions & 9 deletions src/services/refactors/convertImport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,34 +73,33 @@ namespace ts.refactor {
function doChangeNamespaceToNamed(sourceFile: SourceFile, checker: TypeChecker, changes: textChanges.ChangeTracker, toConvert: NamespaceImport, allowSyntheticDefaultImports: boolean): void {
let usedAsNamespaceOrDefault = false;

const nodesToReplace: PropertyAccessExpression[] = [];
const nodesToReplace: (PropertyAccessExpression | QualifiedName)[] = [];
const conflictingNames = new Map<string, true>();

FindAllReferences.Core.eachSymbolReferenceInFile(toConvert.name, checker, sourceFile, id => {
if (!isPropertyAccessExpression(id.parent)) {
if (!isPropertyAccessOrQualifiedName(id.parent)) {
usedAsNamespaceOrDefault = true;
}
else {
const parent = cast(id.parent, isPropertyAccessExpression);
const exportName = parent.name.text;
const exportName = getRightOfPropertyAccessOrQualifiedName(id.parent).text;
if (checker.resolveName(exportName, id, SymbolFlags.All, /*excludeGlobals*/ true)) {
conflictingNames.set(exportName, true);
}
Debug.assert(parent.expression === id, "Parent expression should match id");
nodesToReplace.push(parent);
Debug.assert(getLeftOfPropertyAccessOrQualifiedName(id.parent) === id, "Parent expression should match id");
nodesToReplace.push(id.parent);
}
});

// We may need to change `mod.x` to `_x` to avoid a name conflict.
const exportNameToImportName = new Map<string, string>();

for (const propertyAccess of nodesToReplace) {
const exportName = propertyAccess.name.text;
for (const propertyAccessOrQualifiedName of nodesToReplace) {
const exportName = getRightOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName).text;
let importName = exportNameToImportName.get(exportName);
if (importName === undefined) {
exportNameToImportName.set(exportName, importName = conflictingNames.has(exportName) ? getUniqueName(exportName, sourceFile) : exportName);
}
changes.replaceNode(sourceFile, propertyAccess, factory.createIdentifier(importName));
changes.replaceNode(sourceFile, propertyAccessOrQualifiedName, factory.createIdentifier(importName));
}

const importSpecifiers: ImportSpecifier[] = [];
Expand All @@ -118,6 +117,14 @@ namespace ts.refactor {
}
}

function getRightOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName: PropertyAccessExpression | QualifiedName) {
return isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.name : propertyAccessOrQualifiedName.right;
}

function getLeftOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName: PropertyAccessExpression | QualifiedName) {
return isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.expression : propertyAccessOrQualifiedName.left;
}

function doChangeNamedToNamespace(sourceFile: SourceFile, checker: TypeChecker, changes: textChanges.ChangeTracker, toConvert: NamedImports): void {
const importDecl = toConvert.parent.parent;
const { moduleSpecifier } = importDecl;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/// <reference path='fourslash.ts' />

/////*a*/import * as m from "m";/*b*/
////declare const a: m.aa;
////declare const b: m.b;

goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert import",
actionName: "Convert namespace import to named imports",
actionDescription: "Convert namespace import to named imports",
newContent:
`import { aa, b as b_1 } from "m";
declare const a: aa;
declare const b: b_1;`,
});

0 comments on commit 5581009

Please sign in to comment.