Skip to content

Commit 8e4f47c

Browse files
committed
Fix the issue when file is attached to project because its a root file name but program contains instead its d.ts
Fixes #33323
1 parent 1c24e27 commit 8e4f47c

File tree

1 file changed

+30
-6
lines changed

1 file changed

+30
-6
lines changed

src/server/session.ts

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ namespace ts.server {
434434
const memGetDefinition = memoize(getDefinition);
435435
projectService.forEachEnabledProject(project => {
436436
if (!addToSeen(seenProjects, project.projectName)) return;
437-
const definition = getDefinitionInProject(memGetDefinition(), defaultProject, project);
437+
const definition = mapDefinitionInProject(memGetDefinition(), defaultProject, project);
438438
if (definition) {
439439
toDo = callbackProjectAndLocation<TLocation>({ project, location: definition as TLocation }, projectService, toDo, seenProjects, cb);
440440
}
@@ -446,22 +446,46 @@ namespace ts.server {
446446
}
447447
}
448448

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+
}
451456
const mappedDefinition = definingProject.isSourceOfProjectReferenceRedirect(definition.fileName) ?
452457
definition :
453458
definingProject.getLanguageService().getSourceMapper().tryGetGeneratedPosition(definition);
454459
return mappedDefinition && project.containsFile(toNormalizedPath(mappedDefinition.fileName)) ? mappedDefinition : undefined;
455460
}
456461

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+
457478
function callbackProjectAndLocation<TLocation extends DocumentPosition | undefined>(
458479
projectAndLocation: ProjectAndLocation<TLocation>,
459480
projectService: ProjectService,
460481
toDo: ProjectAndLocation<TLocation>[] | undefined,
461482
seenProjects: Map<true>,
462483
cb: CombineProjectOutputCallback<TLocation>,
463484
): 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;
465489
cb(projectAndLocation, (project, location) => {
466490
seenProjects.set(projectAndLocation.project.projectName, true);
467491
const originalLocation = projectService.getOriginalLocationEnsuringConfiguredProject(project, location);
@@ -475,8 +499,8 @@ namespace ts.server {
475499
}
476500
const symlinkedProjectsMap = projectService.getSymlinkedProjects(originalScriptInfo);
477501
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);
480504
});
481505
}
482506
return originalLocation === location ? undefined : originalLocation;

0 commit comments

Comments
 (0)