Skip to content

Commit 1434226

Browse files
authored
fix(language-server): Ensure LS is enabled in same order as project initialization (#1447)
ngcc processes might finish out of order, but we need to re-enable the language service for the projects in the same order that the ngcc processes were spawned in. With solution-style configs, we need to ensure that the language service enabling respects the order that the projects were defined in the references list. If we enable the language service out of order, the second project in the list will request diagnostics first and then be the project that's prioritized for that project's set of files. This will cause issues if the second project is, for example, one that only includes `*.spec.ts` files and not the entire set of files needed to compile the app (i.e. `*.module.ts`). A test was not written for this because it is difficult to consistently emulate the `ngcc` processes finishing out of order with solution style project configs. Fixes #1444
1 parent 3ef2e90 commit 1434226

File tree

1 file changed

+25
-6
lines changed

1 file changed

+25
-6
lines changed

server/src/session.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ export class Session {
5353
private readonly configuredProjToExternalProj = new Map<string, string>();
5454
private readonly logToConsole: boolean;
5555
private readonly openFiles = new MruTracker();
56+
// Tracks the spawn order and status of the `ngcc` processes. This allows us to ensure we enable
57+
// the LS in the same order the projects were created in.
58+
private projectNgccQueue: Array<{project: ts.server.Project, done: boolean}> = [];
5659
private diagnosticsTimeout: NodeJS.Timeout|null = null;
5760
private isProjectLoading = false;
5861
/**
@@ -1098,6 +1101,7 @@ export class Session {
10981101
let success = false;
10991102

11001103
try {
1104+
this.projectNgccQueue.push({project, done: false});
11011105
await resolveAndRunNgcc(configFilePath, {
11021106
report: (msg: string) => {
11031107
this.connection.sendProgress(NgccProgressType, NgccProgressToken, {
@@ -1114,19 +1118,34 @@ export class Session {
11141118
configFilePath}, language service may not operate correctly:\n` +
11151119
` ${e.message}`);
11161120
} finally {
1121+
const loadingStatus = this.projectNgccQueue.find(p => p.project === project);
1122+
if (loadingStatus !== undefined) {
1123+
loadingStatus.done = true;
1124+
}
11171125
this.connection.sendProgress(NgccProgressType, NgccProgressToken, {
11181126
done: true,
11191127
configFilePath,
11201128
success,
11211129
});
11221130
}
11231131

1124-
// Re-enable language service even if ngcc fails, because users could fix
1125-
// the problem by running ngcc themselves. If we keep language service
1126-
// disabled, there's no way users could use the extension even after
1127-
// resolving ngcc issues. On the client side, we will warn users about
1128-
// potentially degraded experience.
1129-
this.enableLanguageServiceForProject(project);
1132+
// ngcc processes might finish out of order, but we need to re-enable the language service for
1133+
// the projects in the same order that the ngcc processes were spawned in. With solution-style
1134+
// configs, we need to ensure that the language service enabling respects the order that the
1135+
// projects were defined in the references list. If we enable the language service out of order,
1136+
// the second project in the list will request diagnostics first and then be the project that's
1137+
// prioritized for that project's set of files. This will cause issues if the second project is,
1138+
// for example, one that only includes `*.spec.ts` files and not the entire set of files needed
1139+
// to compile the app (i.e. `*.module.ts`).
1140+
for (let i = 0; i < this.projectNgccQueue.length && this.projectNgccQueue[i].done; i++) {
1141+
// Re-enable language service even if ngcc fails, because users could fix
1142+
// the problem by running ngcc themselves. If we keep language service
1143+
// disabled, there's no way users could use the extension even after
1144+
// resolving ngcc issues. On the client side, we will warn users about
1145+
// potentially degraded experience.
1146+
this.enableLanguageServiceForProject(this.projectNgccQueue[i].project);
1147+
}
1148+
this.projectNgccQueue = this.projectNgccQueue.filter(({done}) => !done);
11301149
}
11311150
}
11321151

0 commit comments

Comments
 (0)