Fix diagnostic propagation
This commit is contained in:
parent
0e70335791
commit
db5f33e961
|
|
@ -8,6 +8,7 @@ import {
|
||||||
ChangeSet,
|
ChangeSet,
|
||||||
} from "@codemirror/state";
|
} from "@codemirror/state";
|
||||||
import { history } from "@codemirror/commands";
|
import { history } from "@codemirror/commands";
|
||||||
|
import { Diagnostic, setDiagnostics } from "@codemirror/lint";
|
||||||
import { Editor } from "./editor";
|
import { Editor } from "./editor";
|
||||||
import van, { State } from "vanjs-core";
|
import van, { State } from "vanjs-core";
|
||||||
import { WorkspaceFile } from "@codemirror/lsp-client";
|
import { WorkspaceFile } from "@codemirror/lsp-client";
|
||||||
|
|
@ -104,6 +105,11 @@ export class OpenFile implements WorkspaceFile {
|
||||||
createEditor(): Editor {
|
createEditor(): Editor {
|
||||||
const editor = new Editor(this);
|
const editor = new Editor(this);
|
||||||
this.editors.push(editor);
|
this.editors.push(editor);
|
||||||
|
editor.dispatch(
|
||||||
|
editor.view.state.update(
|
||||||
|
setDiagnostics(editor.view.state, this.diagnostics || []),
|
||||||
|
),
|
||||||
|
);
|
||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,12 +178,7 @@ export class OpenFile implements WorkspaceFile {
|
||||||
es.forEach((e) => e.dispatch(e.view.state.update(trs), true));
|
es.forEach((e) => e.dispatch(e.view.state.update(trs), true));
|
||||||
} else {
|
} else {
|
||||||
this.editors.forEach((e) => {
|
this.editors.forEach((e) => {
|
||||||
const changes = transaction.changes;
|
e.dispatch(e.view.state.update(trs), true);
|
||||||
const userEvent = transaction.annotation(Transaction.userEvent);
|
|
||||||
const annotations = userEvent
|
|
||||||
? [Transaction.userEvent.of(userEvent)]
|
|
||||||
: [];
|
|
||||||
e.dispatch(e.view.state.update({ changes, annotations }), true);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -215,4 +216,14 @@ export class OpenFile implements WorkspaceFile {
|
||||||
if (this.editors.length > 0) return this.editors[0].view;
|
if (this.editors.length > 0) return this.editors[0].view;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private diagnostics: Diagnostic[];
|
||||||
|
setDiagnostics(diagnostics: Diagnostic[]) {
|
||||||
|
this.diagnostics = diagnostics;
|
||||||
|
for (const editor of this.editors) {
|
||||||
|
editor.view.dispatch(
|
||||||
|
setDiagnostics(editor.view.state, diagnostics),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,14 @@ import { EditorView } from "@codemirror/view";
|
||||||
import {
|
import {
|
||||||
LSPClient,
|
LSPClient,
|
||||||
LSPPlugin,
|
LSPPlugin,
|
||||||
languageServerExtensions,
|
|
||||||
Workspace,
|
Workspace,
|
||||||
|
serverCompletion,
|
||||||
|
hoverTooltips,
|
||||||
|
signatureHelp,
|
||||||
} from "@codemirror/lsp-client";
|
} from "@codemirror/lsp-client";
|
||||||
|
|
||||||
import { OpenFile } from "./filestate";
|
import { OpenFile } from "./filestate";
|
||||||
|
import { serverDiagnostics } from "./lsp/diagnostics";
|
||||||
|
|
||||||
// Create a very small MessagePort-based transport implementation
|
// Create a very small MessagePort-based transport implementation
|
||||||
// compatible with @codemirror/lsp-client's expected Transport interface.
|
// compatible with @codemirror/lsp-client's expected Transport interface.
|
||||||
|
|
@ -257,7 +260,12 @@ export async function createLspExtension(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const client = new LSPClient({
|
const client = new LSPClient({
|
||||||
extensions: languageServerExtensions(),
|
extensions: [
|
||||||
|
serverDiagnostics(),
|
||||||
|
serverCompletion(),
|
||||||
|
hoverTooltips(),
|
||||||
|
signatureHelp(),
|
||||||
|
],
|
||||||
rootUri: rootUri,
|
rootUri: rootUri,
|
||||||
workspace: (c) => new OpenFileWorkspace(c),
|
workspace: (c) => new OpenFileWorkspace(c),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
import type * as lsp from "vscode-languageserver-protocol"
|
||||||
|
import {setDiagnostics} from "@codemirror/lint"
|
||||||
|
import {ViewPlugin, ViewUpdate} from "@codemirror/view"
|
||||||
|
import {LSPPlugin, LSPClientExtension} from "@codemirror/lsp-client"
|
||||||
|
import {OpenFile} from "../filestate"
|
||||||
|
import { Text } from "@codemirror/state"
|
||||||
|
|
||||||
|
function toSeverity(sev: lsp.DiagnosticSeverity) {
|
||||||
|
return sev == 1 ? "error" : sev == 2 ? "warning" : sev == 3 ? "info" : "hint"
|
||||||
|
}
|
||||||
|
|
||||||
|
const autoSync = ViewPlugin.fromClass(class {
|
||||||
|
pending: any | null = null
|
||||||
|
update(update: ViewUpdate) {
|
||||||
|
if (update.docChanged) {
|
||||||
|
if (this.pending != null) clearTimeout(this.pending)
|
||||||
|
this.pending = setTimeout(() => {
|
||||||
|
this.pending = null
|
||||||
|
let plugin = LSPPlugin.get(update.view)
|
||||||
|
if (plugin) plugin.client.sync()
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destroy() {
|
||||||
|
if (this.pending != null) clearTimeout(this.pending)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function fromPosition(doc: Text, pos: lsp.Position): number {
|
||||||
|
let line = doc.line(pos.line + 1)
|
||||||
|
return line.from + pos.character
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serverDiagnostics(): LSPClientExtension {
|
||||||
|
return {
|
||||||
|
clientCapabilities: {textDocument: {publishDiagnostics: {versionSupport: true}}},
|
||||||
|
notificationHandlers: {
|
||||||
|
"textDocument/publishDiagnostics": (client, params: lsp.PublishDiagnosticsParams) => {
|
||||||
|
let file = client.workspace.getFile(params.uri) as OpenFile;
|
||||||
|
if (!file || params.version != null && params.version != file.version) return false;
|
||||||
|
for(const view of file.editors.map(e => e.view)) {
|
||||||
|
const mapPos = (p: number) => file.changes ? file.changes.mapPos(p) : p;
|
||||||
|
file.setDiagnostics(params.diagnostics.map(item => ({
|
||||||
|
from: mapPos(fromPosition(file.doc, item.range.start)),
|
||||||
|
to: mapPos(fromPosition(file.doc, item.range.end)),
|
||||||
|
severity: toSeverity(item.severity ?? 1),
|
||||||
|
message: item.message,
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editorExtension: autoSync
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue