Skip to content

Commit 01ca100

Browse files
committed
Include the target symbol in search if location is propertyName or the import or export specifier dont specify "as" clause
Handles microsoft#7708
1 parent ace2285 commit 01ca100

2 files changed

Lines changed: 50 additions & 29 deletions

File tree

src/services/services.ts

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5611,8 +5611,19 @@ namespace ts {
56115611
};
56125612
}
56135613

5614-
function isImportSpecifierSymbol(symbol: Symbol) {
5615-
return (symbol.flags & SymbolFlags.Alias) && !!getDeclarationOfKind(symbol, SyntaxKind.ImportSpecifier);
5614+
function getImportOrExportSpecifierPropertyNameSymbolSpecifier(symbol: Symbol, location: Node): ImportOrExportSpecifier {
5615+
if (symbol.flags & SymbolFlags.Alias) {
5616+
const importOrExportSpecifier = <ImportOrExportSpecifier>forEach(symbol.declarations,
5617+
declaration => (declaration.kind === SyntaxKind.ImportSpecifier ||
5618+
declaration.kind === SyntaxKind.ExportSpecifier) ? declaration : undefined);
5619+
if (importOrExportSpecifier &&
5620+
// export { a }
5621+
(!importOrExportSpecifier.propertyName ||
5622+
// export {a as class } where a is location
5623+
importOrExportSpecifier.propertyName === location)) {
5624+
return importOrExportSpecifier;
5625+
}
5626+
}
56165627
}
56175628

56185629
function isObjectBindingPatternElementWithoutPropertyName(symbol: Symbol) {
@@ -6077,17 +6088,19 @@ namespace ts {
60776088
let result = [symbol];
60786089

60796090
// If the symbol is an alias, add what it aliases to the list
6080-
if (isImportSpecifierSymbol(symbol)) {
6081-
result.push(typeChecker.getAliasedSymbol(symbol));
6082-
}
6083-
6084-
// For export specifiers, the exported name can be referring to a local symbol, e.g.:
60856091
// import {a} from "mod";
6086-
// export {a as somethingElse}
6087-
// We want the *local* declaration of 'a' as declared in the import,
6088-
// *not* as declared within "mod" (or farther)
6089-
if (location.parent.kind === SyntaxKind.ExportSpecifier) {
6090-
result.push(typeChecker.getExportSpecifierLocalTargetSymbol(<ExportSpecifier>location.parent));
6092+
// export {a}
6093+
//// For export specifiers, the exported name can be referring to a local symbol, e.g.:
6094+
//// import {a} from "mod";
6095+
//// export {a as somethingElse}
6096+
//// We want the *local* declaration of 'a' as declared in the import,
6097+
//// *not* as declared within "mod" (or farther)
6098+
const importOrExportSpecifier = getImportOrExportSpecifierPropertyNameSymbolSpecifier(symbol, location);
6099+
if (importOrExportSpecifier) {
6100+
result = result.concat(populateSearchSymbolSet(
6101+
importOrExportSpecifier.kind === SyntaxKind.ImportSpecifier ?
6102+
typeChecker.getAliasedSymbol(symbol) :
6103+
typeChecker.getExportSpecifierLocalTargetSymbol(importOrExportSpecifier), location));
60916104
}
60926105

60936106
// If the location is in a context sensitive location (i.e. in an object literal) try
@@ -6212,23 +6225,13 @@ namespace ts {
62126225
}
62136226

62146227
// If the reference symbol is an alias, check if what it is aliasing is one of the search
6215-
// symbols.
6216-
if (isImportSpecifierSymbol(referenceSymbol)) {
6217-
const aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol);
6218-
if (searchSymbols.indexOf(aliasedSymbol) >= 0) {
6219-
return aliasedSymbol;
6220-
}
6221-
}
6222-
6223-
// For export specifiers, it can be a local symbol, e.g.
6224-
// import {a} from "mod";
6225-
// export {a as somethingElse}
6226-
// We want the local target of the export (i.e. the import symbol) and not the final target (i.e. "mod".a)
6227-
if (referenceLocation.parent.kind === SyntaxKind.ExportSpecifier) {
6228-
const aliasedSymbol = typeChecker.getExportSpecifierLocalTargetSymbol(<ExportSpecifier>referenceLocation.parent);
6229-
if (searchSymbols.indexOf(aliasedSymbol) >= 0) {
6230-
return aliasedSymbol;
6231-
}
6228+
// symbols but by looking up for related symbol of this alias so it can handle multiple level of indirectness.
6229+
const importOrExportSpecifier = getImportOrExportSpecifierPropertyNameSymbolSpecifier(referenceSymbol, referenceLocation);
6230+
if (importOrExportSpecifier) {
6231+
const aliasedSymbol = importOrExportSpecifier.kind === SyntaxKind.ImportSpecifier ?
6232+
typeChecker.getAliasedSymbol(referenceSymbol) :
6233+
typeChecker.getExportSpecifierLocalTargetSymbol(importOrExportSpecifier);
6234+
return getRelatedSymbol(searchSymbols, aliasedSymbol, referenceLocation);
62326235
}
62336236

62346237
// If the reference location is in an object literal, try to get the contextual type for the
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @Filename: a.ts
4+
////export var /*1*/a;
5+
6+
// @Filename: b.ts
7+
////import { /*2*/a } from './a';
8+
////export { /*3*/a };
9+
10+
goTo.file("a.ts");
11+
goTo.marker("1");
12+
13+
goTo.file("b.ts");
14+
goTo.marker("2");
15+
verify.referencesCountIs(3);
16+
17+
goTo.marker("3");
18+
verify.referencesCountIs(3);

0 commit comments

Comments
 (0)