11/* @internal */
22namespace ts . FindAllReferences {
3- export function findReferencedSymbols ( typeChecker : TypeChecker , cancellationToken : CancellationToken , sourceFiles : SourceFile [ ] , sourceFile : SourceFile , position : number , findInStrings : boolean , findInComments : boolean ) : ReferencedSymbol [ ] | undefined {
3+ export function findReferencedSymbols ( typeChecker : TypeChecker , cancellationToken : CancellationToken , sourceFiles : SourceFile [ ] , sourceFile : SourceFile , position : number , findInStrings : boolean , findInComments : boolean , isForRename : boolean ) : ReferencedSymbol [ ] | undefined {
44 const node = getTouchingPropertyName ( sourceFile , position , /*includeJsDocComment*/ true ) ;
5- return getReferencedSymbolsForNode ( typeChecker , cancellationToken , node , sourceFiles , findInStrings , findInComments , /*implementations*/ false ) ;
5+ return getReferencedSymbolsForNode ( typeChecker , cancellationToken , node , sourceFiles , findInStrings , findInComments , isForRename ) ;
66 }
77
8- export function getReferencedSymbolsForNode ( typeChecker : TypeChecker , cancellationToken : CancellationToken , node : Node , sourceFiles : SourceFile [ ] , findInStrings : boolean , findInComments : boolean , implementations : boolean ) : ReferencedSymbol [ ] | undefined {
8+ export function getReferencedSymbolsForNode ( typeChecker : TypeChecker , cancellationToken : CancellationToken , node : Node , sourceFiles : SourceFile [ ] , findInStrings ? : boolean , findInComments ? : boolean , isForRename ?: boolean , implementations ? : boolean ) : ReferencedSymbol [ ] | undefined {
99 if ( ! implementations ) {
1010 const special = getReferencedSymbolsSpecial ( node , sourceFiles , typeChecker , cancellationToken ) ;
1111 if ( special ) {
@@ -33,11 +33,16 @@ namespace ts.FindAllReferences {
3333 return undefined ;
3434 }
3535
36- const aliasedSymbol = followAliasIfNecessary ( symbol , node , typeChecker ) ;
37- const isShorthandModule = ts . isShorthandAmbientModuleSymbol ( aliasedSymbol ) ;
38- // Don't follow alias for shorthand modules because we lose information that way.
39- if ( ! isShorthandModule ) {
40- symbol = aliasedSymbol ;
36+ const { symbol : aliasedSymbol , shorthandModuleSymbol } = followAliases ( symbol , node , typeChecker , isForRename ) ;
37+ symbol = aliasedSymbol ;
38+
39+ // Build the set of symbols to search for, initially it has only the current symbol
40+ const searchSymbols = populateSearchSymbolSet ( symbol , node , typeChecker , implementations ) ;
41+ if ( shorthandModuleSymbol ) {
42+ searchSymbols . push ( shorthandModuleSymbol ) ;
43+ }
44+ function isSearchedFor ( symbol : Symbol ) : boolean {
45+ return contains ( searchSymbols , symbol ) ;
4146 }
4247
4348 // Compute the meaning from the location and the symbol it references
@@ -48,12 +53,6 @@ namespace ts.FindAllReferences {
4853 const symbolToIndex : number [ ] = [ ] ;
4954 const inheritsFromCache : Map < boolean > = createMap < boolean > ( ) ;
5055
51- // Build the set of symbols to search for, initially it has only the current symbol
52- const searchSymbols = populateSearchSymbolSet ( symbol , node , typeChecker , implementations , isShorthandModule ? aliasedSymbol : undefined ) ;
53- function isSearchedFor ( symbol : Symbol ) : boolean {
54- return contains ( searchSymbols , symbol ) ;
55- }
56-
5756 // Get the text to search for.
5857 // Note: if this is an external module symbol, the name doesn't include quotes.
5958 const declaredName = stripQuotes ( getDeclaredName ( typeChecker , symbol , node ) ) ;
@@ -116,6 +115,31 @@ namespace ts.FindAllReferences {
116115 return undefined ;
117116 }
118117
118+ /**
119+ * Follows aliases to get to the original declaration of a symbol.
120+ * For a shorthand ambient module, we don't follow the alias to it, but we will need to add it to the set of search symbols.
121+ */
122+ function followAliases ( symbol : Symbol , node : Node , typeChecker : TypeChecker , isForRename : boolean ) : { symbol : Symbol , shorthandModuleSymbol ?: Symbol } {
123+ while ( true ) {
124+ // When renaming a default import, only rename in the current file
125+ if ( isForRename && isImportDefaultSymbol ( symbol ) ) {
126+ return { symbol } ;
127+ }
128+
129+ const aliasedSymbol = getAliasSymbolForPropertyNameSymbol ( symbol , node , typeChecker ) ;
130+ // Don't follow alias if it goes to unknown symbol. This can happen if it points to an untyped module.
131+ if ( ! aliasedSymbol || ! aliasedSymbol . declarations ) {
132+ return { symbol } ;
133+ }
134+
135+ if ( ts . isShorthandAmbientModuleSymbol ( aliasedSymbol ) ) {
136+ return { symbol, shorthandModuleSymbol : aliasedSymbol } ;
137+ }
138+
139+ symbol = aliasedSymbol ;
140+ }
141+ }
142+
119143 function sourceFileHasName ( sourceFile : SourceFile , name : string ) : boolean {
120144 return getNameTable ( sourceFile ) . get ( name ) !== undefined ;
121145 }
@@ -157,29 +181,30 @@ namespace ts.FindAllReferences {
157181 }
158182
159183 function getAliasSymbolForPropertyNameSymbol ( symbol : Symbol , location : Node , typeChecker : TypeChecker ) : Symbol | undefined {
160- if ( symbol . flags & SymbolFlags . Alias ) {
161- // Default import get alias
162- const defaultImport = getDeclarationOfKind ( symbol , SyntaxKind . ImportClause ) ;
163- if ( defaultImport ) {
164- return typeChecker . getAliasedSymbol ( symbol ) ;
165- }
184+ if ( ! ( symbol . flags & SymbolFlags . Alias ) ) {
185+ return undefined ;
186+ }
166187
167- const importOrExportSpecifier = < ImportOrExportSpecifier > forEach ( symbol . declarations ,
168- declaration => ( declaration . kind === SyntaxKind . ImportSpecifier ||
169- declaration . kind === SyntaxKind . ExportSpecifier ) ? declaration : undefined ) ;
170- if ( importOrExportSpecifier &&
171- // export { a }
172- ( ! importOrExportSpecifier . propertyName ||
173- // export {a as class } where a is location
174- importOrExportSpecifier . propertyName === location ) ) {
175- // If Import specifier -> get alias
176- // else Export specifier -> get local target
177- return importOrExportSpecifier . kind === SyntaxKind . ImportSpecifier ?
178- typeChecker . getAliasedSymbol ( symbol ) :
179- typeChecker . getExportSpecifierLocalTargetSymbol ( importOrExportSpecifier ) ;
180- }
188+ // Default import get alias
189+ const defaultImport = getDeclarationOfKind ( symbol , SyntaxKind . ImportClause ) ;
190+ if ( defaultImport ) {
191+ return typeChecker . getAliasedSymbol ( symbol ) ;
192+ }
193+
194+ const importOrExportSpecifier = < ImportOrExportSpecifier > forEach ( symbol . declarations ,
195+ declaration => ( declaration . kind === SyntaxKind . ImportSpecifier ||
196+ declaration . kind === SyntaxKind . ExportSpecifier ) ? declaration : undefined ) ;
197+ if ( importOrExportSpecifier &&
198+ // export { a }
199+ ( ! importOrExportSpecifier . propertyName ||
200+ // export {a as class } where a is location
201+ importOrExportSpecifier . propertyName === location ) ) {
202+ // If Import specifier -> get alias
203+ // else Export specifier -> get local target
204+ return importOrExportSpecifier . kind === SyntaxKind . ImportSpecifier ?
205+ typeChecker . getAliasedSymbol ( symbol ) :
206+ typeChecker . getExportSpecifierLocalTargetSymbol ( importOrExportSpecifier ) ;
181207 }
182- return undefined ;
183208 }
184209
185210 function followAliasIfNecessary ( symbol : Symbol , location : Node , typeChecker : TypeChecker ) : Symbol {
@@ -1022,9 +1047,9 @@ namespace ts.FindAllReferences {
10221047 }
10231048 }
10241049
1025- function populateSearchSymbolSet ( symbol : Symbol , location : Node , typeChecker : TypeChecker , implementations : boolean , aliasSymbol ?: Symbol ) : Symbol [ ] {
1050+ function populateSearchSymbolSet ( symbol : Symbol , location : Node , typeChecker : TypeChecker , implementations : boolean ) : Symbol [ ] {
10261051 // The search set contains at least the current symbol
1027- let result = [ symbol ] ;
1052+ const result = [ symbol ] ;
10281053
10291054 // If the location is name of property symbol from object literal destructuring pattern
10301055 // Search the property symbol
@@ -1037,10 +1062,6 @@ namespace ts.FindAllReferences {
10371062 }
10381063 }
10391064
1040- if ( aliasSymbol ) {
1041- result = result . concat ( populateSearchSymbolSet ( aliasSymbol , location , typeChecker , implementations ) ) ;
1042- }
1043-
10441065 // If the location is in a context sensitive location (i.e. in an object literal) try
10451066 // to get a contextual type for it, and add the property symbol from the contextual
10461067 // type to the search set
@@ -1072,7 +1093,7 @@ namespace ts.FindAllReferences {
10721093 // Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members
10731094 if ( symbol . valueDeclaration && symbol . valueDeclaration . kind === SyntaxKind . Parameter &&
10741095 isParameterPropertyDeclaration ( < ParameterDeclaration > symbol . valueDeclaration ) ) {
1075- result = result . concat ( typeChecker . getSymbolsOfParameterPropertyDeclaration ( < ParameterDeclaration > symbol . valueDeclaration , symbol . name ) ) ;
1096+ addRange ( result , typeChecker . getSymbolsOfParameterPropertyDeclaration ( < ParameterDeclaration > symbol . valueDeclaration , symbol . name ) ) ;
10761097 }
10771098
10781099 // If this is symbol of binding element without propertyName declaration in Object binding pattern
@@ -1447,4 +1468,8 @@ namespace ts.FindAllReferences {
14471468
14481469 return false ;
14491470 }
1471+
1472+ function isImportDefaultSymbol ( symbol : Symbol ) : boolean {
1473+ return symbol . declarations [ 0 ] . kind === SyntaxKind . ImportClause ;
1474+ }
14501475}
0 commit comments