1
1
/* @internal */
2
2
namespace ts . FindAllReferences {
3
- export function findReferencedSymbols ( typeChecker : TypeChecker , cancellationToken : CancellationToken , sourceFiles : SourceFile [ ] , sourceFile : SourceFile , position : number , findInStrings : boolean , findInComments : boolean ) : ReferencedSymbol [ ] {
3
+ export function findReferencedSymbols ( typeChecker : TypeChecker , cancellationToken : CancellationToken , sourceFiles : SourceFile [ ] , sourceFile : SourceFile , position : number , findInStrings : boolean , findInComments : boolean ) : ReferencedSymbol [ ] | undefined {
4
4
const node = getTouchingPropertyName ( sourceFile , position , /*includeJsDocComment*/ true ) ;
5
- if ( node === sourceFile ) {
6
- return undefined ;
7
- }
8
-
9
- switch ( node . kind ) {
10
- case SyntaxKind . NumericLiteral :
11
- if ( ! isLiteralNameOfPropertyDeclarationOrIndexAccess ( node ) ) {
12
- break ;
13
- }
14
- // Fallthrough
15
- case SyntaxKind . Identifier :
16
- case SyntaxKind . ThisKeyword :
17
- // case SyntaxKind.SuperKeyword: TODO:GH#9268
18
- case SyntaxKind . ConstructorKeyword :
19
- case SyntaxKind . StringLiteral :
20
- return getReferencedSymbolsForNode ( typeChecker , cancellationToken , node , sourceFiles , findInStrings , findInComments , /*implementations*/ false ) ;
21
- }
22
- return undefined ;
5
+ return getReferencedSymbolsForNode ( typeChecker , cancellationToken , node , sourceFiles , findInStrings , findInComments , /*implementations*/ false ) ;
23
6
}
24
7
25
- export function getReferencedSymbolsForNode ( typeChecker : TypeChecker , cancellationToken : CancellationToken , node : Node , sourceFiles : SourceFile [ ] , findInStrings : boolean , findInComments : boolean , implementations : boolean ) : ReferencedSymbol [ ] {
8
+ export function getReferencedSymbolsForNode ( typeChecker : TypeChecker , cancellationToken : CancellationToken , node : Node , sourceFiles : SourceFile [ ] , findInStrings : boolean , findInComments : boolean , implementations : boolean ) : ReferencedSymbol [ ] | undefined {
26
9
if ( ! implementations ) {
10
+ if ( isTypeKeyword ( node . kind ) ) {
11
+ return getAllReferencesForKeyword ( sourceFiles , node . kind , cancellationToken ) ;
12
+ }
13
+
27
14
// Labels
28
15
if ( isLabelName ( node ) ) {
29
16
if ( isJumpStatementTarget ( node ) ) {
@@ -68,8 +55,6 @@ namespace ts.FindAllReferences {
68
55
return undefined ;
69
56
}
70
57
71
- let result : ReferencedSymbol [ ] ;
72
-
73
58
// Compute the meaning from the location and the symbol it references
74
59
const searchMeaning = getIntersectingMeaningFromDeclarations ( getMeaningFromLocation ( node ) , declarations ) ;
75
60
@@ -84,6 +69,7 @@ namespace ts.FindAllReferences {
84
69
// Maps from a symbol ID to the ReferencedSymbol entry in 'result'.
85
70
const symbolToIndex : number [ ] = [ ] ;
86
71
72
+ let result : ReferencedSymbol [ ] ;
87
73
if ( scope ) {
88
74
result = [ ] ;
89
75
getReferencesInNode ( scope , symbol , declaredName , node , searchMeaning , findInStrings , findInComments , result , symbolToIndex , implementations , typeChecker , cancellationToken ) ;
@@ -92,10 +78,7 @@ namespace ts.FindAllReferences {
92
78
const internedName = getInternedName ( symbol , node ) ;
93
79
for ( const sourceFile of sourceFiles ) {
94
80
cancellationToken . throwIfCancellationRequested ( ) ;
95
-
96
- const nameTable = getNameTable ( sourceFile ) ;
97
-
98
- if ( nameTable . get ( internedName ) !== undefined ) {
81
+ if ( sourceFileHasName ( sourceFile , internedName ) ) {
99
82
result = result || [ ] ;
100
83
getReferencesInNode ( sourceFile , symbol , declaredName , node , searchMeaning , findInStrings , findInComments , result , symbolToIndex , implementations , typeChecker , cancellationToken ) ;
101
84
}
@@ -105,9 +88,13 @@ namespace ts.FindAllReferences {
105
88
return result ;
106
89
}
107
90
91
+ function sourceFileHasName ( sourceFile : SourceFile , name : string ) : boolean {
92
+ return getNameTable ( sourceFile ) . get ( name ) !== undefined ;
93
+ }
94
+
108
95
function getDefinition ( symbol : Symbol , node : Node , typeChecker : TypeChecker ) : ReferencedSymbolDefinitionInfo {
109
- const info = SymbolDisplay . getSymbolDisplayPartsDocumentationAndSymbolKind ( typeChecker , symbol , node . getSourceFile ( ) , getContainerNode ( node ) , node ) ;
110
- const name = map ( info . displayParts , p => p . text ) . join ( "" ) ;
96
+ const { displayParts , symbolKind } = SymbolDisplay . getSymbolDisplayPartsDocumentationAndSymbolKind ( typeChecker , symbol , node . getSourceFile ( ) , getContainerNode ( node ) , node ) ;
97
+ const name = displayParts . map ( p => p . text ) . join ( "" ) ;
111
98
const declarations = symbol . declarations ;
112
99
if ( ! declarations || declarations . length === 0 ) {
113
100
return undefined ;
@@ -117,10 +104,10 @@ namespace ts.FindAllReferences {
117
104
containerKind : "" ,
118
105
containerName : "" ,
119
106
name,
120
- kind : info . symbolKind ,
107
+ kind : symbolKind ,
121
108
fileName : declarations [ 0 ] . getSourceFile ( ) . fileName ,
122
109
textSpan : createTextSpan ( declarations [ 0 ] . getStart ( ) , 0 ) ,
123
- displayParts : info . displayParts
110
+ displayParts
124
111
} ;
125
112
}
126
113
@@ -351,6 +338,43 @@ namespace ts.FindAllReferences {
351
338
}
352
339
}
353
340
341
+ function getAllReferencesForKeyword ( sourceFiles : SourceFile [ ] , keywordKind : ts . SyntaxKind , cancellationToken : CancellationToken ) : ReferencedSymbol [ ] {
342
+ const name = tokenToString ( keywordKind ) ;
343
+ const definition : ReferencedSymbolDefinitionInfo = {
344
+ containerKind : "" ,
345
+ containerName : "" ,
346
+ fileName : "" ,
347
+ kind : ScriptElementKind . keyword ,
348
+ name,
349
+ textSpan : createTextSpan ( 0 , 1 ) ,
350
+ displayParts : [ { text : name , kind : ScriptElementKind . keyword } ]
351
+ }
352
+
353
+ const references : ReferenceEntry [ ] = [ ] ;
354
+ for ( const sourceFile of sourceFiles ) {
355
+ cancellationToken . throwIfCancellationRequested ( ) ;
356
+ addReferencesForKeywordInFile ( sourceFile , keywordKind , name , cancellationToken , references ) ;
357
+ }
358
+
359
+ return [ { definition, references } ] ;
360
+ }
361
+
362
+ function addReferencesForKeywordInFile ( sourceFile : SourceFile , kind : SyntaxKind , searchText : string , cancellationToken : CancellationToken , references : Push < ReferenceEntry > ) : void {
363
+ const possiblePositions = getPossibleSymbolReferencePositions ( sourceFile , searchText , sourceFile . getStart ( ) , sourceFile . getEnd ( ) , cancellationToken ) ;
364
+ for ( const position of possiblePositions ) {
365
+ cancellationToken . throwIfCancellationRequested ( ) ;
366
+ const referenceLocation = getTouchingPropertyName ( sourceFile , position ) ;
367
+ if ( referenceLocation . kind === kind ) {
368
+ references . push ( {
369
+ textSpan : createTextSpanFromNode ( referenceLocation ) ,
370
+ fileName : sourceFile . fileName ,
371
+ isWriteAccess : false ,
372
+ isDefinition : false ,
373
+ } ) ;
374
+ }
375
+ }
376
+ }
377
+
354
378
/** Search within node "container" for references for a search value, where the search value is defined as a
355
379
* tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
356
380
* searchLocation: a node where the search value
@@ -375,67 +399,64 @@ namespace ts.FindAllReferences {
375
399
376
400
const parents = getParentSymbolsOfPropertyAccess ( ) ;
377
401
const inheritsFromCache : Map < boolean > = createMap < boolean > ( ) ;
402
+ // Build the set of symbols to search for, initially it has only the current symbol
403
+ const searchSymbols = populateSearchSymbolSet ( searchSymbol , searchLocation , typeChecker , implementations ) ;
378
404
379
- if ( possiblePositions . length ) {
380
- // Build the set of symbols to search for, initially it has only the current symbol
381
- const searchSymbols = populateSearchSymbolSet ( searchSymbol , searchLocation , typeChecker , implementations ) ;
382
-
383
- forEach ( possiblePositions , position => {
384
- cancellationToken . throwIfCancellationRequested ( ) ;
405
+ for ( const position of possiblePositions ) {
406
+ cancellationToken . throwIfCancellationRequested ( ) ;
385
407
386
- const referenceLocation = getTouchingPropertyName ( sourceFile , position ) ;
387
- if ( ! isValidReferencePosition ( referenceLocation , searchText ) ) {
388
- // This wasn't the start of a token. Check to see if it might be a
389
- // match in a comment or string if that's what the caller is asking
390
- // for.
391
- if ( ! implementations && ( ( findInStrings && isInString ( sourceFile , position ) ) ||
392
- ( findInComments && isInNonReferenceComment ( sourceFile , position ) ) ) ) {
393
-
394
- // In the case where we're looking inside comments/strings, we don't have
395
- // an actual definition. So just use 'undefined' here. Features like
396
- // 'Rename' won't care (as they ignore the definitions), and features like
397
- // 'FindReferences' will just filter out these results.
398
- result . push ( {
399
- definition : undefined ,
400
- references : [ {
401
- fileName : sourceFile . fileName ,
402
- textSpan : createTextSpan ( position , searchText . length ) ,
403
- isWriteAccess : false ,
404
- isDefinition : false
405
- } ]
406
- } ) ;
407
- }
408
- return ;
408
+ const referenceLocation = getTouchingPropertyName ( sourceFile , position ) ;
409
+ if ( ! isValidReferencePosition ( referenceLocation , searchText ) ) {
410
+ // This wasn't the start of a token. Check to see if it might be a
411
+ // match in a comment or string if that's what the caller is asking
412
+ // for.
413
+ if ( ! implementations && ( ( findInStrings && isInString ( sourceFile , position ) ) ||
414
+ ( findInComments && isInNonReferenceComment ( sourceFile , position ) ) ) ) {
415
+
416
+ // In the case where we're looking inside comments/strings, we don't have
417
+ // an actual definition. So just use 'undefined' here. Features like
418
+ // 'Rename' won't care (as they ignore the definitions), and features like
419
+ // 'FindReferences' will just filter out these results.
420
+ result . push ( {
421
+ definition : undefined ,
422
+ references : [ {
423
+ fileName : sourceFile . fileName ,
424
+ textSpan : createTextSpan ( position , searchText . length ) ,
425
+ isWriteAccess : false ,
426
+ isDefinition : false
427
+ } ]
428
+ } ) ;
409
429
}
430
+ continue ;
431
+ }
410
432
411
- if ( ! ( getMeaningFromLocation ( referenceLocation ) & searchMeaning ) ) {
412
- return ;
413
- }
433
+ if ( ! ( getMeaningFromLocation ( referenceLocation ) & searchMeaning ) ) {
434
+ continue ;
435
+ }
414
436
415
- const referenceSymbol = typeChecker . getSymbolAtLocation ( referenceLocation ) ;
416
- if ( referenceSymbol ) {
417
- const referenceSymbolDeclaration = referenceSymbol . valueDeclaration ;
418
- const shorthandValueSymbol = typeChecker . getShorthandAssignmentValueSymbol ( referenceSymbolDeclaration ) ;
419
- const relatedSymbol = getRelatedSymbol ( searchSymbols , referenceSymbol , referenceLocation ,
420
- /*searchLocationIsConstructor*/ searchLocation . kind === SyntaxKind . ConstructorKeyword , parents , inheritsFromCache , typeChecker ) ;
437
+ const referenceSymbol = typeChecker . getSymbolAtLocation ( referenceLocation ) ;
438
+ if ( referenceSymbol ) {
439
+ const referenceSymbolDeclaration = referenceSymbol . valueDeclaration ;
440
+ const shorthandValueSymbol = typeChecker . getShorthandAssignmentValueSymbol ( referenceSymbolDeclaration ) ;
441
+ const relatedSymbol = getRelatedSymbol ( searchSymbols , referenceSymbol , referenceLocation ,
442
+ /*searchLocationIsConstructor*/ searchLocation . kind === SyntaxKind . ConstructorKeyword , parents , inheritsFromCache , typeChecker ) ;
421
443
422
- if ( relatedSymbol ) {
423
- addReferenceToRelatedSymbol ( referenceLocation , relatedSymbol ) ;
424
- }
425
- /* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
426
- * has two meaning : property name and property value. Therefore when we do findAllReference at the position where
427
- * an identifier is declared, the language service should return the position of the variable declaration as well as
428
- * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
429
- * position of property accessing, the referenceEntry of such position will be handled in the first case.
430
- */
431
- else if ( ! ( referenceSymbol . flags & SymbolFlags . Transient ) && searchSymbols . indexOf ( shorthandValueSymbol ) >= 0 ) {
432
- addReferenceToRelatedSymbol ( referenceSymbolDeclaration . name , shorthandValueSymbol ) ;
433
- }
434
- else if ( searchLocation . kind === SyntaxKind . ConstructorKeyword ) {
435
- findAdditionalConstructorReferences ( referenceSymbol , referenceLocation ) ;
436
- }
444
+ if ( relatedSymbol ) {
445
+ addReferenceToRelatedSymbol ( referenceLocation , relatedSymbol ) ;
437
446
}
438
- } ) ;
447
+ /* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
448
+ * has two meaning : property name and property value. Therefore when we do findAllReference at the position where
449
+ * an identifier is declared, the language service should return the position of the variable declaration as well as
450
+ * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
451
+ * position of property accessing, the referenceEntry of such position will be handled in the first case.
452
+ */
453
+ else if ( ! ( referenceSymbol . flags & SymbolFlags . Transient ) && searchSymbols . indexOf ( shorthandValueSymbol ) >= 0 ) {
454
+ addReferenceToRelatedSymbol ( referenceSymbolDeclaration . name , shorthandValueSymbol ) ;
455
+ }
456
+ else if ( searchLocation . kind === SyntaxKind . ConstructorKeyword ) {
457
+ findAdditionalConstructorReferences ( referenceSymbol , referenceLocation ) ;
458
+ }
459
+ }
439
460
}
440
461
return ;
441
462
0 commit comments