@@ -111,7 +111,7 @@ namespace ts.FindAllReferences {
111
111
return flattenEntries ( Core . getReferencedSymbolsForNode ( position , node , program , sourceFiles , cancellationToken , options , sourceFilesSet ) ) ;
112
112
}
113
113
114
- function flattenEntries ( referenceSymbols : SymbolAndEntries [ ] | undefined ) : ReadonlyArray < Entry > | undefined {
114
+ function flattenEntries ( referenceSymbols : ReadonlyArray < SymbolAndEntries > | undefined ) : ReadonlyArray < Entry > | undefined {
115
115
return referenceSymbols && flatMap ( referenceSymbols , r => r . references ) ;
116
116
}
117
117
@@ -282,6 +282,11 @@ namespace ts.FindAllReferences {
282
282
return createTextSpanFromBounds ( start , end ) ;
283
283
}
284
284
285
+ export function getTextSpanOfEntry ( entry : Entry ) {
286
+ return entry . kind === EntryKind . Span ? entry . textSpan :
287
+ getTextSpan ( entry . node , entry . node . getSourceFile ( ) ) ;
288
+ }
289
+
285
290
/** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */
286
291
function isWriteAccessForReference ( node : Node ) : boolean {
287
292
const decl = getDeclarationFromName ( node ) ;
@@ -353,7 +358,7 @@ namespace ts.FindAllReferences {
353
358
/* @internal */
354
359
namespace ts . FindAllReferences . Core {
355
360
/** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */
356
- 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 {
361
+ export function getReferencedSymbolsForNode ( position : number , node : Node , program : Program , sourceFiles : ReadonlyArray < SourceFile > , cancellationToken : CancellationToken , options : Options = { } , sourceFilesSet : ReadonlyMap < true > = arrayToSet ( sourceFiles , f => f . fileName ) ) : ReadonlyArray < SymbolAndEntries > | undefined {
357
362
if ( isSourceFile ( node ) ) {
358
363
const reference = GoToDefinition . getReferenceAtPosition ( node , position , program ) ;
359
364
const moduleSymbol = reference && program . getTypeChecker ( ) . getMergedSymbol ( reference . file . symbol ) ;
@@ -368,7 +373,7 @@ namespace ts.FindAllReferences.Core {
368
373
}
369
374
370
375
const checker = program . getTypeChecker ( ) ;
371
- let symbol = checker . getSymbolAtLocation ( node ) ;
376
+ const symbol = checker . getSymbolAtLocation ( node ) ;
372
377
373
378
// Could not find a symbol e.g. unknown identifier
374
379
if ( ! symbol ) {
@@ -380,23 +385,95 @@ namespace ts.FindAllReferences.Core {
380
385
return getReferencedSymbolsForModule ( program , symbol . parent ! , /*excludeImportTypeOfExportEquals*/ false , sourceFiles , sourceFilesSet ) ;
381
386
}
382
387
383
- let moduleReferences : SymbolAndEntries [ ] = emptyArray ;
384
- const moduleSourceFile = isModuleSymbol ( symbol ) ;
385
- let referencedNode : Node | undefined = node ;
386
- if ( moduleSourceFile ) {
387
- const exportEquals = symbol . exports ! . get ( InternalSymbolName . ExportEquals ) ;
388
- // If !!exportEquals, we're about to add references to `import("mod")` anyway, so don't double-count them.
389
- moduleReferences = getReferencedSymbolsForModule ( program , symbol , ! ! exportEquals , sourceFiles , sourceFilesSet ) ;
390
- if ( ! exportEquals || ! sourceFilesSet . has ( moduleSourceFile . fileName ) ) return moduleReferences ;
391
- // Continue to get references to 'export ='.
392
- symbol = skipAlias ( exportEquals , checker ) ;
393
- referencedNode = undefined ;
388
+ const moduleReferences = getReferencedSymbolsForModuleIfDeclaredBySourceFile ( symbol , program , sourceFiles , cancellationToken , options , sourceFilesSet ) ;
389
+ if ( moduleReferences && ! ( symbol . flags & SymbolFlags . Transient ) ) {
390
+ return moduleReferences ;
391
+ }
392
+
393
+ const aliasedSymbol = getMergedAliasedSymbolOfNamespaceExportDeclaration ( node , symbol , checker ) ;
394
+ const moduleReferencesOfExportTarget = aliasedSymbol &&
395
+ getReferencedSymbolsForModuleIfDeclaredBySourceFile ( aliasedSymbol , program , sourceFiles , cancellationToken , options , sourceFilesSet ) ;
396
+
397
+ const references = getReferencedSymbolsForSymbol ( symbol , node , sourceFiles , sourceFilesSet , checker , cancellationToken , options ) ;
398
+ return mergeReferences ( program , moduleReferences , references , moduleReferencesOfExportTarget ) ;
399
+ }
400
+
401
+ function getMergedAliasedSymbolOfNamespaceExportDeclaration ( node : Node , symbol : Symbol , checker : TypeChecker ) {
402
+ if ( node . parent && isNamespaceExportDeclaration ( node . parent ) ) {
403
+ const aliasedSymbol = checker . getAliasedSymbol ( symbol ) ;
404
+ const targetSymbol = checker . getMergedSymbol ( aliasedSymbol ) ;
405
+ if ( aliasedSymbol !== targetSymbol ) {
406
+ return targetSymbol ;
407
+ }
408
+ }
409
+ return undefined ;
410
+ }
411
+
412
+ function getReferencedSymbolsForModuleIfDeclaredBySourceFile ( symbol : Symbol , program : Program , sourceFiles : ReadonlyArray < SourceFile > , cancellationToken : CancellationToken , options : Options , sourceFilesSet : ReadonlyMap < true > ) {
413
+ const moduleSourceFile = symbol . flags & SymbolFlags . Module ? find ( symbol . declarations , isSourceFile ) : undefined ;
414
+ if ( ! moduleSourceFile ) return undefined ;
415
+ const exportEquals = symbol . exports ! . get ( InternalSymbolName . ExportEquals ) ;
416
+ // If !!exportEquals, we're about to add references to `import("mod")` anyway, so don't double-count them.
417
+ const moduleReferences = getReferencedSymbolsForModule ( program , symbol , ! ! exportEquals , sourceFiles , sourceFilesSet ) ;
418
+ if ( ! exportEquals || ! sourceFilesSet . has ( moduleSourceFile . fileName ) ) return moduleReferences ;
419
+ // Continue to get references to 'export ='.
420
+ const checker = program . getTypeChecker ( ) ;
421
+ symbol = skipAlias ( exportEquals , checker ) ;
422
+ return mergeReferences ( program , moduleReferences , getReferencedSymbolsForSymbol ( symbol , /*node*/ undefined , sourceFiles , sourceFilesSet , checker , cancellationToken , options ) ) ;
423
+ }
424
+
425
+ /**
426
+ * Merges the references by sorting them (by file index in sourceFiles and their location in it) that point to same definition symbol
427
+ */
428
+ function mergeReferences ( program : Program , ...referencesToMerge : ( SymbolAndEntries [ ] | undefined ) [ ] ) : SymbolAndEntries [ ] | undefined {
429
+ let result : SymbolAndEntries [ ] | undefined ;
430
+ for ( const references of referencesToMerge ) {
431
+ if ( ! references || ! references . length ) continue ;
432
+ if ( ! result ) {
433
+ result = references ;
434
+ continue ;
435
+ }
436
+ for ( const entry of references ) {
437
+ if ( ! entry . definition || entry . definition . type !== DefinitionKind . Symbol ) {
438
+ result . push ( entry ) ;
439
+ continue ;
440
+ }
441
+ const symbol = entry . definition . symbol ;
442
+ const refIndex = findIndex ( result , ref => ! ! ref . definition &&
443
+ ref . definition . type === DefinitionKind . Symbol &&
444
+ ref . definition . symbol === symbol ) ;
445
+ if ( refIndex === - 1 ) {
446
+ result . push ( entry ) ;
447
+ continue ;
448
+ }
449
+
450
+ const reference = result [ refIndex ] ;
451
+ result [ refIndex ] = {
452
+ definition : reference . definition ,
453
+ references : reference . references . concat ( entry . references ) . sort ( ( entry1 , entry2 ) => {
454
+ const entry1File = getSourceFileIndexOfEntry ( program , entry1 ) ;
455
+ const entry2File = getSourceFileIndexOfEntry ( program , entry2 ) ;
456
+ if ( entry1File !== entry2File ) {
457
+ return compareValues ( entry1File , entry2File ) ;
458
+ }
459
+
460
+ const entry1Span = getTextSpanOfEntry ( entry1 ) ;
461
+ const entry2Span = getTextSpanOfEntry ( entry2 ) ;
462
+ return entry1Span . start !== entry2Span . start ?
463
+ compareValues ( entry1Span . start , entry2Span . start ) :
464
+ compareValues ( entry1Span . length , entry2Span . length ) ;
465
+ } )
466
+ } ;
467
+ }
394
468
}
395
- return concatenate ( moduleReferences , getReferencedSymbolsForSymbol ( symbol , referencedNode , sourceFiles , sourceFilesSet , checker , cancellationToken , options ) ) ;
469
+ return result ;
396
470
}
397
471
398
- function isModuleSymbol ( symbol : Symbol ) : SourceFile | undefined {
399
- return symbol . flags & SymbolFlags . Module ? find ( symbol . declarations , isSourceFile ) : undefined ;
472
+ function getSourceFileIndexOfEntry ( program : Program , entry : Entry ) {
473
+ const sourceFile = entry . kind === EntryKind . Span ?
474
+ program . getSourceFile ( entry . fileName ) ! :
475
+ entry . node . getSourceFile ( ) ;
476
+ return program . getSourceFiles ( ) . indexOf ( sourceFile ) ;
400
477
}
401
478
402
479
function getReferencedSymbolsForModule ( program : Program , symbol : Symbol , excludeImportTypeOfExportEquals : boolean , sourceFiles : ReadonlyArray < SourceFile > , sourceFilesSet : ReadonlyMap < true > ) : SymbolAndEntries [ ] {
@@ -435,7 +512,7 @@ namespace ts.FindAllReferences.Core {
435
512
break ;
436
513
default :
437
514
// This may be merged with something.
438
- Debug . fail ( "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration." ) ;
515
+ Debug . assert ( ! ! ( symbol . flags & SymbolFlags . Transient ) , "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration." ) ;
439
516
}
440
517
}
441
518
@@ -551,6 +628,8 @@ namespace ts.FindAllReferences.Core {
551
628
// If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references.
552
629
return firstDefined ( symbol . declarations , decl => {
553
630
if ( ! decl . parent ) {
631
+ // Ignore UMD module and global merge
632
+ if ( symbol . flags & SymbolFlags . Transient ) return undefined ;
554
633
// Assertions for GH#21814. We should be handling SourceFile symbols in `getReferencedSymbolsForModule` instead of getting here.
555
634
Debug . fail ( `Unexpected symbol at ${ Debug . showSyntaxKind ( node ) } : ${ Debug . showSymbol ( symbol ) } ` ) ;
556
635
}
@@ -588,6 +667,12 @@ namespace ts.FindAllReferences.Core {
588
667
Class ,
589
668
}
590
669
670
+ function getNonModuleSymbolOfMergedModuleSymbol ( symbol : Symbol ) {
671
+ if ( ! ( symbol . flags & ( SymbolFlags . Module | SymbolFlags . Transient ) ) ) return undefined ;
672
+ const decl = symbol . declarations && find ( symbol . declarations , d => ! isSourceFile ( d ) && ! isModuleDeclaration ( d ) ) ;
673
+ return decl && decl . symbol ;
674
+ }
675
+
591
676
/**
592
677
* Holds all state needed for the finding references.
593
678
* Unlike `Search`, there is only one `State`.
@@ -648,7 +733,7 @@ namespace ts.FindAllReferences.Core {
648
733
// The other two forms seem to be handled downstream (e.g. in `skipPastExportOrImportSpecifier`), so special-casing the first form
649
734
// here appears to be intentional).
650
735
const {
651
- text = stripQuotes ( unescapeLeadingUnderscores ( ( getLocalSymbolForExportDefault ( symbol ) || symbol ) . escapedName ) ) ,
736
+ text = stripQuotes ( unescapeLeadingUnderscores ( ( getLocalSymbolForExportDefault ( symbol ) || getNonModuleSymbolOfMergedModuleSymbol ( symbol ) || symbol ) . escapedName ) ) ,
652
737
allSearchSymbols = [ symbol ] ,
653
738
} = searchOptions ;
654
739
const escapedText = escapeLeadingUnderscores ( text ) ;
@@ -1573,6 +1658,13 @@ namespace ts.FindAllReferences.Core {
1573
1658
if ( res2 ) return res2 ;
1574
1659
}
1575
1660
1661
+ const aliasedSymbol = getMergedAliasedSymbolOfNamespaceExportDeclaration ( location , symbol , checker ) ;
1662
+ if ( aliasedSymbol ) {
1663
+ // In case of UMD module and global merging, search for global as well
1664
+ const res = cbSymbol ( aliasedSymbol , /*rootSymbol*/ undefined , /*baseSymbol*/ undefined , EntryKind . Node ) ;
1665
+ if ( res ) return res ;
1666
+ }
1667
+
1576
1668
const res = fromRoot ( symbol ) ;
1577
1669
if ( res ) return res ;
1578
1670
0 commit comments