Skip to content

Commit b86346a

Browse files
committed
fix(lsp): add Push model support and fix JSON LSP diagnostics
- Add diagnosticsStore to capture Push model notifications - Handle textDocument/publishDiagnostics notifications in processBuffer - Fix workspace/configuration response for JSON LSP validation - Add missing language mappings (json, html, css, sh, fish, md, tf) - diagnostics() now tries Pull first, falls back to Push store
1 parent 4debb57 commit b86346a

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

src/tools/lsp/client.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { readFileSync } from "fs"
33
import { extname, resolve } from "path"
44
import type { ResolvedServer } from "./config"
55
import { getLanguageId } from "./config"
6+
import type { Diagnostic } from "./types"
67

78
interface ManagedClient {
89
client: LSPClient
@@ -155,6 +156,7 @@ export class LSPClient {
155156
private openedFiles = new Set<string>()
156157
private stderrBuffer: string[] = []
157158
private processExited = false
159+
private diagnosticsStore = new Map<string, Diagnostic[]>()
158160

159161
constructor(
160162
private root: string,
@@ -290,7 +292,11 @@ export class LSPClient {
290292
try {
291293
const msg = JSON.parse(content)
292294

293-
if ("id" in msg && "method" in msg) {
295+
if ("method" in msg && !("id" in msg)) {
296+
if (msg.method === "textDocument/publishDiagnostics" && msg.params?.uri) {
297+
this.diagnosticsStore.set(msg.params.uri, msg.params.diagnostics ?? [])
298+
}
299+
} else if ("id" in msg && "method" in msg) {
294300
this.handleServerRequest(msg.id, msg.method, msg.params)
295301
} else if ("id" in msg && this.pending.has(msg.id)) {
296302
const handler = this.pending.get(msg.id)!
@@ -347,9 +353,14 @@ export class LSPClient {
347353
this.proc.stdin.write(`Content-Length: ${Buffer.byteLength(msg)}\r\n\r\n${msg}`)
348354
}
349355

350-
private handleServerRequest(id: number | string, method: string, _params?: unknown): void {
356+
private handleServerRequest(id: number | string, method: string, params?: unknown): void {
351357
if (method === "workspace/configuration") {
352-
this.respond(id, [{}])
358+
const items = (params as { items?: Array<{ section?: string }> })?.items ?? []
359+
const result = items.map((item) => {
360+
if (item.section === "json") return { validate: { enable: true } }
361+
return {}
362+
})
363+
this.respond(id, result)
353364
} else if (method === "client/registerCapability") {
354365
this.respond(id, null)
355366
} else if (method === "window/workDoneProgress/create") {
@@ -412,7 +423,9 @@ export class LSPClient {
412423
...this.server.initialization,
413424
})
414425
this.notify("initialized")
415-
this.notify("workspace/didChangeConfiguration", { settings: {} })
426+
this.notify("workspace/didChangeConfiguration", {
427+
settings: { json: { validate: { enable: true } } },
428+
})
416429
await new Promise((r) => setTimeout(r, 300))
417430
}
418431

@@ -477,13 +490,23 @@ export class LSPClient {
477490
return this.send("workspace/symbol", { query })
478491
}
479492

480-
async diagnostics(filePath: string): Promise<unknown> {
493+
async diagnostics(filePath: string): Promise<{ items: Diagnostic[] }> {
481494
const absPath = resolve(filePath)
495+
const uri = `file://${absPath}`
482496
await this.openFile(absPath)
483497
await new Promise((r) => setTimeout(r, 500))
484-
return this.send("textDocument/diagnostic", {
485-
textDocument: { uri: `file://${absPath}` },
486-
})
498+
499+
try {
500+
const result = await this.send("textDocument/diagnostic", {
501+
textDocument: { uri },
502+
})
503+
if (result && typeof result === "object" && "items" in result) {
504+
return result as { items: Diagnostic[] }
505+
}
506+
} catch {
507+
}
508+
509+
return { items: this.diagnosticsStore.get(uri) ?? [] }
487510
}
488511

489512
async prepareRename(filePath: string, line: number, character: number): Promise<unknown> {
@@ -545,5 +568,6 @@ export class LSPClient {
545568
this.proc?.kill()
546569
this.proc = null
547570
this.processExited = true
571+
this.diagnosticsStore.clear()
548572
}
549573
}

src/tools/lsp/constants.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,18 @@ export const EXT_TO_LANG: Record<string, string> = {
175175
".astro": "astro",
176176
".yaml": "yaml",
177177
".yml": "yaml",
178+
".json": "json",
179+
".jsonc": "jsonc",
180+
".html": "html",
181+
".htm": "html",
182+
".css": "css",
183+
".scss": "scss",
184+
".less": "less",
185+
".sh": "shellscript",
186+
".bash": "shellscript",
187+
".zsh": "shellscript",
188+
".fish": "fish",
189+
".md": "markdown",
190+
".tf": "terraform",
191+
".tfvars": "terraform",
178192
}

0 commit comments

Comments
 (0)