@@ -386,7 +386,7 @@ namespace ts.FindAllReferences.Core {
386
386
const searchMeaning = getIntersectingMeaningFromDeclarations ( getMeaningFromLocation ( node ) , symbol . declarations ) ;
387
387
388
388
const result : SymbolAndEntries [ ] = [ ] ;
389
- const state = createState ( sourceFiles , node , checker , cancellationToken , searchMeaning , options , result ) ;
389
+ const state = new State ( sourceFiles , /*isForConstructor*/ node . kind === SyntaxKind . ConstructorKeyword , checker , cancellationToken , searchMeaning , options , result ) ;
390
390
const search = state . createSearch ( node , symbol , /*comingFrom*/ undefined , { allSearchSymbols : populateSearchSymbolSet ( symbol , node , checker , options . implementations ) } ) ;
391
391
392
392
// Try to get the smallest valid scope that we can limit our search to;
@@ -446,35 +446,9 @@ namespace ts.FindAllReferences.Core {
446
446
* Holds all state needed for the finding references.
447
447
* Unlike `Search`, there is only one `State`.
448
448
*/
449
- interface State extends Options {
450
- /** True if we're searching for constructor references. */
451
- readonly isForConstructor : boolean ;
452
-
453
- readonly sourceFiles : SourceFile [ ] ;
454
- readonly checker : TypeChecker ;
455
- readonly cancellationToken : CancellationToken ;
456
- readonly searchMeaning : SemanticMeaning ;
457
-
449
+ class State {
458
450
/** Cache for `explicitlyinheritsFrom`. */
459
- readonly inheritsFromCache : Map < boolean > ;
460
-
461
- /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */
462
- getImportSearches ( exportSymbol : Symbol , exportInfo : ExportInfo ) : ImportsResult ;
463
-
464
- /** @param allSearchSymbols set of additinal symbols for use by `includes`. */
465
- createSearch ( location : Node , symbol : Symbol , comingFrom : ImportExport | undefined , searchOptions ?: { text ?: string , allSearchSymbols ?: Symbol [ ] } ) : Search ;
466
-
467
- /**
468
- * Callback to add references for a particular searched symbol.
469
- * This initializes a reference group, so only call this if you will add at least one reference.
470
- */
471
- referenceAdder ( searchSymbol : Symbol , searchLocation : Node ) : ( node : Node ) => void ;
472
-
473
- /** Add a reference with no associated definition. */
474
- addStringOrCommentReference ( fileName : string , textSpan : TextSpan ) : void ;
475
-
476
- /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */
477
- markSearchedSymbol ( sourceFile : SourceFile , symbol : Symbol ) : boolean ;
451
+ readonly inheritsFromCache = createMap < boolean > ( ) ;
478
452
479
453
/**
480
454
* Type nodes can contain multiple references to the same type. For example:
@@ -483,7 +457,7 @@ namespace ts.FindAllReferences.Core {
483
457
* duplicate entries would be returned here as each of the type references is part of
484
458
* the same implementation. For that reason, check before we add a new entry.
485
459
*/
486
- markSeenContainingTypeReference ( containingTypeReference : Node ) : boolean ;
460
+ readonly markSeenContainingTypeReference = nodeSeenTracker ( ) ;
487
461
488
462
/**
489
463
* It's possible that we will encounter the right side of `export { foo as bar } from "x";` more than once.
@@ -496,61 +470,68 @@ namespace ts.FindAllReferences.Core {
496
470
* But another reference to it may appear in the same source file.
497
471
* See `tests/cases/fourslash/transitiveExportImports3.ts`.
498
472
*/
499
- markSeenReExportRHS ( rhs : Identifier ) : boolean ;
500
- }
501
-
502
- function createState ( sourceFiles : SourceFile [ ] , originalLocation : Node , checker : TypeChecker , cancellationToken : CancellationToken , searchMeaning : SemanticMeaning , options : Options , result : Push < SymbolAndEntries > ) : State {
503
- const symbolIdToReferences : Entry [ ] [ ] = [ ] ;
504
- const inheritsFromCache = createMap < boolean > ( ) ;
505
- // Source file ID → symbol ID → Whether the symbol has been searched for in the source file.
506
- const sourceFileToSeenSymbols : Array < Array < true > > = [ ] ;
507
- const isForConstructor = originalLocation . kind === SyntaxKind . ConstructorKeyword ;
508
- let importTracker : ImportTracker | undefined ;
509
-
510
- return {
511
- ...options ,
512
- sourceFiles, isForConstructor, checker, cancellationToken, searchMeaning, inheritsFromCache, getImportSearches, createSearch, referenceAdder, addStringOrCommentReference,
513
- markSearchedSymbol, markSeenContainingTypeReference : nodeSeenTracker ( ) , markSeenReExportRHS : nodeSeenTracker ( ) ,
514
- } ;
515
-
516
- function getImportSearches ( exportSymbol : Symbol , exportInfo : ExportInfo ) : ImportsResult {
517
- if ( ! importTracker ) importTracker = createImportTracker ( sourceFiles , checker , cancellationToken ) ;
518
- return importTracker ( exportSymbol , exportInfo , options . isForRename ) ;
473
+ readonly markSeenReExportRHS = nodeSeenTracker ( ) ;
474
+
475
+ constructor (
476
+ readonly sourceFiles : SourceFile [ ] ,
477
+ /** True if we're searching for constructor references. */
478
+ readonly isForConstructor : boolean ,
479
+ readonly checker : TypeChecker ,
480
+ readonly cancellationToken : CancellationToken ,
481
+ readonly searchMeaning : SemanticMeaning ,
482
+ readonly options : Options ,
483
+ private readonly result : Push < SymbolAndEntries > ) { }
484
+
485
+ private importTracker : ImportTracker | undefined ;
486
+ /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */
487
+ getImportSearches ( exportSymbol : Symbol , exportInfo : ExportInfo ) : ImportsResult {
488
+ if ( ! this . importTracker ) this . importTracker = createImportTracker ( this . sourceFiles , this . checker , this . cancellationToken ) ;
489
+ return this . importTracker ( exportSymbol , exportInfo , this . options . isForRename ) ;
519
490
}
520
491
521
- function createSearch ( location : Node , symbol : Symbol , comingFrom : ImportExport , searchOptions : { text ?: string , allSearchSymbols ?: Symbol [ ] } = { } ) : Search {
492
+ /** @param allSearchSymbols set of additinal symbols for use by `includes`. */
493
+ createSearch ( location : Node , symbol : Symbol , comingFrom : ImportExport | undefined , searchOptions : { text ?: string , allSearchSymbols ?: Symbol [ ] } = { } ) : Search {
522
494
// Note: if this is an external module symbol, the name doesn't include quotes.
523
- const { text = stripQuotes ( getDeclaredName ( checker , symbol , location ) ) , allSearchSymbols = undefined } = searchOptions ;
495
+ const { text = stripQuotes ( getDeclaredName ( this . checker , symbol , location ) ) , allSearchSymbols = undefined } = searchOptions ;
524
496
const escapedText = escapeIdentifier ( text ) ;
525
- const parents = options . implementations && getParentSymbolsOfPropertyAccess ( location , symbol , checker ) ;
497
+ const parents = this . options . implementations && getParentSymbolsOfPropertyAccess ( location , symbol , this . checker ) ;
526
498
return { location, symbol, comingFrom, text, escapedText, parents, includes } ;
527
499
528
500
function includes ( referenceSymbol : Symbol ) : boolean {
529
501
return allSearchSymbols ? contains ( allSearchSymbols , referenceSymbol ) : referenceSymbol === symbol ;
530
502
}
531
503
}
532
504
533
- function referenceAdder ( referenceSymbol : Symbol , searchLocation : Node ) : ( node : Node ) => void {
534
- const symbolId = getSymbolId ( referenceSymbol ) ;
535
- let references = symbolIdToReferences [ symbolId ] ;
505
+ private readonly symbolIdToReferences : Entry [ ] [ ] = [ ] ;
506
+ /**
507
+ * Callback to add references for a particular searched symbol.
508
+ * This initializes a reference group, so only call this if you will add at least one reference.
509
+ */
510
+ referenceAdder ( searchSymbol : Symbol , searchLocation : Node ) : ( node : Node ) => void {
511
+ const symbolId = getSymbolId ( searchSymbol ) ;
512
+ let references = this . symbolIdToReferences [ symbolId ] ;
536
513
if ( ! references ) {
537
- references = symbolIdToReferences [ symbolId ] = [ ] ;
538
- result . push ( { definition : { type : "symbol" , symbol : referenceSymbol , node : searchLocation } , references } ) ;
514
+ references = this . symbolIdToReferences [ symbolId ] = [ ] ;
515
+ this . result . push ( { definition : { type : "symbol" , symbol : searchSymbol , node : searchLocation } , references } ) ;
539
516
}
540
517
return node => references . push ( nodeEntry ( node ) ) ;
541
518
}
542
519
543
- function addStringOrCommentReference ( fileName : string , textSpan : TextSpan ) : void {
544
- result . push ( {
520
+ /** Add a reference with no associated definition. */
521
+ addStringOrCommentReference ( fileName : string , textSpan : TextSpan ) : void {
522
+ this . result . push ( {
545
523
definition : undefined ,
546
524
references : [ { type : "span" , fileName, textSpan } ]
547
525
} ) ;
548
526
}
549
527
550
- function markSearchedSymbol ( sourceFile : SourceFile , symbol : Symbol ) : boolean {
528
+ // Source file ID → symbol ID → Whether the symbol has been searched for in the source file.
529
+ private readonly sourceFileToSeenSymbols : Array < Array < true > > = [ ] ;
530
+ /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */
531
+ markSearchedSymbol ( sourceFile : SourceFile , symbol : Symbol ) : boolean {
551
532
const sourceId = getNodeId ( sourceFile ) ;
552
533
const symbolId = getSymbolId ( symbol ) ;
553
- const seenSymbols = sourceFileToSeenSymbols [ sourceId ] || ( sourceFileToSeenSymbols [ sourceId ] = [ ] ) ;
534
+ const seenSymbols = this . sourceFileToSeenSymbols [ sourceId ] || ( this . sourceFileToSeenSymbols [ sourceId ] = [ ] ) ;
554
535
return ! seenSymbols [ symbolId ] && ( seenSymbols [ symbolId ] = true ) ;
555
536
}
556
537
}
@@ -580,7 +561,7 @@ namespace ts.FindAllReferences.Core {
580
561
break ;
581
562
case ExportKind . Default :
582
563
// Search for a property access to '.default'. This can't be renamed.
583
- indirectSearch = state . isForRename ? undefined : state . createSearch ( exportLocation , exportSymbol , ImportExport . Export , { text : "default" } ) ;
564
+ indirectSearch = state . options . isForRename ? undefined : state . createSearch ( exportLocation , exportSymbol , ImportExport . Export , { text : "default" } ) ;
584
565
break ;
585
566
case ExportKind . ExportEquals :
586
567
break ;
@@ -803,7 +784,7 @@ namespace ts.FindAllReferences.Core {
803
784
return ;
804
785
}
805
786
806
- for ( const position of getPossibleSymbolReferencePositions ( sourceFile , search . text , container , /*fullStart*/ state . findInComments || container . jsDoc !== undefined ) ) {
787
+ for ( const position of getPossibleSymbolReferencePositions ( sourceFile , search . text , container , /*fullStart*/ state . options . findInComments || container . jsDoc !== undefined ) ) {
807
788
getReferencesAtLocation ( sourceFile , position , search , state ) ;
808
789
}
809
790
}
@@ -815,7 +796,7 @@ namespace ts.FindAllReferences.Core {
815
796
// This wasn't the start of a token. Check to see if it might be a
816
797
// match in a comment or string if that's what the caller is asking
817
798
// for.
818
- if ( ! state . implementations && ( state . findInStrings && isInString ( sourceFile , position ) || state . findInComments && isInNonReferenceComment ( sourceFile , position ) ) ) {
799
+ if ( ! state . options . implementations && ( state . options . findInStrings && isInString ( sourceFile , position ) || state . options . findInComments && isInNonReferenceComment ( sourceFile , position ) ) ) {
819
800
// In the case where we're looking inside comments/strings, we don't have
820
801
// an actual definition. So just use 'undefined' here. Features like
821
802
// 'Rename' won't care (as they ignore the definitions), and features like
@@ -881,7 +862,7 @@ namespace ts.FindAllReferences.Core {
881
862
addRef ( ) ;
882
863
}
883
864
884
- if ( ! state . isForRename && state . markSeenReExportRHS ( name ) ) {
865
+ if ( ! state . options . isForRename && state . markSeenReExportRHS ( name ) ) {
885
866
addReference ( name , referenceSymbol , name , state ) ;
886
867
}
887
868
}
@@ -892,7 +873,7 @@ namespace ts.FindAllReferences.Core {
892
873
}
893
874
894
875
// For `export { foo as bar }`, rename `foo`, but not `bar`.
895
- if ( ! ( referenceLocation === propertyName && state . isForRename ) ) {
876
+ if ( ! ( referenceLocation === propertyName && state . options . isForRename ) ) {
896
877
const exportKind = ( referenceLocation as Identifier ) . originalKeywordKind === ts . SyntaxKind . DefaultKeyword ? ExportKind . Default : ExportKind . Named ;
897
878
const exportInfo = getExportInfo ( referenceSymbol , exportKind , state . checker ) ;
898
879
Debug . assert ( ! ! exportInfo ) ;
@@ -934,7 +915,7 @@ namespace ts.FindAllReferences.Core {
934
915
const { symbol } = importOrExport ;
935
916
936
917
if ( importOrExport . kind === ImportExport . Import ) {
937
- if ( ! state . isForRename || importOrExport . isNamedImport ) {
918
+ if ( ! state . options . isForRename || importOrExport . isNamedImport ) {
938
919
searchForImportedSymbol ( symbol , state ) ;
939
920
}
940
921
}
@@ -960,7 +941,7 @@ namespace ts.FindAllReferences.Core {
960
941
961
942
function addReference ( referenceLocation : Node , relatedSymbol : Symbol , searchLocation : Node , state : State ) : void {
962
943
const addRef = state . referenceAdder ( relatedSymbol , searchLocation ) ;
963
- if ( state . implementations ) {
944
+ if ( state . options . implementations ) {
964
945
addImplementationReferences ( referenceLocation , addRef , state ) ;
965
946
}
966
947
else {
0 commit comments