diff --git a/packages/tailwindcss-language-server/src/tw.ts b/packages/tailwindcss-language-server/src/tw.ts index f2376154..882d1be2 100644 --- a/packages/tailwindcss-language-server/src/tw.ts +++ b/packages/tailwindcss-language-server/src/tw.ts @@ -929,7 +929,13 @@ export class TW { } // If the trigger characters haven't changed then we don't need to do anything - if (equal(Array.from(chars), Array.from(this.lastTriggerCharacters ?? []))) return + if ( + this.completionRegistration && + equal(Array.from(chars), Array.from(this.lastTriggerCharacters ?? [])) + ) { + return + } + this.lastTriggerCharacters = chars this.completionRegistration?.dispose() @@ -1127,6 +1133,7 @@ export class TW { this.commonRegistrations?.dispose() this.commonRegistrations = undefined + this.lastTriggerCharacters.clear() this.completionRegistration?.dispose() this.completionRegistration = undefined diff --git a/packages/tailwindcss-language-server/tests/env/capabilities.test.ts b/packages/tailwindcss-language-server/tests/env/capabilities.test.ts index 22eac608..6799c0ba 100644 --- a/packages/tailwindcss-language-server/tests/env/capabilities.test.ts +++ b/packages/tailwindcss-language-server/tests/env/capabilities.test.ts @@ -182,3 +182,65 @@ defineTest({ expect(idsBefore).toEqual(idsAfter) }, }) + +defineTest({ + name: 'Trigger characters are registered after a server restart', + fs: { + 'app.css': '@import "tailwindcss"', + }, + prepare: async ({ root }) => ({ client: await createClient({ root }) }), + handle: async ({ root, client }) => { + // Initially don't have any registered capabilities because dynamic + // registration is delayed until after project initialization + expect(client.serverCapabilities).toEqual([]) + + // We open a document so a project gets initialized + await client.open({ + lang: 'html', + text: '
', + }) + + // And now capabilities are registered + expect(client.serverCapabilities).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + method: 'textDocument/hover', + }), + + expect.objectContaining({ + method: 'textDocument/completion', + registerOptions: { + documentSelector: null, + resolveProvider: true, + triggerCharacters: ['"', "'", '`', ' ', '.', '(', '[', ']', '!', '/', '-', ':'], + }, + }), + ]), + ) + + let didRestart = new Promise((resolve) => { + client.conn.onNotification('@/tailwindCSS/serverRestarted', resolve) + }) + + // Force a server restart by telling the server tsconfig.json changed + client.notifyChangedFiles({ + changed: [`${root}/tsconfig.json`], + }) + + // Wait for the server initialization to finish + await didRestart + + expect(client.serverCapabilities).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + method: 'textDocument/completion', + registerOptions: { + documentSelector: null, + resolveProvider: true, + triggerCharacters: ['"', "'", '`', ' ', '.', '(', '[', ']', '!', '/', '-', ':'], + }, + }), + ]), + ) + }, +})