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,45 @@ 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
+ if ( sourceFileHasName ( sourceFile , name ) ) {
357
+ addReferencesForKeywordInFile ( sourceFile , keywordKind , name , cancellationToken , references ) ;
358
+ }
359
+ }
360
+
361
+ return [ { definition, references } ] ;
362
+ }
363
+
364
+ function addReferencesForKeywordInFile ( sourceFile : SourceFile , kind : SyntaxKind , searchText : string , cancellationToken : CancellationToken , references : Push < ReferenceEntry > ) : void {
365
+ const possiblePositions = getPossibleSymbolReferencePositions ( sourceFile , searchText , sourceFile . getStart ( ) , sourceFile . getEnd ( ) , cancellationToken ) ;
366
+ for ( const position of possiblePositions ) {
367
+ cancellationToken . throwIfCancellationRequested ( ) ;
368
+ const referenceLocation = getTouchingPropertyName ( sourceFile , position ) ;
369
+ if ( referenceLocation . kind === kind ) {
370
+ references . push ( {
371
+ textSpan : createTextSpanFromNode ( referenceLocation ) ,
372
+ fileName : sourceFile . fileName ,
373
+ isWriteAccess : false ,
374
+ isDefinition : false ,
375
+ } ) ;
376
+ }
377
+ }
378
+ }
379
+
354
380
/** Search within node "container" for references for a search value, where the search value is defined as a
355
381
* tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
356
382
* searchLocation: a node where the search value
@@ -375,67 +401,64 @@ namespace ts.FindAllReferences {
375
401
376
402
const parents = getParentSymbolsOfPropertyAccess ( ) ;
377
403
const inheritsFromCache : Map < boolean > = createMap < boolean > ( ) ;
404
+ // Build the set of symbols to search for, initially it has only the current symbol
405
+ const searchSymbols = populateSearchSymbolSet ( searchSymbol , searchLocation , typeChecker , implementations ) ;
378
406
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 ( ) ;
407
+ for ( const position of possiblePositions ) {
408
+ cancellationToken . throwIfCancellationRequested ( ) ;
385
409
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 ;
410
+ const referenceLocation = getTouchingPropertyName ( sourceFile , position ) ;
411
+ if ( ! isValidReferencePosition ( referenceLocation , searchText ) ) {
412
+ // This wasn't the start of a token. Check to see if it might be a
413
+ // match in a comment or string if that's what the caller is asking
414
+ // for.
415
+ if ( ! implementations && ( ( findInStrings && isInString ( sourceFile , position ) ) ||
416
+ ( findInComments && isInNonReferenceComment ( sourceFile , position ) ) ) ) {
417
+
418
+ // In the case where we're looking inside comments/strings, we don't have
419
+ // an actual definition. So just use 'undefined' here. Features like
420
+ // 'Rename' won't care (as they ignore the definitions), and features like
421
+ // 'FindReferences' will just filter out these results.
422
+ result . push ( {
423
+ definition : undefined ,
424
+ references : [ {
425
+ fileName : sourceFile . fileName ,
426
+ textSpan : createTextSpan ( position , searchText . length ) ,
427
+ isWriteAccess : false ,
428
+ isDefinition : false
429
+ } ]
430
+ } ) ;
409
431
}
432
+ continue ;
433
+ }
410
434
411
- if ( ! ( getMeaningFromLocation ( referenceLocation ) & searchMeaning ) ) {
412
- return ;
413
- }
435
+ if ( ! ( getMeaningFromLocation ( referenceLocation ) & searchMeaning ) ) {
436
+ continue ;
437
+ }
414
438
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 ) ;
439
+ const referenceSymbol = typeChecker . getSymbolAtLocation ( referenceLocation ) ;
440
+ if ( referenceSymbol ) {
441
+ const referenceSymbolDeclaration = referenceSymbol . valueDeclaration ;
442
+ const shorthandValueSymbol = typeChecker . getShorthandAssignmentValueSymbol ( referenceSymbolDeclaration ) ;
443
+ const relatedSymbol = getRelatedSymbol ( searchSymbols , referenceSymbol , referenceLocation ,
444
+ /*searchLocationIsConstructor*/ searchLocation . kind === SyntaxKind . ConstructorKeyword , parents , inheritsFromCache , typeChecker ) ;
421
445
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
- }
446
+ if ( relatedSymbol ) {
447
+ addReferenceToRelatedSymbol ( referenceLocation , relatedSymbol ) ;
437
448
}
438
- } ) ;
449
+ /* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
450
+ * has two meaning : property name and property value. Therefore when we do findAllReference at the position where
451
+ * an identifier is declared, the language service should return the position of the variable declaration as well as
452
+ * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
453
+ * position of property accessing, the referenceEntry of such position will be handled in the first case.
454
+ */
455
+ else if ( ! ( referenceSymbol . flags & SymbolFlags . Transient ) && searchSymbols . indexOf ( shorthandValueSymbol ) >= 0 ) {
456
+ addReferenceToRelatedSymbol ( referenceSymbolDeclaration . name , shorthandValueSymbol ) ;
457
+ }
458
+ else if ( searchLocation . kind === SyntaxKind . ConstructorKeyword ) {
459
+ findAdditionalConstructorReferences ( referenceSymbol , referenceLocation ) ;
460
+ }
461
+ }
439
462
}
440
463
return ;
441
464
0 commit comments