fix: clangd hanging fixed (#3611)

Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Filip
2025-11-12 07:21:55 +01:00
committed by GitHub
parent 7c2d4ee79a
commit aa2e2c76c0
4 changed files with 191 additions and 92 deletions

View File

@@ -103,6 +103,7 @@ export namespace LSP {
broken: new Set<string>(),
servers,
clients,
spawning: new Map<string, Promise<LSPClient.Info | undefined>>(),
}
},
async (state) => {
@@ -145,6 +146,49 @@ export namespace LSP {
const s = await state()
const extension = path.parse(file).ext || file
const result: LSPClient.Info[] = []
async function schedule(server: LSPServer.Info, root: string, key: string) {
const handle = await server
.spawn(root)
.then((value) => {
if (!value) s.broken.add(key)
return value
})
.catch((err) => {
s.broken.add(key)
log.error(`Failed to spawn LSP server ${server.id}`, { error: err })
return undefined
})
if (!handle) return undefined
log.info("spawned lsp server", { serverID: server.id })
const client = await LSPClient.create({
serverID: server.id,
server: handle,
root,
}).catch((err) => {
s.broken.add(key)
handle.process.kill()
log.error(`Failed to initialize LSP client ${server.id}`, { error: err })
return undefined
})
if (!client) {
handle.process.kill()
return undefined
}
const existing = s.clients.find((x) => x.root === root && x.serverID === server.id)
if (existing) {
handle.process.kill()
return existing
}
s.clients.push(client)
return client
}
for (const server of Object.values(s.servers)) {
if (server.extensions.length && !server.extensions.includes(extension)) continue
const root = await server.root(file)
@@ -156,39 +200,31 @@ export namespace LSP {
result.push(match)
continue
}
const handle = await server
.spawn(root)
.then((h) => {
if (h === undefined) {
s.broken.add(root + server.id)
}
return h
})
.catch((err) => {
s.broken.add(root + server.id)
log.error(`Failed to spawn LSP server ${server.id}`, { error: err })
return undefined
})
if (!handle) continue
log.info("spawned lsp server", { serverID: server.id })
const client = await LSPClient.create({
serverID: server.id,
server: handle,
root,
}).catch((err) => {
s.broken.add(root + server.id)
handle.process.kill()
log.error(`Failed to initialize LSP client ${server.id}`, {
error: err,
})
return undefined
const inflight = s.spawning.get(root + server.id)
if (inflight) {
const client = await inflight
if (!client) continue
result.push(client)
continue
}
const task = schedule(server, root, root + server.id)
s.spawning.set(root + server.id, task)
task.finally(() => {
if (s.spawning.get(root + server.id) === task) {
s.spawning.delete(root + server.id)
}
})
const client = await task
if (!client) continue
s.clients.push(client)
result.push(client)
Bus.publish(Event.Updated, {})
}
return result
}
@@ -199,6 +235,7 @@ export namespace LSP {
if (!clients.includes(client)) return
const wait = waitForDiagnostics ? client.waitForDiagnostics({ path: input }) : Promise.resolve()
await client.notify.open({ path: input })
return wait
}).catch((err) => {
log.error("failed to touch file", { err, file: input })