From 957963dc7efbf15813dc155f6e93c74ad266cb8f Mon Sep 17 00:00:00 2001 From: Jason Dent Date: Sun, 22 Dec 2024 09:51:29 +0100 Subject: [PATCH] fix: Send back diags using language server --- packages/_server/.gitignore | 11 +++--- packages/_server/package.json | 4 +-- packages/_server/rollup.config.mjs | 2 +- packages/_server/src/server.mts | 19 +++++----- packages/_server/src/utils/catchPromise.mts | 35 +++++++++++------- packages/_server/tsconfig.api.json | 2 +- packages/_server/tsconfig.test.json | 1 + packages/client/src/client/client.mts | 40 +++++++++++---------- 8 files changed, 65 insertions(+), 49 deletions(-) diff --git a/packages/_server/.gitignore b/packages/_server/.gitignore index a229a01f53..c012f6e9be 100644 --- a/packages/_server/.gitignore +++ b/packages/_server/.gitignore @@ -1,5 +1,6 @@ -out -node_modules -!.vscode -temp -dist +out +node_modules +!.vscode +temp +dist +lib diff --git a/packages/_server/package.json b/packages/_server/package.json index 02dfe043b7..db5f7cbc3e 100644 --- a/packages/_server/package.json +++ b/packages/_server/package.json @@ -26,7 +26,7 @@ "require": "./dist/api.cjs" }, "./lib": { - "import": "./dist/lib/index.mjs" + "import": "./lib/lib/index.mjs" } }, "devDependencies": { @@ -72,7 +72,7 @@ "#build:ts-json-schema-generator": "esbuild --bundle ../../../../code/clones/ts-json-schema-generator/dist/ts-json-schema-generator.js --outfile=scripts/ts-json-schema-generator.cjs --platform=node --external:typescript", "clean-build-production": "npm run clean && npm run build:production", "clean-build": "npm run clean && npm run build", - "clean": "shx rm -rf dist temp out coverage", + "clean": "shx rm -rf dist temp out coverage lib", "test-watch": "vitest", "test": "vitest run", "watch": "concurrently npm:watch:esbuild npm:watch:api npm:watch:tsc", diff --git a/packages/_server/rollup.config.mjs b/packages/_server/rollup.config.mjs index 5a8737e867..05884de878 100644 --- a/packages/_server/rollup.config.mjs +++ b/packages/_server/rollup.config.mjs @@ -2,7 +2,7 @@ import dts from 'rollup-plugin-dts'; const config = [ { - input: './dist/api.d.ts', + input: './lib/api.d.ts', output: [{ file: './dist/api.d.cts', format: 'es' }], plugins: [dts()], }, diff --git a/packages/_server/src/server.mts b/packages/_server/src/server.mts index fcde12327d..172f1448c8 100644 --- a/packages/_server/src/server.mts +++ b/packages/_server/src/server.mts @@ -83,6 +83,14 @@ async function calcDefaultSettings(): Promise { }; } +// This is to filter out the "Off" severity that is used to hide issues from the VS Code Problems panel. +const knownDiagnosticSeverityLevels = new Set([ + DiagnosticSeverity.Error, + DiagnosticSeverity.Warning, + DiagnosticSeverity.Information, + DiagnosticSeverity.Hint, +]); + export function run(): void { // debounce buffer const disposables = createDisposableList(); @@ -488,14 +496,6 @@ export function run(): void { const diags: Required = { uri, version, diagnostics }; - // This is to filter out the "Off" severity that is used to hide issues from the VS Code Problems panel. - const knownDiagnosticSeverityLevels = new Set([ - DiagnosticSeverity.Error, - DiagnosticSeverity.Warning, - DiagnosticSeverity.Information, - DiagnosticSeverity.Hint, - ]); - function mapDiagnostic(diag: Diagnostic): Diagnostic { return { ...diag, @@ -504,7 +504,8 @@ export function run(): void { } const diagsForClient = { ...diags, diagnostics: diags.diagnostics.map(mapDiagnostic) }; - catchPromise(clientServerApi.clientNotification.onDiagnostics(diagsForClient)); + catchPromise(connection.sendDiagnostics(diagsForClient)); + // catchPromise(clientServerApi.clientNotification.onDiagnostics(diagsForClient)); } async function shouldValidateDocument( diff --git a/packages/_server/src/utils/catchPromise.mts b/packages/_server/src/utils/catchPromise.mts index 2aa75c4195..4dd75ba27f 100644 --- a/packages/_server/src/utils/catchPromise.mts +++ b/packages/_server/src/utils/catchPromise.mts @@ -1,16 +1,14 @@ /* eslint-disable @typescript-eslint/unified-signatures */ -type ErrorHandler = (e: unknown) => T; +type ErrorHandler = (e: unknown) => void; function defaultHandler(e: unknown) { console.error(e); - return undefined; } -function contextHandler(context: string | undefined): (e: unknown) => undefined { +function contextHandler(context: string | undefined): (e: unknown) => void { if (!context) return defaultHandler; return (e) => { - console.error('%s: %s', context, e); - return undefined; + console.error(`${context}: ${e}`); }; } @@ -19,20 +17,33 @@ function contextHandler(context: string | undefined): (e: unknown) => undefined * @param p - the promise to catch * @param handler - a handler to handle the rejection. */ -export function catchPromise(p: Promise, handler: ErrorHandler): Promise; +export function catchPromise(p: Promise, handler: ErrorHandler): Promise; /** * Used for catching promises that are not returned. A fire and forget situation. * If the promise is rejected, it is resolved with `undefined`. * @param p - the promise to catch */ -export function catchPromise(p: Promise): Promise; -export function catchPromise(p: Promise, context: string): Promise; -export function catchPromise(p: Promise, handler?: ErrorHandler): Promise; -export async function catchPromise(p: Promise, handlerOrContext?: ErrorHandler | string): Promise { +export function catchPromise(p: Promise): Promise; +/** + * Used for catching promises that are not returned. A fire and forget situation. + * If the promise is rejected, it is resolved with `undefined`. + * @param p - the promise to catch + * @param context - A context string to help identify where the error came from. + */ +export function catchPromise(p: Promise, context: string): Promise; +/** + * Used for catching promises that are not returned. A fire and forget situation. + * If the promise is rejected, it is resolved with `undefined`. + * @param p - the promise to catch + * @param handler - a handler to handle the rejection. + */ +export function catchPromise(p: Promise, handler: ErrorHandler): Promise; +export function catchPromise(p: Promise, handlerOrContext?: ErrorHandler | string): Promise; +export async function catchPromise(p: Promise, handlerOrContext?: ErrorHandler | string): Promise { const handler = typeof handlerOrContext === 'function' ? handlerOrContext : contextHandler(handlerOrContext); try { - return await p; + await p; } catch (e) { - return handler(e); + handler(e); } } diff --git a/packages/_server/tsconfig.api.json b/packages/_server/tsconfig.api.json index 89dfd6a484..96743fa933 100644 --- a/packages/_server/tsconfig.api.json +++ b/packages/_server/tsconfig.api.json @@ -1,7 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "outDir": "./dist", + "outDir": "./lib", "rootDir": "./src", "skipLibCheck": true, "types": ["node"] diff --git a/packages/_server/tsconfig.test.json b/packages/_server/tsconfig.test.json index a48c780664..55ea2c1514 100644 --- a/packages/_server/tsconfig.test.json +++ b/packages/_server/tsconfig.test.json @@ -1,6 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { + "noEmit": true, "outDir": "./temp/dist", "types": ["node"] } diff --git a/packages/client/src/client/client.mts b/packages/client/src/client/client.mts index acec87cb14..a3c9006171 100644 --- a/packages/client/src/client/client.mts +++ b/packages/client/src/client/client.mts @@ -10,9 +10,9 @@ import type { WorkspaceConfigForDocument, } from 'code-spell-checker-server/api'; import { extractEnabledSchemeList, extractKnownFileTypeIds } from 'code-spell-checker-server/lib'; -import { createDisposableList, type DisposableHybrid } from 'utils-disposables'; +import { createDisposableList, type DisposableHybrid, makeDisposable } from 'utils-disposables'; import type { CodeAction, Diagnostic, DiagnosticCollection, Disposable, ExtensionContext, Range, TextDocument } from 'vscode'; -import { languages as vsCodeSupportedLanguages, Uri, workspace } from 'vscode'; +import { EventEmitter, languages as vsCodeSupportedLanguages, Uri, workspace } from 'vscode'; import { diagnosticSource } from '../constants.js'; import { isLcCodeAction, mapDiagnosticToLc, mapLcCodeAction, mapRangeToLc } from '../languageServer/clientHelpers.js'; @@ -48,7 +48,7 @@ export { GetConfigurationForDocumentResult } from './server/index.mjs'; // The debug options for the server const debugExecArgv = ['--nolazy', '--inspect=60048']; -const diagnosticCollectionName = diagnosticSource; +const diagnosticCollectionName = diagnosticSource + 'Server'; export type ServerResponseIsSpellCheckEnabled = Partial; @@ -75,6 +75,7 @@ export class CSpellClient implements Disposable { private broadcasterOnDocumentConfigChange = createBroadcaster(); private broadcasterOnBlockFile = createBroadcaster(); private ready = new Resolvable(); + private diagEmitter = new EventEmitter(); /** * @param: {string} module -- absolute path to the server module. @@ -98,6 +99,11 @@ export class CSpellClient implements Disposable { this.languageIds = new Set([...languageIds, ...LanguageIds.languageIds, ...extractKnownFileTypeIds(settings)]); + const handleDiagnostics = (uri: Uri, diagnostics: Diagnostic[]) => { + logger.log(`${new Date().toISOString()} Client handleDiagnostics: ${uri.toString()}`); + this.diagEmitter.fire({ uri, diagnostics }); + }; + const uniqueLangIds = [...this.languageIds]; const documentSelector = [...this.allowedSchemas].flatMap((scheme) => uniqueLangIds.map((language) => ({ language, scheme }))); // Options to control the language client @@ -108,12 +114,7 @@ export class CSpellClient implements Disposable { // Synchronize the setting section 'spellChecker' to the server configurationSection: [sectionCSpell, 'search'], }, - middleware: { - handleDiagnostics(uri, diagnostics, next) { - logger.log(`${new Date().toISOString()} Client handleDiagnostics: ${uri.toString()}`); - next(uri, diagnostics); - }, - }, + middleware: { handleDiagnostics }, }; const execArgv = this.calcServerArgs(); @@ -340,16 +341,17 @@ export class CSpellClient implements Disposable { } public onDiagnostics(fn: (diags: DiagnosticsFromServer) => void): DisposableHybrid { - return this.serverApi.onDiagnostics((pub) => { - const cvt = this.client.protocol2CodeConverter; - const uri = cvt.asUri(pub.uri); - const diags: DiagnosticsFromServer = { - uri, - version: pub.version, - diagnostics: pub.diagnostics.map((diag) => cvt.asDiagnostic(diag)), - }; - return fn(diags); - }); + return makeDisposable(this.diagEmitter.event(fn)); + // return this.serverApi.onDiagnostics((pub) => { + // const cvt = this.client.protocol2CodeConverter; + // const uri = cvt.asUri(pub.uri); + // const diags: DiagnosticsFromServer = { + // uri, + // version: pub.version, + // diagnostics: pub.diagnostics.map((diag) => cvt.asDiagnostic(diag)), + // }; + // return fn(diags); + // }); } private async initWhenReady() {