From 6258e787f7a60a8e5d75e6c23e5dee92e9064ea4 Mon Sep 17 00:00:00 2001 From: Leon Date: Fri, 26 Jan 2024 11:50:57 +0100 Subject: [PATCH] feat: use incremental instead of full content updates --- src/app.ts | 2 +- src/lsp.ts | 42 ++++++++++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/app.ts b/src/app.ts index d08b970..dd2438b 100644 --- a/src/app.ts +++ b/src/app.ts @@ -11,7 +11,7 @@ const main = async () => { triggerCharacters: ["{", "(", ")", "=", ">", " ", ",", ":", ".", "<", "/"] }, textDocumentSync: { - change: 1, + change: 2, } } }) diff --git a/src/lsp.ts b/src/lsp.ts index 11efb91..c874d2b 100644 --- a/src/lsp.ts +++ b/src/lsp.ts @@ -19,8 +19,8 @@ enum DiagnosticSeverity { } type Position = { - start: number, - end: number + line: number, + character: number } type Range = { @@ -81,25 +81,47 @@ class Service { this.on(Event.DidOpen, ({ ctx, request }) => { ctx.currentUri = request.params.textDocument.uri + ctx.contents = request.params.textDocument.text + ctx.language = request.params.textDocument.languageId + ctx.contentVersion = 0 }) - this.on(Event.Shutdown, ({ ctx, request }) => { + this.on(Event.Shutdown, () => { log("received shutdown request") process.exit(0) }) - this.on(Event.DidOpen, async ({ ctx, request }) => { - ctx.contents = request.params.textDocument.text - ctx.language = request.params.textDocument.languageId - ctx.contentVersion = 0 - }) - this.on(Event.DidChange, async ({ ctx, request }) => { - ctx.contents = request.params.contentChanges[0].text + request.params.contentChanges.forEach((change) => { + this.positionalUpdate(change.text, change.range) + }) + ctx.contentVersion = request.params.textDocument.version }) } + positionalUpdate(text: string, range: Range) { + const lines = this.contents.split("\n") + const start = range.start.line + const end = range.end.line + const startLine = lines[start] + const endLine = lines[end] + const startLineStart = startLine.substring(0, range.start.character) + const endLineEnd = endLine.substring(range.end.character) + const newLines = [startLineStart + text + endLineEnd] + + const newContents = lines.reduce((acc, line, index) => { + if (index < start || index > end) { + acc.push(line) + } else if (index === start) { + acc.push(newLines[0]) + } + return acc + }, []) + + this.contents = newContents.join("\n") + } + on(event: string, callback: (request: EventRequest) => void) { const parent = this