1
1
/* @internal */
2
2
namespace 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 {
4
4
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 ) ;
6
6
}
7
7
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 {
9
9
if ( ! implementations ) {
10
10
const special = getReferencedSymbolsSpecial ( node , sourceFiles , typeChecker , cancellationToken ) ;
11
11
if ( special ) {
@@ -33,11 +33,16 @@ namespace ts.FindAllReferences {
33
33
return undefined ;
34
34
}
35
35
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 ) ;
41
46
}
42
47
43
48
// Compute the meaning from the location and the symbol it references
@@ -48,12 +53,6 @@ namespace ts.FindAllReferences {
48
53
const symbolToIndex : number [ ] = [ ] ;
49
54
const inheritsFromCache : Map < boolean > = createMap < boolean > ( ) ;
50
55
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
-
57
56
// Get the text to search for.
58
57
// Note: if this is an external module symbol, the name doesn't include quotes.
59
58
const declaredName = stripQuotes ( getDeclaredName ( typeChecker , symbol , node ) ) ;
@@ -116,6 +115,31 @@ namespace ts.FindAllReferences {
116
115
return undefined ;
117
116
}
118
117
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
+
119
143
function sourceFileHasName ( sourceFile : SourceFile , name : string ) : boolean {
120
144
return getNameTable ( sourceFile ) . get ( name ) !== undefined ;
121
145
}
@@ -157,29 +181,30 @@ namespace ts.FindAllReferences {
157
181
}
158
182
159
183
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
+ }
166
187
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 ) ;
181
207
}
182
- return undefined ;
183
208
}
184
209
185
210
function followAliasIfNecessary ( symbol : Symbol , location : Node , typeChecker : TypeChecker ) : Symbol {
@@ -1022,9 +1047,9 @@ namespace ts.FindAllReferences {
1022
1047
}
1023
1048
}
1024
1049
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 [ ] {
1026
1051
// The search set contains at least the current symbol
1027
- let result = [ symbol ] ;
1052
+ const result = [ symbol ] ;
1028
1053
1029
1054
// If the location is name of property symbol from object literal destructuring pattern
1030
1055
// Search the property symbol
@@ -1037,10 +1062,6 @@ namespace ts.FindAllReferences {
1037
1062
}
1038
1063
}
1039
1064
1040
- if ( aliasSymbol ) {
1041
- result = result . concat ( populateSearchSymbolSet ( aliasSymbol , location , typeChecker , implementations ) ) ;
1042
- }
1043
-
1044
1065
// If the location is in a context sensitive location (i.e. in an object literal) try
1045
1066
// to get a contextual type for it, and add the property symbol from the contextual
1046
1067
// type to the search set
@@ -1072,7 +1093,7 @@ namespace ts.FindAllReferences {
1072
1093
// Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members
1073
1094
if ( symbol . valueDeclaration && symbol . valueDeclaration . kind === SyntaxKind . Parameter &&
1074
1095
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 ) ) ;
1076
1097
}
1077
1098
1078
1099
// If this is symbol of binding element without propertyName declaration in Object binding pattern
@@ -1447,4 +1468,8 @@ namespace ts.FindAllReferences {
1447
1468
1448
1469
return false ;
1449
1470
}
1471
+
1472
+ function isImportDefaultSymbol ( symbol : Symbol ) : boolean {
1473
+ return symbol . declarations [ 0 ] . kind === SyntaxKind . ImportClause ;
1474
+ }
1450
1475
}
0 commit comments