@@ -236,7 +236,7 @@ namespace ts.FindAllReferences.Core {
236
236
export function getReferencedSymbolsForNode ( position : number , node : Node , program : Program , sourceFiles : ReadonlyArray < SourceFile > , cancellationToken : CancellationToken , options : Options = { } , sourceFilesSet : ReadonlyMap < true > = arrayToSet ( sourceFiles , f => f . fileName ) ) : SymbolAndEntries [ ] | undefined {
237
237
if ( isSourceFile ( node ) ) {
238
238
const reference = GoToDefinition . getReferenceAtPosition ( node , position , program ) ;
239
- return reference && getReferencedSymbolsForModule ( program , program . getTypeChecker ( ) . getMergedSymbol ( reference . file . symbol ) , sourceFiles , sourceFilesSet ) ;
239
+ return reference && getReferencedSymbolsForModule ( program , program . getTypeChecker ( ) . getMergedSymbol ( reference . file . symbol ) , /*excludeImportTypeOfExportEquals*/ false , sourceFiles , sourceFilesSet ) ;
240
240
}
241
241
242
242
if ( ! options . implementations ) {
@@ -247,45 +247,45 @@ namespace ts.FindAllReferences.Core {
247
247
}
248
248
249
249
const checker = program . getTypeChecker ( ) ;
250
- const symbol = checker . getSymbolAtLocation ( node ) ;
250
+ let symbol = checker . getSymbolAtLocation ( node ) ;
251
251
252
252
// Could not find a symbol e.g. unknown identifier
253
253
if ( ! symbol ) {
254
254
// String literal might be a property (and thus have a symbol), so do this here rather than in getReferencedSymbolsSpecial.
255
255
return ! options . implementations && isStringLiteral ( node ) ? getReferencesForStringLiteral ( node , sourceFiles , cancellationToken ) : undefined ;
256
256
}
257
257
258
- if ( symbol . flags & SymbolFlags . Module && isModuleReferenceLocation ( node ) ) {
259
- return getReferencedSymbolsForModule ( program , symbol , sourceFiles , sourceFilesSet ) ;
258
+ let moduleReferences : SymbolAndEntries [ ] = emptyArray ;
259
+ const moduleSourceFile = isModuleSymbol ( symbol ) ;
260
+ if ( moduleSourceFile ) {
261
+ const exportEquals = symbol . exports . get ( InternalSymbolName . ExportEquals ) ;
262
+ // If !!exportEquals, we're about to add references to `import("mod")` anyway, so don't double-count them.
263
+ moduleReferences = getReferencedSymbolsForModule ( program , symbol , ! ! exportEquals , sourceFiles , sourceFilesSet ) ;
264
+ if ( ! exportEquals || ! sourceFilesSet . has ( moduleSourceFile . fileName ) ) return moduleReferences ;
265
+ // Continue to get references to 'export ='.
266
+ symbol = skipAlias ( exportEquals , checker ) ;
267
+ node = undefined ;
260
268
}
261
-
262
- return getReferencedSymbolsForSymbol ( symbol , node , sourceFiles , sourceFilesSet , checker , cancellationToken , options ) ;
269
+ return concatenate ( moduleReferences , getReferencedSymbolsForSymbol ( symbol , node , sourceFiles , sourceFilesSet , checker , cancellationToken , options ) ) ;
263
270
}
264
271
265
- function isModuleReferenceLocation ( node : Node ) : boolean {
266
- if ( ! isStringLiteralLike ( node ) ) {
267
- return false ;
268
- }
269
- switch ( node . parent . kind ) {
270
- case SyntaxKind . ModuleDeclaration :
271
- case SyntaxKind . ExternalModuleReference :
272
- case SyntaxKind . ImportDeclaration :
273
- case SyntaxKind . ExportDeclaration :
274
- return true ;
275
- case SyntaxKind . LiteralType :
276
- return isImportTypeNode ( node . parent . parent ) ;
277
- case SyntaxKind . CallExpression :
278
- return isRequireCall ( node . parent as CallExpression , /*checkArgumentIsStringLiteralLike*/ false ) || isImportCall ( node . parent as CallExpression ) ;
279
- default :
280
- return false ;
281
- }
272
+ function isModuleSymbol ( symbol : Symbol ) : SourceFile | undefined {
273
+ return symbol . flags & SymbolFlags . Module && find ( symbol . declarations , isSourceFile ) ;
282
274
}
283
275
284
- function getReferencedSymbolsForModule ( program : Program , symbol : Symbol , sourceFiles : ReadonlyArray < SourceFile > , sourceFilesSet : ReadonlyMap < true > ) : SymbolAndEntries [ ] {
276
+ function getReferencedSymbolsForModule ( program : Program , symbol : Symbol , excludeImportTypeOfExportEquals : boolean , sourceFiles : ReadonlyArray < SourceFile > , sourceFilesSet : ReadonlyMap < true > ) : SymbolAndEntries [ ] {
285
277
Debug . assert ( ! ! symbol . valueDeclaration ) ;
286
278
287
- const references = findModuleReferences ( program , sourceFiles , symbol ) . map < Entry > ( reference => {
279
+ const references = mapDefined < ModuleReference , Entry > ( findModuleReferences ( program , sourceFiles , symbol ) , reference => {
288
280
if ( reference . kind === "import" ) {
281
+ const parent = reference . literal . parent ;
282
+ if ( isLiteralTypeNode ( parent ) ) {
283
+ const importType = cast ( parent . parent , isImportTypeNode ) ;
284
+ if ( excludeImportTypeOfExportEquals && ! importType . qualifier ) {
285
+ return undefined ;
286
+ }
287
+ }
288
+ // import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway.
289
289
return { type : "node" , node : reference . literal } ;
290
290
}
291
291
else {
@@ -308,11 +308,12 @@ namespace ts.FindAllReferences.Core {
308
308
}
309
309
break ;
310
310
default :
311
+ // This may be merged with something.
311
312
Debug . fail ( "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration." ) ;
312
313
}
313
314
}
314
315
315
- return [ { definition : { type : "symbol" , symbol } , references } ] ;
316
+ return references . length ? [ { definition : { type : "symbol" , symbol } , references } ] : emptyArray ;
316
317
}
317
318
318
319
/** getReferencedSymbols for special node kinds. */
@@ -345,21 +346,21 @@ namespace ts.FindAllReferences.Core {
345
346
}
346
347
347
348
/** Core find-all-references algorithm for a normal symbol. */
348
- function getReferencedSymbolsForSymbol ( symbol : Symbol , node : Node , sourceFiles : ReadonlyArray < SourceFile > , sourceFilesSet : ReadonlyMap < true > , checker : TypeChecker , cancellationToken : CancellationToken , options : Options ) : SymbolAndEntries [ ] {
349
- symbol = skipPastExportOrImportSpecifierOrUnion ( symbol , node , checker ) || symbol ;
349
+ function getReferencedSymbolsForSymbol ( symbol : Symbol , node : Node | undefined , sourceFiles : ReadonlyArray < SourceFile > , sourceFilesSet : ReadonlyMap < true > , checker : TypeChecker , cancellationToken : CancellationToken , options : Options ) : SymbolAndEntries [ ] {
350
+ symbol = node && skipPastExportOrImportSpecifierOrUnion ( symbol , node , checker ) || symbol ;
350
351
351
352
// Compute the meaning from the location and the symbol it references
352
- const searchMeaning = getIntersectingMeaningFromDeclarations ( node , symbol ) ;
353
+ const searchMeaning = node ? getIntersectingMeaningFromDeclarations ( node , symbol ) : SemanticMeaning . All ;
353
354
354
355
const result : SymbolAndEntries [ ] = [ ] ;
355
- const state = new State ( sourceFiles , sourceFilesSet , getSpecialSearchKind ( node ) , checker , cancellationToken , searchMeaning , options , result ) ;
356
+ const state = new State ( sourceFiles , sourceFilesSet , node ? getSpecialSearchKind ( node ) : SpecialSearchKind . None , checker , cancellationToken , searchMeaning , options , result ) ;
356
357
357
- if ( node . kind === SyntaxKind . DefaultKeyword ) {
358
+ if ( node && node . kind === SyntaxKind . DefaultKeyword ) {
358
359
addReference ( node , symbol , state ) ;
359
360
searchForImportsOfExport ( node , symbol , { exportingModuleSymbol : Debug . assertDefined ( symbol . parent , "Expected export symbol to have a parent" ) , exportKind : ExportKind . Default } , state ) ;
360
361
}
361
362
else {
362
- const search = state . createSearch ( node , symbol , /*comingFrom*/ undefined , { allSearchSymbols : populateSearchSymbolSet ( symbol , node , checker , options . implementations ) } ) ;
363
+ const search = state . createSearch ( node , symbol , /*comingFrom*/ undefined , { allSearchSymbols : node ? populateSearchSymbolSet ( symbol , node , checker , options . implementations ) : [ symbol ] } ) ;
363
364
364
365
// Try to get the smallest valid scope that we can limit our search to;
365
366
// otherwise we'll need to search globally (i.e. include each file).
@@ -499,7 +500,7 @@ namespace ts.FindAllReferences.Core {
499
500
}
500
501
501
502
/** @param allSearchSymbols set of additinal symbols for use by `includes`. */
502
- createSearch ( location : Node , symbol : Symbol , comingFrom : ImportExport | undefined , searchOptions : { text ?: string , allSearchSymbols ?: Symbol [ ] } = { } ) : Search {
503
+ createSearch ( location : Node | undefined , symbol : Symbol , comingFrom : ImportExport | undefined , searchOptions : { text ?: string , allSearchSymbols ?: Symbol [ ] } = { } ) : Search {
503
504
// Note: if this is an external module symbol, the name doesn't include quotes.
504
505
// Note: getLocalSymbolForExportDefault handles `export default class C {}`, but not `export default C` or `export { C as default }`.
505
506
// The other two forms seem to be handled downstream (e.g. in `skipPastExportOrImportSpecifier`), so special-casing the first form
@@ -509,7 +510,7 @@ namespace ts.FindAllReferences.Core {
509
510
allSearchSymbols = [ symbol ] ,
510
511
} = searchOptions ;
511
512
const escapedText = escapeLeadingUnderscores ( text ) ;
512
- const parents = this . options . implementations && getParentSymbolsOfPropertyAccess ( location , symbol , this . checker ) ;
513
+ const parents = this . options . implementations && location && getParentSymbolsOfPropertyAccess ( location , symbol , this . checker ) ;
513
514
return { symbol, comingFrom, text, escapedText, parents, allSearchSymbols, includes : sym => contains ( allSearchSymbols , sym ) } ;
514
515
}
515
516
@@ -559,11 +560,7 @@ namespace ts.FindAllReferences.Core {
559
560
if ( singleReferences . length ) {
560
561
const addRef = state . referenceAdder ( exportSymbol ) ;
561
562
for ( const singleRef of singleReferences ) {
562
- // At `default` in `import { default as x }` or `export { default as x }`, do add a reference, but do not rename.
563
- if ( hasMatchingMeaning ( singleRef , state ) &&
564
- ! ( state . options . isForRename && ( isExportSpecifier ( singleRef . parent ) || isImportSpecifier ( singleRef . parent ) ) && singleRef . escapedText === InternalSymbolName . Default ) ) {
565
- addRef ( singleRef ) ;
566
- }
563
+ if ( shouldAddSingleReference ( singleRef , state ) ) addRef ( singleRef ) ;
567
564
}
568
565
}
569
566
@@ -593,6 +590,15 @@ namespace ts.FindAllReferences.Core {
593
590
}
594
591
}
595
592
593
+ function shouldAddSingleReference ( singleRef : Identifier | StringLiteral , state : State ) : boolean {
594
+ if ( ! hasMatchingMeaning ( singleRef , state ) ) return false ;
595
+ if ( ! state . options . isForRename ) return true ;
596
+ // Don't rename an import type `import("./module-name")` when renaming `name` in `export = name;`
597
+ if ( ! isIdentifier ( singleRef ) ) return false ;
598
+ // At `default` in `import { default as x }` or `export { default as x }`, do add a reference, but do not rename.
599
+ return ! ( ( isExportSpecifier ( singleRef . parent ) || isImportSpecifier ( singleRef . parent ) ) && singleRef . escapedText === InternalSymbolName . Default ) ;
600
+ }
601
+
596
602
// Go to the symbol we imported from and find references for it.
597
603
function searchForImportedSymbol ( symbol : Symbol , state : State ) : void {
598
604
for ( const declaration of symbol . declarations ) {
0 commit comments