@@ -16,7 +16,8 @@ import { Filesystem } from "../util"
1616const DIAGNOSTICS_DEBOUNCE_MS = 150
1717const DIAGNOSTICS_POLL_MS = 500
1818const DIAGNOSTICS_REQUEST_TIMEOUT_MS = 2_000
19- const DIAGNOSTICS_WAIT_TIMEOUT_MS = 10_000
19+ const DIAGNOSTICS_WAIT_TIMEOUT_MS = 3_000
20+ const DIAGNOSTICS_PULL_WAIT_TIMEOUT_MS = 10_000
2021const DIAGNOSTICS_SETTLE_MS = 1_500
2122
2223const log = Log . create ( { service : "lsp.client" } )
@@ -62,6 +63,7 @@ type ServerCapabilities = {
6263 | {
6364 change ?: number
6465 }
66+ diagnosticProvider ?: unknown
6567 [ key : string ] : unknown
6668}
6769
@@ -210,6 +212,7 @@ export async function create(input: { serverID: string; server: LSPServer.Handle
210212 )
211213 } )
212214 const syncKind = getSyncKind ( initialized . capabilities )
215+ const hasStaticPullDiagnostics = Boolean ( initialized . capabilities ?. diagnosticProvider )
213216
214217 await connection . sendNotification ( "initialized" , { } )
215218
@@ -257,10 +260,14 @@ export async function create(input: { serverID: string; server: LSPServer.Handle
257260 }
258261
259262 async function requestDiagnostics ( filePath : string ) {
263+ const registrations = [ ...diagnosticRegistrations . values ( ) ] . filter (
264+ ( registration ) => registration . registerOptions ?. workspaceDiagnostics !== true ,
265+ )
266+ if ( ! hasStaticPullDiagnostics && registrations . length === 0 ) return false
267+
260268 const results = [ await requestDiagnosticReport ( filePath ) ]
261269 const identifiers = new Set (
262- [ ...diagnosticRegistrations . values ( ) ]
263- . filter ( ( registration ) => registration . registerOptions ?. workspaceDiagnostics !== true )
270+ registrations
264271 . map ( ( registration ) => registration . registerOptions ?. identifier )
265272 . filter ( ( identifier ) : identifier is string => Boolean ( identifier ) ) ,
266273 )
@@ -374,40 +381,47 @@ export async function create(input: { serverID: string; server: LSPServer.Handle
374381 path . isAbsolute ( request . path ) ? request . path : path . resolve ( input . directory , request . path ) ,
375382 )
376383 log . info ( "waiting for diagnostics" , { path : normalizedPath } )
377- let unsub : ( ) => void
384+ let unsub : ( ( ) => void ) | undefined
378385 let debounceTimer : ReturnType < typeof setTimeout > | undefined
379- let pushed = false
380- let firstHandledAt : number | undefined
386+ let done = false
387+ let resolvePushed : ( ( ) => void ) | undefined
388+ const timeout = hasStaticPullDiagnostics || diagnosticRegistrations . size > 0
389+ ? DIAGNOSTICS_PULL_WAIT_TIMEOUT_MS
390+ : DIAGNOSTICS_WAIT_TIMEOUT_MS
381391 return await withTimeout (
382- ( async ( ) => {
383- unsub = Bus . subscribe ( Event . Diagnostics , ( event ) => {
384- if ( event . properties . path !== normalizedPath || event . properties . serverID !== result . serverID ) return
385- if ( debounceTimer ) clearTimeout ( debounceTimer )
386- debounceTimer = setTimeout ( ( ) => {
387- pushed = true
388- } , DIAGNOSTICS_DEBOUNCE_MS )
389- } )
390- await new Promise ( ( resolve ) => setTimeout ( resolve , DIAGNOSTICS_DEBOUNCE_MS ) )
391- while ( true ) {
392- if ( pushed ) {
393- log . info ( "got diagnostics" , { path : normalizedPath } )
394- return
395- }
396- const handled = await requestDiagnostics ( normalizedPath )
397- if ( handled ) {
398- firstHandledAt = firstHandledAt ?? Date . now ( )
399- if ( Date . now ( ) - firstHandledAt >= DIAGNOSTICS_SETTLE_MS ) {
392+ Promise . race ( [
393+ new Promise < void > ( ( resolve ) => {
394+ resolvePushed = resolve
395+ unsub = Bus . subscribe ( Event . Diagnostics , ( event ) => {
396+ if ( event . properties . path !== normalizedPath || event . properties . serverID !== result . serverID ) return
397+ if ( debounceTimer ) clearTimeout ( debounceTimer )
398+ debounceTimer = setTimeout ( ( ) => {
400399 log . info ( "got diagnostics" , { path : normalizedPath } )
401- return
400+ resolve ( )
401+ } , DIAGNOSTICS_DEBOUNCE_MS )
402+ } )
403+ } ) ,
404+ ( async ( ) => {
405+ let firstHandledAt : number | undefined
406+ while ( ! done ) {
407+ const handled = await requestDiagnostics ( normalizedPath )
408+ if ( handled ) {
409+ firstHandledAt = firstHandledAt ?? Date . now ( )
410+ if ( Date . now ( ) - firstHandledAt >= DIAGNOSTICS_SETTLE_MS ) {
411+ log . info ( "got diagnostics" , { path : normalizedPath } )
412+ return
413+ }
402414 }
415+ await new Promise ( ( resolve ) => setTimeout ( resolve , DIAGNOSTICS_POLL_MS ) )
403416 }
404- await new Promise ( ( resolve ) => setTimeout ( resolve , DIAGNOSTICS_POLL_MS ) )
405- }
406- } ) ( ) ,
407- DIAGNOSTICS_WAIT_TIMEOUT_MS ,
417+ } ) ( ) ,
418+ ] ) ,
419+ timeout ,
408420 )
409421 . catch ( ( ) => { } )
410422 . finally ( ( ) => {
423+ done = true
424+ resolvePushed ?.( )
411425 if ( debounceTimer ) clearTimeout ( debounceTimer )
412426 unsub ?.( )
413427 } )
0 commit comments