@@ -434,7 +434,7 @@ namespace ts.server {
434
434
const memGetDefinition = memoize ( getDefinition ) ;
435
435
projectService . forEachEnabledProject ( project => {
436
436
if ( ! addToSeen ( seenProjects , project . projectName ) ) return ;
437
- const definition = getDefinitionInProject ( memGetDefinition ( ) , defaultProject , project ) ;
437
+ const definition = mapDefinitionInProject ( memGetDefinition ( ) , defaultProject , project ) ;
438
438
if ( definition ) {
439
439
toDo = callbackProjectAndLocation < TLocation > ( { project, location : definition as TLocation } , projectService , toDo , seenProjects , cb ) ;
440
440
}
@@ -446,22 +446,46 @@ namespace ts.server {
446
446
}
447
447
}
448
448
449
- function getDefinitionInProject ( definition : DocumentPosition | undefined , definingProject : Project , project : Project ) : DocumentPosition | undefined {
450
- if ( ! definition || project . containsFile ( toNormalizedPath ( definition . fileName ) ) ) return definition ;
449
+ function mapDefinitionInProject ( definition : DocumentPosition | undefined , definingProject : Project , project : Project ) : DocumentPosition | undefined {
450
+ // If the definition is actually from the project, definition is correct as is
451
+ if ( ! definition ||
452
+ project . containsFile ( toNormalizedPath ( definition . fileName ) ) &&
453
+ ! isLocationProjectReferenceRedirect ( project , definition ) ) {
454
+ return definition ;
455
+ }
451
456
const mappedDefinition = definingProject . isSourceOfProjectReferenceRedirect ( definition . fileName ) ?
452
457
definition :
453
458
definingProject . getLanguageService ( ) . getSourceMapper ( ) . tryGetGeneratedPosition ( definition ) ;
454
459
return mappedDefinition && project . containsFile ( toNormalizedPath ( mappedDefinition . fileName ) ) ? mappedDefinition : undefined ;
455
460
}
456
461
462
+ function isLocationProjectReferenceRedirect ( project : Project , location : DocumentPosition | undefined ) {
463
+ if ( ! location ) return false ;
464
+ const program = project . getLanguageService ( ) . getProgram ( ) ;
465
+ if ( ! program ) return false ;
466
+ const sourceFile = program . getSourceFile ( location . fileName ) ;
467
+
468
+ // It is possible that location is attached to project but
469
+ // the program actually includes its redirect instead.
470
+ // This happens when rootFile in project is one of the file from referenced project
471
+ // Thus root is attached but program doesnt have the actual .ts file but .d.ts
472
+ // If this is not the file we were actually looking, return rest of the toDo
473
+ return ! ! sourceFile &&
474
+ sourceFile . resolvedPath !== sourceFile . path &&
475
+ sourceFile . resolvedPath !== project . toPath ( location . fileName ) ;
476
+ }
477
+
457
478
function callbackProjectAndLocation < TLocation extends DocumentPosition | undefined > (
458
479
projectAndLocation : ProjectAndLocation < TLocation > ,
459
480
projectService : ProjectService ,
460
481
toDo : ProjectAndLocation < TLocation > [ ] | undefined ,
461
482
seenProjects : Map < true > ,
462
483
cb : CombineProjectOutputCallback < TLocation > ,
463
484
) : ProjectAndLocation < TLocation > [ ] | undefined {
464
- if ( projectAndLocation . project . getCancellationToken ( ) . isCancellationRequested ( ) ) return undefined ; // Skip rest of toDo if cancelled
485
+ const { project, location } = projectAndLocation ;
486
+ if ( project . getCancellationToken ( ) . isCancellationRequested ( ) ) return undefined ; // Skip rest of toDo if cancelled
487
+ // If this is not the file we were actually looking, return rest of the toDo
488
+ if ( isLocationProjectReferenceRedirect ( project , location ) ) return toDo ;
465
489
cb ( projectAndLocation , ( project , location ) => {
466
490
seenProjects . set ( projectAndLocation . project . projectName , true ) ;
467
491
const originalLocation = projectService . getOriginalLocationEnsuringConfiguredProject ( project , location ) ;
@@ -475,8 +499,8 @@ namespace ts.server {
475
499
}
476
500
const symlinkedProjectsMap = projectService . getSymlinkedProjects ( originalScriptInfo ) ;
477
501
if ( symlinkedProjectsMap ) {
478
- symlinkedProjectsMap . forEach ( ( symlinkedProjects ) => {
479
- for ( const symlinkedProject of symlinkedProjects ) addToTodo ( { project : symlinkedProject , location : originalLocation as TLocation } , toDo ! , seenProjects ) ;
502
+ symlinkedProjectsMap . forEach ( ( symlinkedProjects , symlinkedPath ) => {
503
+ for ( const symlinkedProject of symlinkedProjects ) addToTodo ( { project : symlinkedProject , location : { fileName : symlinkedPath , pos : originalLocation . pos } as TLocation } , toDo ! , seenProjects ) ;
480
504
} ) ;
481
505
}
482
506
return originalLocation === location ? undefined : originalLocation ;
0 commit comments