Fix bug in importTracker: default and namespace imports are not exclusive (#24965)

This commit is contained in:
Andy
2018-06-15 12:15:39 -07:00
committed by GitHub
parent 581d2e8e96
commit e7e69ad4a2
3 changed files with 46 additions and 39 deletions

View File

@@ -103,23 +103,17 @@ namespace ts.FindAllReferences {
break; // TODO: GH#23879
case SyntaxKind.ImportEqualsDeclaration:
handleNamespaceImport(direct, direct.name, hasModifier(direct, ModifierFlags.Export));
handleNamespaceImport(direct, direct.name, hasModifier(direct, ModifierFlags.Export), /*alreadyAddedDirect*/ false);
break;
case SyntaxKind.ImportDeclaration:
directImports.push(direct);
const namedBindings = direct.importClause && direct.importClause.namedBindings;
if (namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport) {
handleNamespaceImport(direct, namedBindings.name);
handleNamespaceImport(direct, namedBindings.name, /*isReExport*/ false, /*alreadyAddedDirect*/ true);
}
else if (isDefaultImport(direct)) {
const sourceFileLike = getSourceFileLikeForImportDeclaration(direct);
if (!isAvailableThroughGlobal) {
addIndirectUser(sourceFileLike); // Add a check for indirect uses to handle synthetic default imports
}
directImports.push(direct);
}
else {
directImports.push(direct);
else if (!isAvailableThroughGlobal && isDefaultImport(direct)) {
addIndirectUser(getSourceFileLikeForImportDeclaration(direct)); // Add a check for indirect uses to handle synthetic default imports
}
break;
@@ -145,10 +139,10 @@ namespace ts.FindAllReferences {
}
}
function handleNamespaceImport(importDeclaration: ImportEqualsDeclaration | ImportDeclaration, name: Identifier, isReExport?: boolean): void {
function handleNamespaceImport(importDeclaration: ImportEqualsDeclaration | ImportDeclaration, name: Identifier, isReExport: boolean, alreadyAddedDirect: boolean): void {
if (exportKind === ExportKind.ExportEquals) {
// This is a direct import, not import-as-namespace.
directImports.push(importDeclaration);
if (!alreadyAddedDirect) directImports.push(importDeclaration);
}
else if (!isAvailableThroughGlobal) {
const sourceFileLike = getSourceFileLikeForImportDeclaration(importDeclaration);
@@ -247,34 +241,30 @@ namespace ts.FindAllReferences {
return;
}
const { importClause } = decl;
if (!importClause) {
return;
}
const { name, namedBindings } = decl.importClause || { name: undefined, namedBindings: undefined };
const { namedBindings } = importClause;
if (namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport) {
handleNamespaceImportLike(namedBindings.name);
return;
}
if (exportKind === ExportKind.Named) {
searchForNamedImport(namedBindings as NamedImports | undefined); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217)
}
else {
// `export =` might be imported by a default import if `--allowSyntheticDefaultImports` is on, so this handles both ExportKind.Default and ExportKind.ExportEquals
const { name } = importClause;
// If a default import has the same name as the default export, allow to rename it.
// Given `import f` and `export default function f`, we will rename both, but for `import g` we will rename just that.
if (name && (!isForRename || name.escapedText === symbolEscapedNameNoDefault(exportSymbol))) {
const defaultImportAlias = checker.getSymbolAtLocation(name)!;
addSearch(name, defaultImportAlias);
if (namedBindings) {
switch (namedBindings.kind) {
case SyntaxKind.NamespaceImport:
handleNamespaceImportLike(namedBindings.name);
break;
case SyntaxKind.NamedImports:
// 'default' might be accessed as a named import `{ default as foo }`.
if (exportKind === ExportKind.Named || exportKind === ExportKind.Default) {
searchForNamedImport(namedBindings);
}
break;
default:
Debug.assertNever(namedBindings);
}
}
// 'default' might be accessed as a named import `{ default as foo }`.
if (exportKind === ExportKind.Default) {
searchForNamedImport(namedBindings);
}
// `export =` might be imported by a default import if `--allowSyntheticDefaultImports` is on, so this handles both ExportKind.Default and ExportKind.ExportEquals.
// If a default import has the same name as the default export, allow to rename it.
// Given `import f` and `export default function f`, we will rename both, but for `import g` we will rename just that.
if (name && (exportKind === ExportKind.Default || exportKind === ExportKind.ExportEquals) && (!isForRename || name.escapedText === symbolEscapedNameNoDefault(exportSymbol))) {
const defaultImportAlias = checker.getSymbolAtLocation(name)!;
addSearch(name, defaultImportAlias);
}
}