Skip to content

Commit

Permalink
Fix race for the LSP server. (#200)
Browse files Browse the repository at this point in the history
Sometimes we would see multiple LSP servers because of a race condition.
Now we store the promise instead of the actual LSP client. This way we
don't accidentally start two clients.
  • Loading branch information
floitsch authored Jun 23, 2022
1 parent bd0d842 commit 498b1d2
Showing 1 changed file with 23 additions and 10 deletions.
33 changes: 23 additions & 10 deletions vscode/src/lspClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { DocumentSelector, LanguageClient, LanguageClientOptions, ServerOptions

// Untitled documents, or documents outside all workspaces go to a default client.
let nonFileClient: LanguageClient;
const clients: Map<string, LanguageClient> = new Map();
const clients: Map<string, Promise<LanguageClient>> = new Map();
const clientCounts: Map<string, number> = new Map();
let _workspaceFolders: Set<string>|undefined;

Expand Down Expand Up @@ -191,13 +191,26 @@ export function activateLsp(context: ExtensionContext, lspCommand: Array<string>
}
const workingDir = config.workingDir!;
if (!clients.has(workingDir)) {
const client = await startToitLsp(context, lspCommand, outputChannel, config);
clients.set(workingDir, client);
const clientPromise = startToitLsp(context, lspCommand, outputChannel, config);
clients.set(workingDir, clientPromise);
clientCounts.set(workingDir, 1);
} else {
const oldCount = clientCounts.get(workingDir)!;
clientCounts.set(workingDir, oldCount + 1);
}
const clientPromise = clients.get(workingDir);
try {
await clientPromise;
} catch (e) {
// Delete the current client promise from the map.
// It's not completely clear if the check for the clientPromise is necessary, but
// it can't hurt.
if (clients.has(workingDir) && clientCounts.get(workingDir) === clientPromise) {
clients.delete(workingDir);
clientCounts.delete(workingDir);
}
throw e;
}
}

async function didOpenTextDocument(document: TextDocument): Promise<void> {
Expand All @@ -224,10 +237,10 @@ export function activateLsp(context: ExtensionContext, lspCommand: Array<string>
if (clients.has(workingDir)) {
const oldCount = clientCounts.get(workingDir)!;
if (oldCount === 1) {
const client = clients.get(workingDir)!;
const clientPromise = clients.get(workingDir)!;
clients.delete(workingDir);
clientCounts.delete(workingDir);
client.stop();
clientPromise.then((client) => client.stop());
} else {
clientCounts.set(workingDir, oldCount - 1);
}
Expand All @@ -239,10 +252,10 @@ export function activateLsp(context: ExtensionContext, lspCommand: Array<string>
Workspace.onDidChangeWorkspaceFolders(event => {
for (const folder of event.removed) {
const uriString = folder.uri.toString();
const client = clients.get(uriString);
if (client) {
const clientPromise = clients.get(uriString);
if (clientPromise) {
clients.delete(uriString);
client.stop();
clientPromise.then((client) => client.stop());
}
}
});
Expand All @@ -254,8 +267,8 @@ export function deactivateLsp(): Thenable<void> {
if (nonFileClient) {
promises.push(nonFileClient.stop());
}
for (const client of clients.values()) {
promises.push(client.stop());
for (const clientPromise of clients.values()) {
promises.push(clientPromise.then((client) => client.stop()));
}
return Promise.all(promises).then(() => undefined);
}

0 comments on commit 498b1d2

Please sign in to comment.