refactor: replace string-matching error checks with custom error classes

This commit is contained in:
2026-04-30 08:27:13 -04:00
parent 81ed5c88b8
commit 7abe4efa02
4 changed files with 59 additions and 12 deletions

View File

@@ -7,6 +7,10 @@ import { Type } from "typebox";
import * as path from "node:path";
import { uriToPath } from "./src/client.ts";
import { daemonDiagnostics, daemonRequest } from "./src/daemonClient.ts";
import {
ServerNotFoundError,
UnsupportedExtensionError,
} from "./src/types.ts";
// Format Hover - Turn an LSP hover response into readable text.
function formatHover(result: unknown): string {
@@ -202,6 +206,16 @@ function formatDiagnostics(result: unknown): string {
.join("\n");
}
// Is Expected Error - Returns true if the error is an expected condition
// (unsupported file type or missing server binary) that should be
// suppressed rather than surfaced to the user.
function isExpectedError(error: unknown): boolean {
return (
error instanceof UnsupportedExtensionError ||
error instanceof ServerNotFoundError
);
}
// Run LSP Request - Forwards to the daemon, which owns the long-lived
// LspClient cache and handles didOpen/didChange syncing. The daemon
// injects textDocument.uri from the file path, so we omit it here.
@@ -210,13 +224,27 @@ async function runLsp(
method: string,
params: Record<string, unknown>,
): Promise<unknown> {
return daemonRequest(filePath, method, params);
try {
return await daemonRequest(filePath, method, params);
} catch (error) {
if (isExpectedError(error)) {
return undefined;
}
throw error;
}
}
// Run LSP Diagnostics - Diagnostics arrive as a notification, so the
// daemon has a dedicated op that waits for the next publish.
async function runDiagnostics(filePath: string): Promise<unknown> {
return daemonDiagnostics(filePath, 1500);
try {
return await daemonDiagnostics(filePath, 1500);
} catch (error) {
if (isExpectedError(error)) {
return undefined;
}
throw error;
}
}
// Shared Parameters Schema - All position-based tools accept file + optional
@@ -412,11 +440,12 @@ export default function (pi: ExtensionAPI) {
} catch (error) {
// Silently fail - don't interrupt the flow
// Only log if there's an actual error we care about
if (error && typeof error === "object" && "message" in error) {
const msg = (error as { message: string }).message;
if (!msg.includes("not found on PATH")) {
console.error("LSP auto-check failed:", msg);
}
if (!isExpectedError(error)) {
const msg =
error && typeof error === "object" && "message" in error
? (error as { message: string }).message
: String(error);
console.error("LSP auto-check failed:", msg);
}
}
});