Skip to content

Commit 84c06bb

Browse files
committed
Create ancestor projects for composite projects till projectRoot but load them and their references when doing all project wide operation like rename
1 parent 9d2f618 commit 84c06bb

File tree

3 files changed

+40
-8
lines changed

3 files changed

+40
-8
lines changed

src/server/editorServices.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2533,6 +2533,28 @@ namespace ts.server {
25332533
}
25342534
}
25352535

2536+
/*@internal*/
2537+
loadAncestorAndReferenceConfiguredProjects(forProjects: ReadonlyMap<Project>) {
2538+
// Load all the projects ancestor projects for seen projects
2539+
this.configuredProjects.forEach(project => {
2540+
if (project.isInitialLoadPending() &&
2541+
project.forEachProjectReference(returnFalse, returnFalse, path => forProjects.has(path))) {
2542+
// Load the project
2543+
project.updateGraph();
2544+
// We want to also load the referenced projects
2545+
// TODO:: Save them when project stays alive but at lower priority
2546+
project.forEachProjectReference(ref => {
2547+
if (ref) {
2548+
const configFileName = toNormalizedPath(ref.sourceFile.fileName);
2549+
const configuredProject = this.findConfiguredProjectByProjectName(configFileName) ||
2550+
this.createAndLoadConfiguredProject(toNormalizedPath(configFileName), `Creating project for transitive reference of ancestor project: ${project.projectName}`);
2551+
updateProjectIfDirty(configuredProject);
2552+
}
2553+
}, noop, noop);
2554+
}
2555+
});
2556+
}
2557+
25362558
private removeOrphanConfiguredProjects() {
25372559
const toRemoveConfiguredProjects = cloneMap(this.configuredProjects);
25382560

@@ -2546,7 +2568,7 @@ namespace ts.server {
25462568
markOriginalProjectsAsUsed(project);
25472569
}
25482570
else {
2549-
project.forEachResolvedProjectReference(
2571+
project.forEachProjectReference(
25502572
resolvedRef => markProjectAsUsedIfReferencedConfigWithOpenRef(project, resolvedRef && this.configuredProjects.get(resolvedRef.sourceFile.path)),
25512573
projectRef => markProjectAsUsedIfReferencedConfigWithOpenRef(project, this.configuredProjects.get(this.toPath(projectRef.path))),
25522574
potentialProjectRef => markProjectAsUsedIfReferencedConfigWithOpenRef(project, this.configuredProjects.get(potentialProjectRef))

src/server/project.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1443,7 +1443,7 @@ namespace ts.server {
14431443
}
14441444

14451445
/*@internal*/
1446-
forEachResolvedProjectReference<T>(
1446+
forEachProjectReference<T>(
14471447
cb: (resolvedProjectReference: ResolvedProjectReference | undefined, resolvedProjectReferencePath: Path) => T | undefined,
14481448
cbProjectRef: (projectReference: ProjectReference) => T | undefined,
14491449
cbPotentialProjectRef: (path: Path) => T | undefined

src/server/session.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ namespace ts.server {
412412
): void {
413413
const projectService = defaultProject.projectService;
414414
let toDo: ProjectAndLocation<TLocation>[] | undefined;
415-
const seenProjects = createMap<true>();
415+
const seenProjects = createMap<Project>();
416416
forEachProjectInProjects(projects, initialLocation && initialLocation.fileName, (project, path) => {
417417
// TLocation shoud be either `sourcemaps.SourceMappableLocation` or `undefined`. Since `initialLocation` is `TLocation` this cast should be valid.
418418
const location = (initialLocation ? { fileName: path, position: initialLocation.position } : undefined) as TLocation;
@@ -421,9 +421,11 @@ namespace ts.server {
421421

422422
// After initial references are collected, go over every other project and see if it has a reference for the symbol definition.
423423
if (getDefinition) {
424+
projectService.loadAncestorAndReferenceConfiguredProjects(seenProjects);
425+
424426
const memGetDefinition = memoize(getDefinition);
425427
projectService.forEachEnabledProject(project => {
426-
if (!addToSeen(seenProjects, project.projectName)) return;
428+
if (!addToSeen(seenProjects, project)) return;
427429
const definition = getDefinitionInProject(memGetDefinition(), defaultProject, project);
428430
if (definition) {
429431
toDo = callbackProjectAndLocation<TLocation>({ project, location: definition as TLocation }, projectService, toDo, seenProjects, cb);
@@ -442,16 +444,24 @@ namespace ts.server {
442444
return mappedDefinition && project.containsFile(toNormalizedPath(mappedDefinition.fileName)) ? mappedDefinition : undefined;
443445
}
444446

447+
function addToSeen(seenProjects: Map<Project>, project: Project) {
448+
return ts.addToSeen(seenProjects, getProjectKey(project), project);
449+
}
450+
451+
function getProjectKey(project: Project) {
452+
return project.projectKind === ProjectKind.Configured ? (project as ConfiguredProject).canonicalConfigFilePath : project.projectName;
453+
}
454+
445455
function callbackProjectAndLocation<TLocation extends sourcemaps.SourceMappableLocation | undefined>(
446456
projectAndLocation: ProjectAndLocation<TLocation>,
447457
projectService: ProjectService,
448458
toDo: ProjectAndLocation<TLocation>[] | undefined,
449-
seenProjects: Map<true>,
459+
seenProjects: Map<Project>,
450460
cb: CombineProjectOutputCallback<TLocation>,
451461
): ProjectAndLocation<TLocation>[] | undefined {
452462
if (projectAndLocation.project.getCancellationToken().isCancellationRequested()) return undefined; // Skip rest of toDo if cancelled
453463
cb(projectAndLocation, (project, location) => {
454-
seenProjects.set(projectAndLocation.project.projectName, true);
464+
seenProjects.set(getProjectKey(projectAndLocation.project), projectAndLocation.project);
455465
const originalLocation = projectService.getOriginalLocationEnsuringConfiguredProject(project, location);
456466
if (!originalLocation) return undefined;
457467

@@ -472,8 +482,8 @@ namespace ts.server {
472482
return toDo;
473483
}
474484

475-
function addToTodo<TLocation extends sourcemaps.SourceMappableLocation | undefined>(projectAndLocation: ProjectAndLocation<TLocation>, toDo: Push<ProjectAndLocation<TLocation>>, seenProjects: Map<true>): void {
476-
if (addToSeen(seenProjects, projectAndLocation.project.projectName)) toDo.push(projectAndLocation);
485+
function addToTodo<TLocation extends sourcemaps.SourceMappableLocation | undefined>(projectAndLocation: ProjectAndLocation<TLocation>, toDo: Push<ProjectAndLocation<TLocation>>, seenProjects: Map<Project>): void {
486+
if (addToSeen(seenProjects, projectAndLocation.project)) toDo.push(projectAndLocation);
477487
}
478488

479489
function documentSpanLocation({ fileName, textSpan }: DocumentSpan): sourcemaps.SourceMappableLocation {

0 commit comments

Comments
 (0)