fix(lsp): include file paths in directory diagnostics output
This commit is contained in:
@@ -1,12 +1,56 @@
|
||||
import { describe, expect, it } from "bun:test"
|
||||
import { beforeEach, describe, expect, it, mock } from "bun:test"
|
||||
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "fs"
|
||||
import { join } from "path"
|
||||
import os from "os"
|
||||
|
||||
import { isDirectoryPath } from "./lsp-client-wrapper"
|
||||
import { aggregateDiagnosticsForDirectory } from "./directory-diagnostics"
|
||||
import type { Diagnostic } from "./types"
|
||||
|
||||
const diagnosticsMock = mock(async (_filePath: string) => ({ items: [] as Diagnostic[] }))
|
||||
const getClientMock = mock(async () => ({ diagnostics: diagnosticsMock }))
|
||||
const releaseClientMock = mock(() => {})
|
||||
|
||||
mock.module("./config", () => ({
|
||||
findServerForExtension: (extension: string) => ({
|
||||
status: "found" as const,
|
||||
server: {
|
||||
id: "test-server",
|
||||
command: ["test-server"],
|
||||
extensions: [extension],
|
||||
priority: 1,
|
||||
},
|
||||
}),
|
||||
getLanguageId: () => "typescript",
|
||||
}))
|
||||
|
||||
mock.module("./lsp-server", () => ({
|
||||
lspManager: {
|
||||
getClient: getClientMock,
|
||||
releaseClient: releaseClientMock,
|
||||
},
|
||||
}))
|
||||
|
||||
const { isDirectoryPath } = await import("./lsp-client-wrapper")
|
||||
const { aggregateDiagnosticsForDirectory } = await import("./directory-diagnostics")
|
||||
|
||||
function createDiagnostic(message: string): Diagnostic {
|
||||
return {
|
||||
message,
|
||||
severity: 1,
|
||||
range: {
|
||||
start: { line: 0, character: 0 },
|
||||
end: { line: 0, character: 1 },
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe("directory diagnostics", () => {
|
||||
beforeEach(() => {
|
||||
diagnosticsMock.mockReset()
|
||||
diagnosticsMock.mockImplementation(async (_filePath: string) => ({ items: [] }))
|
||||
getClientMock.mockClear()
|
||||
releaseClientMock.mockClear()
|
||||
})
|
||||
|
||||
describe("isDirectoryPath", () => {
|
||||
it("returns true for existing directory", () => {
|
||||
const tmp = mkdtempSync(join(os.tmpdir(), "omo-isdir-"))
|
||||
@@ -52,5 +96,27 @@ describe("directory diagnostics", () => {
|
||||
"Directory does not exist"
|
||||
)
|
||||
})
|
||||
|
||||
it("#given diagnostics from multiple files #when aggregating directory diagnostics #then each entry includes the source file path", async () => {
|
||||
const tmp = mkdtempSync(join(os.tmpdir(), "omo-aggr-files-"))
|
||||
try {
|
||||
const firstFile = join(tmp, "first.ts")
|
||||
const secondFile = join(tmp, "second.ts")
|
||||
|
||||
writeFileSync(firstFile, "export const first = true\n")
|
||||
writeFileSync(secondFile, "export const second = true\n")
|
||||
|
||||
diagnosticsMock.mockImplementation(async (filePath: string) => ({
|
||||
items: [createDiagnostic(`problem in ${filePath}`)],
|
||||
}))
|
||||
|
||||
const result = await aggregateDiagnosticsForDirectory(tmp, ".ts")
|
||||
|
||||
expect(result).toContain(`${firstFile}: error at 1:0: problem in ${firstFile}`)
|
||||
expect(result).toContain(`${secondFile}: error at 1:0: problem in ${secondFile}`)
|
||||
} finally {
|
||||
rmSync(tmp, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -11,6 +11,11 @@ import type { Diagnostic } from "./types"
|
||||
|
||||
const SKIP_DIRECTORIES = new Set(["node_modules", ".git", "dist", "build", ".next", "out"])
|
||||
|
||||
type FileDiagnostic = {
|
||||
filePath: string
|
||||
diagnostic: Diagnostic
|
||||
}
|
||||
|
||||
function collectFilesWithExtension(dir: string, extension: string, maxFiles: number): string[] {
|
||||
const files: string[] = []
|
||||
|
||||
@@ -95,7 +100,7 @@ export async function aggregateDiagnosticsForDirectory(
|
||||
|
||||
const root = findWorkspaceRoot(absDir)
|
||||
|
||||
const allDiagnostics: Diagnostic[] = []
|
||||
const allDiagnostics: FileDiagnostic[] = []
|
||||
const fileErrors: { file: string; error: string }[] = []
|
||||
|
||||
let client: LSPClient
|
||||
@@ -106,7 +111,12 @@ export async function aggregateDiagnosticsForDirectory(
|
||||
try {
|
||||
const result = await client.diagnostics(file)
|
||||
const filtered = filterDiagnosticsBySeverity(result.items, severity)
|
||||
allDiagnostics.push(...filtered)
|
||||
allDiagnostics.push(
|
||||
...filtered.map((diagnostic) => ({
|
||||
filePath: file,
|
||||
diagnostic,
|
||||
}))
|
||||
)
|
||||
} catch (e) {
|
||||
fileErrors.push({
|
||||
file,
|
||||
@@ -138,8 +148,8 @@ export async function aggregateDiagnosticsForDirectory(
|
||||
|
||||
if (displayDiagnostics.length > 0) {
|
||||
lines.push("")
|
||||
for (const diag of displayDiagnostics) {
|
||||
lines.push(formatDiagnostic(diag))
|
||||
for (const { filePath, diagnostic } of displayDiagnostics) {
|
||||
lines.push(`${filePath}: ${formatDiagnostic(diagnostic)}`)
|
||||
}
|
||||
if (wasDiagCapped) {
|
||||
lines.push(
|
||||
|
||||
Reference in New Issue
Block a user