@@ -330,7 +330,7 @@ namespace ts.server {
330
330
perProjectResults . forEach ( ( projectResults , project ) => {
331
331
for ( const result of projectResults ) {
332
332
// If there's a mapped location, it'll appear in the results for another project
333
- if ( ! seen . has ( result ) && ! getMappedLocation ( documentSpanLocation ( result ) , project ) ) {
333
+ if ( ! seen . has ( result ) && ! getMappedLocationForProject ( documentSpanLocation ( result ) , project ) ) {
334
334
results . push ( result ) ;
335
335
seen . add ( result ) ;
336
336
}
@@ -368,7 +368,7 @@ namespace ts.server {
368
368
} ,
369
369
) ;
370
370
371
- // No re-mapping is required if there's exactly one project
371
+ // No re-mapping or isDefinition updatses are required if there's exactly one project
372
372
if ( isArray ( perProjectResults ) ) {
373
373
return perProjectResults ;
374
374
}
@@ -378,18 +378,66 @@ namespace ts.server {
378
378
379
379
const results : ReferencedSymbol [ ] = [ ] ;
380
380
381
- const clearIsDefinition = perProjectResults . get ( defaultProject ) ! [ 0 ] . references [ 0 ] . isDefinition === undefined ;
381
+ const defaultProjectResults = perProjectResults . get ( defaultProject ) ! ;
382
+ if ( defaultProjectResults [ 0 ] . references [ 0 ] . isDefinition === undefined ) {
383
+ // Clear all isDefinition properties
384
+ perProjectResults . forEach ( projectResults => {
385
+ for ( const referencedSymbol of projectResults ) {
386
+ for ( const ref of referencedSymbol . references ) {
387
+ delete ref . isDefinition ;
388
+ }
389
+ }
390
+ } ) ;
391
+ }
392
+ else {
393
+ // Correct isDefinition properties from projects other than defaultProject
394
+ const knownSymbolSpans = createDocumentSpanSet ( ) ;
395
+ for ( const referencedSymbol of defaultProjectResults ) {
396
+ for ( const ref of referencedSymbol . references ) {
397
+ if ( ref . isDefinition ) {
398
+ knownSymbolSpans . add ( ref ) ;
399
+ // One is enough - updateIsDefinitionOfReferencedSymbols will fill out the set based on symbols
400
+ break ;
401
+ }
402
+ }
403
+ }
404
+
405
+ const updatedProjects = new Set < Project > ( ) ;
406
+ while ( true ) {
407
+ let progress = false ;
408
+ perProjectResults . forEach ( ( referencedSymbols , project ) => {
409
+ if ( updatedProjects . has ( project ) ) return ;
410
+ const updated = project . getLanguageService ( ) . updateIsDefinitionOfReferencedSymbols ( referencedSymbols , knownSymbolSpans ) ;
411
+ if ( updated ) {
412
+ updatedProjects . add ( project ) ;
413
+ progress = true ;
414
+ }
415
+ } ) ;
416
+ if ( ! progress ) break ;
417
+ }
418
+
419
+ perProjectResults . forEach ( ( referencedSymbols , project ) => {
420
+ if ( updatedProjects . has ( project ) ) return ;
421
+ for ( const referencedSymbol of referencedSymbols ) {
422
+ for ( const ref of referencedSymbol . references ) {
423
+ ref . isDefinition = false ;
424
+ }
425
+ }
426
+ } ) ;
427
+ }
428
+
429
+ // TODO (acasey): skip this aggregation when simplifying results?
382
430
383
431
perProjectResults . forEach ( ( projectResults , project ) => {
384
432
for ( const referencedSymbol of projectResults ) {
385
- const mappedDefinitionFile = getMappedLocation ( documentSpanLocation ( referencedSymbol . definition ) , project ) ;
433
+ const mappedDefinitionFile = getMappedLocationForProject ( documentSpanLocation ( referencedSymbol . definition ) , project ) ;
386
434
const definition : ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ?
387
435
referencedSymbol . definition :
388
436
{
389
437
...referencedSymbol . definition ,
390
438
textSpan : createTextSpan ( mappedDefinitionFile . pos , referencedSymbol . definition . textSpan . length ) , // Why would the length be the same in the original?
391
439
fileName : mappedDefinitionFile . fileName ,
392
- contextSpan : getMappedContextSpan ( referencedSymbol . definition , project )
440
+ contextSpan : getMappedContextSpanForProject ( referencedSymbol . definition , project )
393
441
} ;
394
442
395
443
let symbolToAddTo = find ( results , o => documentSpansEqual ( o . definition , definition ) ) ;
@@ -399,10 +447,7 @@ namespace ts.server {
399
447
}
400
448
401
449
for ( const ref of referencedSymbol . references ) {
402
- if ( ! contains ( symbolToAddTo . references , ref , documentSpansEqual ) && ! getMappedLocation ( documentSpanLocation ( ref ) , project ) ) {
403
- if ( clearIsDefinition ) {
404
- delete ref . isDefinition ;
405
- }
450
+ if ( ! contains ( symbolToAddTo . references , ref , documentSpansEqual ) && ! getMappedLocationForProject ( documentSpanLocation ( ref ) , project ) ) {
406
451
symbolToAddTo . references . push ( ref ) ;
407
452
}
408
453
}
@@ -603,39 +648,16 @@ namespace ts.server {
603
648
return { fileName, pos : textSpan . start } ;
604
649
}
605
650
606
- function getMappedLocation ( location : DocumentPosition , project : Project ) : DocumentPosition | undefined {
607
- const mapsTo = project . getSourceMapper ( ) . tryGetSourcePosition ( location ) ;
608
- return mapsTo && project . projectService . fileExists ( toNormalizedPath ( mapsTo . fileName ) ) ? mapsTo : undefined ;
651
+ function getMappedLocationForProject ( location : DocumentPosition , project : Project ) : DocumentPosition | undefined {
652
+ return getMappedLocation ( location , project . getSourceMapper ( ) , p => project . projectService . fileExists ( p as NormalizedPath ) ) ;
609
653
}
610
654
611
- function getMappedDocumentSpan ( documentSpan : DocumentSpan , project : Project ) : DocumentSpan | undefined {
612
- const newPosition = getMappedLocation ( documentSpanLocation ( documentSpan ) , project ) ;
613
- if ( ! newPosition ) return undefined ;
614
- return {
615
- fileName : newPosition . fileName ,
616
- textSpan : {
617
- start : newPosition . pos ,
618
- length : documentSpan . textSpan . length
619
- } ,
620
- originalFileName : documentSpan . fileName ,
621
- originalTextSpan : documentSpan . textSpan ,
622
- contextSpan : getMappedContextSpan ( documentSpan , project ) ,
623
- originalContextSpan : documentSpan . contextSpan
624
- } ;
655
+ function getMappedDocumentSpanForProject ( documentSpan : DocumentSpan , project : Project ) : DocumentSpan | undefined {
656
+ return getMappedDocumentSpan ( documentSpan , project . getSourceMapper ( ) , p => project . projectService . fileExists ( p as NormalizedPath ) ) ;
625
657
}
626
658
627
- function getMappedContextSpan ( documentSpan : DocumentSpan , project : Project ) : TextSpan | undefined {
628
- const contextSpanStart = documentSpan . contextSpan && getMappedLocation (
629
- { fileName : documentSpan . fileName , pos : documentSpan . contextSpan . start } ,
630
- project
631
- ) ;
632
- const contextSpanEnd = documentSpan . contextSpan && getMappedLocation (
633
- { fileName : documentSpan . fileName , pos : documentSpan . contextSpan . start + documentSpan . contextSpan . length } ,
634
- project
635
- ) ;
636
- return contextSpanStart && contextSpanEnd ?
637
- { start : contextSpanStart . pos , length : contextSpanEnd . pos - contextSpanStart . pos } :
638
- undefined ;
659
+ function getMappedContextSpanForProject ( documentSpan : DocumentSpan , project : Project ) : TextSpan | undefined {
660
+ return getMappedContextSpan ( documentSpan , project . getSourceMapper ( ) , p => project . projectService . fileExists ( p as NormalizedPath ) ) ;
639
661
}
640
662
641
663
const invalidPartialSemanticModeCommands : readonly CommandNames [ ] = [
@@ -1249,7 +1271,7 @@ namespace ts.server {
1249
1271
1250
1272
private mapDefinitionInfoLocations ( definitions : readonly DefinitionInfo [ ] , project : Project ) : readonly DefinitionInfo [ ] {
1251
1273
return definitions . map ( ( info ) : DefinitionInfo => {
1252
- const newDocumentSpan = getMappedDocumentSpan ( info , project ) ;
1274
+ const newDocumentSpan = getMappedDocumentSpanForProject ( info , project ) ;
1253
1275
return ! newDocumentSpan ? info : {
1254
1276
...newDocumentSpan ,
1255
1277
containerKind : info . containerKind ,
@@ -1390,7 +1412,7 @@ namespace ts.server {
1390
1412
1391
1413
private mapImplementationLocations ( implementations : readonly ImplementationLocation [ ] , project : Project ) : readonly ImplementationLocation [ ] {
1392
1414
return implementations . map ( ( info ) : ImplementationLocation => {
1393
- const newDocumentSpan = getMappedDocumentSpan ( info , project ) ;
1415
+ const newDocumentSpan = getMappedDocumentSpanForProject ( info , project ) ;
1394
1416
return ! newDocumentSpan ? info : {
1395
1417
...newDocumentSpan ,
1396
1418
kind : info . kind ,
@@ -1626,7 +1648,7 @@ namespace ts.server {
1626
1648
const symbolStartOffset = nameSpan ? scriptInfo . positionToLineOffset ( nameSpan . start ) . offset : 0 ;
1627
1649
const symbolName = nameSpan ? scriptInfo . getSnapshot ( ) . getText ( nameSpan . start , textSpanEnd ( nameSpan ) ) : "" ;
1628
1650
const refs : readonly protocol . ReferencesResponseItem [ ] = flatMap ( references , referencedSymbol => {
1629
- return referencedSymbol . references . map ( entry => referenceEntryToReferencesResponseItem ( this . projectService , entry ) ) ;
1651
+ return referencedSymbol . references . map ( entry => referenceEntryToReferencesResponseItem ( this . projectService , entry ) ) ; // TODO (acasey): de-dup
1630
1652
} ) ;
1631
1653
return { refs, symbolName, symbolStartOffset, symbolDisplayString } ;
1632
1654
}
@@ -2230,7 +2252,7 @@ namespace ts.server {
2230
2252
// Mutates `outputs`
2231
2253
function addItemsForProject ( project : Project ) {
2232
2254
const projectItems = project . getLanguageService ( ) . getNavigateToItems ( searchValue , maxResultCount , /*filename*/ undefined , /*excludeDts*/ project . isNonTsProject ( ) ) ;
2233
- const unseenItems = filter ( projectItems , item => tryAddSeenItem ( item ) && ! getMappedLocation ( documentSpanLocation ( item ) , project ) ) ;
2255
+ const unseenItems = filter ( projectItems , item => tryAddSeenItem ( item ) && ! getMappedLocationForProject ( documentSpanLocation ( item ) , project ) ) ;
2234
2256
if ( unseenItems . length ) {
2235
2257
outputs . push ( { project, navigateToItems : unseenItems } ) ;
2236
2258
}
0 commit comments