Fix the issue when file is attached to project because its a root file name but program contains instead its d.ts

Fixes #33323
This commit is contained in:
Sheetal Nandi 2019-09-27 08:58:42 -07:00
parent 1c24e27ce4
commit 8e4f47c8a9

View File

@ -434,7 +434,7 @@ namespace ts.server {
const memGetDefinition = memoize(getDefinition);
projectService.forEachEnabledProject(project => {
if (!addToSeen(seenProjects, project.projectName)) return;
const definition = getDefinitionInProject(memGetDefinition(), defaultProject, project);
const definition = mapDefinitionInProject(memGetDefinition(), defaultProject, project);
if (definition) {
toDo = callbackProjectAndLocation<TLocation>({ project, location: definition as TLocation }, projectService, toDo, seenProjects, cb);
}
@ -446,14 +446,35 @@ namespace ts.server {
}
}
function getDefinitionInProject(definition: DocumentPosition | undefined, definingProject: Project, project: Project): DocumentPosition | undefined {
if (!definition || project.containsFile(toNormalizedPath(definition.fileName))) return definition;
function mapDefinitionInProject(definition: DocumentPosition | undefined, definingProject: Project, project: Project): DocumentPosition | undefined {
// If the definition is actually from the project, definition is correct as is
if (!definition ||
project.containsFile(toNormalizedPath(definition.fileName)) &&
!isLocationProjectReferenceRedirect(project, definition)) {
return definition;
}
const mappedDefinition = definingProject.isSourceOfProjectReferenceRedirect(definition.fileName) ?
definition :
definingProject.getLanguageService().getSourceMapper().tryGetGeneratedPosition(definition);
return mappedDefinition && project.containsFile(toNormalizedPath(mappedDefinition.fileName)) ? mappedDefinition : undefined;
}
function isLocationProjectReferenceRedirect(project: Project, location: DocumentPosition | undefined) {
if (!location) return false;
const program = project.getLanguageService().getProgram();
if (!program) return false;
const sourceFile = program.getSourceFile(location.fileName);
// It is possible that location is attached to project but
// the program actually includes its redirect instead.
// This happens when rootFile in project is one of the file from referenced project
// Thus root is attached but program doesnt have the actual .ts file but .d.ts
// If this is not the file we were actually looking, return rest of the toDo
return !!sourceFile &&
sourceFile.resolvedPath !== sourceFile.path &&
sourceFile.resolvedPath !== project.toPath(location.fileName);
}
function callbackProjectAndLocation<TLocation extends DocumentPosition | undefined>(
projectAndLocation: ProjectAndLocation<TLocation>,
projectService: ProjectService,
@ -461,7 +482,10 @@ namespace ts.server {
seenProjects: Map<true>,
cb: CombineProjectOutputCallback<TLocation>,
): ProjectAndLocation<TLocation>[] | undefined {
if (projectAndLocation.project.getCancellationToken().isCancellationRequested()) return undefined; // Skip rest of toDo if cancelled
const { project, location } = projectAndLocation;
if (project.getCancellationToken().isCancellationRequested()) return undefined; // Skip rest of toDo if cancelled
// If this is not the file we were actually looking, return rest of the toDo
if (isLocationProjectReferenceRedirect(project, location)) return toDo;
cb(projectAndLocation, (project, location) => {
seenProjects.set(projectAndLocation.project.projectName, true);
const originalLocation = projectService.getOriginalLocationEnsuringConfiguredProject(project, location);
@ -475,8 +499,8 @@ namespace ts.server {
}
const symlinkedProjectsMap = projectService.getSymlinkedProjects(originalScriptInfo);
if (symlinkedProjectsMap) {
symlinkedProjectsMap.forEach((symlinkedProjects) => {
for (const symlinkedProject of symlinkedProjects) addToTodo({ project: symlinkedProject, location: originalLocation as TLocation }, toDo!, seenProjects);
symlinkedProjectsMap.forEach((symlinkedProjects, symlinkedPath) => {
for (const symlinkedProject of symlinkedProjects) addToTodo({ project: symlinkedProject, location: { fileName: symlinkedPath, pos: originalLocation.pos } as TLocation }, toDo!, seenProjects);
});
}
return originalLocation === location ? undefined : originalLocation;