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