Skip to content

Commit c7356d4

Browse files
committed
Work around race condition
1 parent effe793 commit c7356d4

File tree

1 file changed

+18
-15
lines changed
  • packages/tailwindcss-language-server/src

1 file changed

+18
-15
lines changed

packages/tailwindcss-language-server/src/tw.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ export class TW {
910910
}
911911

912912
private lastTriggerCharacters: Set<string> | undefined
913-
private completionRegistration: Disposable | undefined
913+
private completionRegistration: Promise<Disposable> | undefined
914914
private async updateTriggerCharacters() {
915915
// If the client does not suppory dynamic registration of completions then
916916
// we cannot update the set of trigger characters
@@ -941,24 +941,27 @@ export class TW {
941941

942942
this.lastTriggerCharacters = chars
943943

944-
// TODO: This might technically be a race condition if:
945-
// - There are multiple workspace roots
946-
// - There are multiple projects with different separators
947-
//
948-
// Everything up to this point is synchronous including the bailout code
949-
// so it *should* be fine
944+
let current = this.completionRegistration
945+
this.completionRegistration = this.connection.client.register(CompletionRequest.type, {
946+
documentSelector: null,
947+
resolveProvider: true,
948+
triggerCharacters: Array.from(chars),
949+
})
950+
951+
// NOTE:
952+
// This weird setup works around a race condition where multiple projects
953+
// with different separators update their capabilities at the same time. It
954+
// is extremely unlikely but it could cause `CompletionRequest` to be
955+
// registered more than once with the LSP client.
950956
//
951-
// The proper fix here is to:
957+
// We store the promises meaning everything up to this point is synchronous
958+
// so it should be fine but really the proper fix here is to:
952959
// - Refactor workspace folder initialization so discovery, initialization,
953960
// file events, config watchers, etc… are all shared.
954961
// - Remove the need for the "restart" concept in the server for as much as
955962
// possible. Each project should be capable of reloading its modules.
956-
this.completionRegistration?.dispose()
957-
this.completionRegistration = await this.connection.client.register(CompletionRequest.type, {
958-
documentSelector: null,
959-
resolveProvider: true,
960-
triggerCharacters: Array.from(chars),
961-
})
963+
await current?.then((r) => r.dispose())
964+
await this.completionRegistration
962965
}
963966

964967
private getProject(document: TextDocumentIdentifier): ProjectService {
@@ -1149,7 +1152,7 @@ export class TW {
11491152
this.commonRegistrations = undefined
11501153

11511154
this.lastTriggerCharacters.clear()
1152-
this.completionRegistration?.dispose()
1155+
this.completionRegistration?.then((r) => r.dispose())
11531156
this.completionRegistration = undefined
11541157

11551158
this.disposables.forEach((d) => d.dispose())

0 commit comments

Comments
 (0)