Browse Source

Increase LSP diagnostics timeout budget

dhaern 2 days ago
parent
commit
01853aca1d
2 changed files with 20 additions and 12 deletions
  1. 9 9
      src/tools/lsp/client.test.ts
  2. 11 3
      src/tools/lsp/client.ts

+ 9 - 9
src/tools/lsp/client.test.ts

@@ -172,8 +172,8 @@ describe('LSPClient diagnostics', () => {
   });
 
   test('diagnostics falls back to cached publishDiagnostics on timeout', async () => {
-    const originalRequestTimeout = LSP_TIMEOUTS.request;
-    LSP_TIMEOUTS.request = 10;
+    const originalDiagnosticsTimeout = LSP_TIMEOUTS.diagnostics;
+    LSP_TIMEOUTS.diagnostics = 10;
 
     const client = new LSPClient(tempDir, {
       id: 'test',
@@ -209,13 +209,13 @@ describe('LSPClient diagnostics', () => {
       expect(result.items).toHaveLength(1);
       expect(result.items[0]?.message).toBe('cached diagnostic');
     } finally {
-      LSP_TIMEOUTS.request = originalRequestTimeout;
+      LSP_TIMEOUTS.diagnostics = originalDiagnosticsTimeout;
     }
   });
 
   test('diagnostics throws after timeout when no cached diagnostics exist', async () => {
-    const originalRequestTimeout = LSP_TIMEOUTS.request;
-    LSP_TIMEOUTS.request = 10;
+    const originalDiagnosticsTimeout = LSP_TIMEOUTS.diagnostics;
+    LSP_TIMEOUTS.diagnostics = 10;
 
     const client = new LSPClient(tempDir, {
       id: 'test',
@@ -240,13 +240,13 @@ describe('LSPClient diagnostics', () => {
         'Unable to retrieve diagnostics',
       );
     } finally {
-      LSP_TIMEOUTS.request = originalRequestTimeout;
+      LSP_TIMEOUTS.diagnostics = originalDiagnosticsTimeout;
     }
   });
 
   test('diagnostics uses cached publishDiagnostics for push-only servers', async () => {
-    const originalRequestTimeout = LSP_TIMEOUTS.request;
-    LSP_TIMEOUTS.request = 200;
+    const originalDiagnosticsTimeout = LSP_TIMEOUTS.diagnostics;
+    LSP_TIMEOUTS.diagnostics = 200;
 
     const client = new LSPClient(tempDir, {
       id: 'test',
@@ -287,7 +287,7 @@ describe('LSPClient diagnostics', () => {
         expect.anything(),
       );
     } finally {
-      LSP_TIMEOUTS.request = originalRequestTimeout;
+      LSP_TIMEOUTS.diagnostics = originalDiagnosticsTimeout;
     }
   });
 

+ 11 - 3
src/tools/lsp/client.ts

@@ -21,6 +21,7 @@ import type {
 
 const START_TIMEOUT_MS = 5_000;
 const REQUEST_TIMEOUT_MS = 5_000;
+const DIAGNOSTICS_TIMEOUT_MS = 15_000;
 const OPEN_FILE_DELAY_MS = 250;
 const INITIALIZE_DELAY_MS = 100;
 const DIAGNOSTIC_SETTLE_DELAY_MS = 250;
@@ -28,6 +29,7 @@ const DIAGNOSTIC_SETTLE_DELAY_MS = 250;
 export const LSP_TIMEOUTS = {
   start: START_TIMEOUT_MS,
   request: REQUEST_TIMEOUT_MS,
+  diagnostics: DIAGNOSTICS_TIMEOUT_MS,
   openFileDelay: OPEN_FILE_DELAY_MS,
   initializeDelay: INITIALIZE_DELAY_MS,
   diagnosticSettleDelay: DIAGNOSTIC_SETTLE_DELAY_MS,
@@ -587,7 +589,7 @@ export class LSPClient {
 
   private async waitForPublishedDiagnostics(
     uri: string,
-    timeoutMs = LSP_TIMEOUTS.request,
+    timeoutMs = LSP_TIMEOUTS.diagnostics,
   ): Promise<Diagnostic[] | undefined> {
     const cachedDiagnostics = this.diagnosticsStore.get(uri);
     if (cachedDiagnostics) {
@@ -703,6 +705,7 @@ export class LSPClient {
   async diagnostics(filePath: string): Promise<{ items: Diagnostic[] }> {
     const absPath = resolve(filePath);
     const uri = pathToFileURL(absPath).href;
+    const startedAt = Date.now();
     await this.openFile(absPath);
     await new Promise((r) => setTimeout(r, LSP_TIMEOUTS.diagnosticSettleDelay));
 
@@ -725,7 +728,7 @@ export class LSPClient {
                 textDocument: { uri },
                 previousResultId: this.diagnosticResultIds.get(uri),
               }),
-              LSP_TIMEOUTS.request,
+              LSP_TIMEOUTS.diagnostics,
               `LSP diagnostics (${this.server.id})`,
             )
           : undefined;
@@ -761,7 +764,12 @@ export class LSPClient {
       }
     }
 
-    const cachedDiagnostics = await this.waitForPublishedDiagnostics(uri);
+    const elapsed = Date.now() - startedAt;
+    const remainingTimeout = Math.max(LSP_TIMEOUTS.diagnostics - elapsed, 0);
+    const cachedDiagnostics = await this.waitForPublishedDiagnostics(
+      uri,
+      remainingTimeout,
+    );
     if (cachedDiagnostics) {
       return { items: cachedDiagnostics };
     }