@@ -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,92 @@ 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
+ function mergeReferences ( program : Program , ...referencesToMerge : ( SymbolAndEntries [ ] | undefined ) [ ] ) : SymbolAndEntries [ ] | undefined {
426
+ let result : SymbolAndEntries [ ] | undefined ;
427
+ for ( const references of referencesToMerge ) {
428
+ if ( ! references || ! references . length ) continue ;
429
+ if ( ! result ) {
430
+ result = references ;
431
+ continue ;
432
+ }
433
+ for ( const entry of references ) {
434
+ if ( ! entry . definition || entry . definition . type !== DefinitionKind . Symbol ) {
435
+ result . push ( entry ) ;
436
+ continue ;
437
+ }
438
+ const symbol = entry . definition . symbol ;
439
+ const refIndex = findIndex ( result , ref => ! ! ref . definition &&
440
+ ref . definition . type === DefinitionKind . Symbol &&
441
+ ref . definition . symbol === symbol ) ;
442
+ if ( refIndex === - 1 ) {
443
+ result . push ( entry ) ;
444
+ continue ;
445
+ }
446
+
447
+ const reference = result [ refIndex ] ;
448
+ result [ refIndex ] = {
449
+ definition : reference . definition ,
450
+ references : reference . references . concat ( entry . references ) . sort ( ( entry1 , entry2 ) => {
451
+ const entry1File = getSourceFileIndexOfEntry ( program , entry1 ) ;
452
+ const entry2File = getSourceFileIndexOfEntry ( program , entry2 ) ;
453
+ if ( entry1File !== entry2File ) {
454
+ return compareValues ( entry1File , entry2File ) ;
455
+ }
456
+
457
+ const entry1Span = getTextSpanOfEntry ( entry1 ) ;
458
+ const entry2Span = getTextSpanOfEntry ( entry2 ) ;
459
+ return entry1Span . start !== entry2Span . start ?
460
+ compareValues ( entry1Span . start , entry2Span . start ) :
461
+ compareValues ( entry1Span . length , entry2Span . length ) ;
462
+ } )
463
+ } ;
464
+ }
394
465
}
395
- return concatenate ( moduleReferences , getReferencedSymbolsForSymbol ( symbol , referencedNode , sourceFiles , sourceFilesSet , checker , cancellationToken , options ) ) ;
466
+ return result ;
396
467
}
397
468
398
- function isModuleSymbol ( symbol : Symbol ) : SourceFile | undefined {
399
- return symbol . flags & SymbolFlags . Module ? find ( symbol . declarations , isSourceFile ) : undefined ;
469
+ function getSourceFileIndexOfEntry ( program : Program , entry : Entry ) {
470
+ const sourceFile = entry . kind === EntryKind . Span ?
471
+ program . getSourceFile ( entry . fileName ) ! :
472
+ entry . node . getSourceFile ( ) ;
473
+ return program . getSourceFiles ( ) . indexOf ( sourceFile ) ;
400
474
}
401
475
402
476
function getReferencedSymbolsForModule ( program : Program , symbol : Symbol , excludeImportTypeOfExportEquals : boolean , sourceFiles : ReadonlyArray < SourceFile > , sourceFilesSet : ReadonlyMap < true > ) : SymbolAndEntries [ ] {
@@ -435,7 +509,7 @@ namespace ts.FindAllReferences.Core {
435
509
break ;
436
510
default :
437
511
// This may be merged with something.
438
- Debug . fail ( "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration." ) ;
512
+ Debug . assert ( ! ! ( symbol . flags & SymbolFlags . Transient ) , "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration." ) ;
439
513
}
440
514
}
441
515
@@ -551,6 +625,8 @@ namespace ts.FindAllReferences.Core {
551
625
// 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
626
return firstDefined ( symbol . declarations , decl => {
553
627
if ( ! decl . parent ) {
628
+ // Ignore UMD module and global merge
629
+ if ( symbol . flags & SymbolFlags . Transient ) return undefined ;
554
630
// Assertions for GH#21814. We should be handling SourceFile symbols in `getReferencedSymbolsForModule` instead of getting here.
555
631
Debug . fail ( `Unexpected symbol at ${ Debug . showSyntaxKind ( node ) } : ${ Debug . showSymbol ( symbol ) } ` ) ;
556
632
}
@@ -588,6 +664,12 @@ namespace ts.FindAllReferences.Core {
588
664
Class ,
589
665
}
590
666
667
+ function getNonModuleSymbolOfMergedModuleSymbol ( symbol : Symbol ) {
668
+ if ( ! ( symbol . flags & ( SymbolFlags . Module | SymbolFlags . Transient ) ) ) return undefined ;
669
+ const decl = symbol . declarations && find ( symbol . declarations , d => ! isSourceFile ( d ) && ! isModuleDeclaration ( d ) ) ;
670
+ return decl && decl . symbol ;
671
+ }
672
+
591
673
/**
592
674
* Holds all state needed for the finding references.
593
675
* Unlike `Search`, there is only one `State`.
@@ -648,7 +730,7 @@ namespace ts.FindAllReferences.Core {
648
730
// The other two forms seem to be handled downstream (e.g. in `skipPastExportOrImportSpecifier`), so special-casing the first form
649
731
// here appears to be intentional).
650
732
const {
651
- text = stripQuotes ( unescapeLeadingUnderscores ( ( getLocalSymbolForExportDefault ( symbol ) || symbol ) . escapedName ) ) ,
733
+ text = stripQuotes ( unescapeLeadingUnderscores ( ( getLocalSymbolForExportDefault ( symbol ) || getNonModuleSymbolOfMergedModuleSymbol ( symbol ) || symbol ) . escapedName ) ) ,
652
734
allSearchSymbols = [ symbol ] ,
653
735
} = searchOptions ;
654
736
const escapedText = escapeLeadingUnderscores ( text ) ;
@@ -1573,6 +1655,13 @@ namespace ts.FindAllReferences.Core {
1573
1655
if ( res2 ) return res2 ;
1574
1656
}
1575
1657
1658
+ const aliasedSymbol = getMergedAliasedSymbolOfNamespaceExportDeclaration ( location , symbol , checker ) ;
1659
+ if ( aliasedSymbol ) {
1660
+ // In case of UMD module and global merging, search for global as well
1661
+ const res = cbSymbol ( aliasedSymbol , /*rootSymbol*/ undefined , /*baseSymbol*/ undefined , EntryKind . Node ) ;
1662
+ if ( res ) return res ;
1663
+ }
1664
+
1576
1665
const res = fromRoot ( symbol ) ;
1577
1666
if ( res ) return res ;
1578
1667
0 commit comments