From 6688c2a91021a1aa3859acd91040eaca0f4bb725 Mon Sep 17 00:00:00 2001 From: Daniel Brice Date: Thu, 1 Feb 2024 18:20:38 -0800 Subject: [PATCH] Annotations fixes and improvements. * Fix bug in annotations file paths. * Fix bug in annotations where diagnostics collection are not cleaned up correctly. * Give each annotations file its own diagnostics collection. --- CHANGELOG.md | 6 ++++++ src/annotations.ts | 27 +++++++++++++++++---------- src/client.ts | 12 +++++------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 938b894..112d5b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to the "alloglot" extension will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). This project adhere's to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [unreleased] + +- Fix bug in annotations file paths. +- Fix bug in annotations where diagnostics collection are not cleaned up correctly. +- Give each annotations file its own diagnostics collection. + ## [2.0.3] - 2024-02-01 - Debug language server startup. diff --git a/src/annotations.ts b/src/annotations.ts index daf0b0e..de6a20d 100644 --- a/src/annotations.ts +++ b/src/annotations.ts @@ -33,6 +33,7 @@ Portions of this software are derived from [ghcid](https://github.com/ndmitchell > OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import { dirname } from 'path' import * as vscode from 'vscode' import { Annotation, AnnotationsConfig, LanguageConfig, alloglot } from "./config"; @@ -41,8 +42,7 @@ export function makeAnnotations(config: LanguageConfig): vscode.Disposable { const { languageId, annotations } = config if (!languageId || !annotations || annotations.length === 0) return vscode.Disposable.from() - const diagnostics = vscode.languages.createDiagnosticCollection(`${alloglot.collections.annotations}-${languageId}`) - const watchers: Array = annotations.map(file => watchAnnotationsFile(diagnostics, file)) + const watchers: Array = annotations.map(cfg => watchAnnotationsFile(languageId, cfg)) const quickFixes = vscode.languages.registerCodeActionsProvider( languageId, @@ -52,12 +52,13 @@ export function makeAnnotations(config: LanguageConfig): vscode.Disposable { return vscode.Disposable.from( quickFixes, - ...watchers, - diagnostics + ...watchers ) } -function watchAnnotationsFile(diagnostics: vscode.DiagnosticCollection, cfg: AnnotationsConfig): vscode.Disposable { +function watchAnnotationsFile(languageId: string, cfg: AnnotationsConfig): vscode.Disposable { + const diagnostics = vscode.languages.createDiagnosticCollection(`${alloglot.collections.annotations}-${languageId}-${cfg.file}`) + const messagePath = utils.path(cfg.mapping.message) const filePath = utils.path(cfg.mapping.file) const startLinePath = utils.path(cfg.mapping.startLine) @@ -112,10 +113,16 @@ function watchAnnotationsFile(diagnostics: vscode.DiagnosticCollection, cfg: Ann return sorted } + function clearAnnotations(uri: vscode.Uri): void { + diagnostics.clear() + } + function addAnnotations(uri: vscode.Uri): void { + clearAnnotations(uri) + const basedir = vscode.Uri.file(dirname(uri.fsPath)) vscode.workspace.fs.readFile(uri).then(bytes => { - annotationsBySourceFile(readAnnotations(bytes)).forEach((anns, path) => { - diagnostics.set(vscode.Uri.file(path), anns.map(utils.annotationAsDiagnostic)) + annotationsBySourceFile(readAnnotations(bytes)).forEach((anns, file) => { + diagnostics.set(vscode.Uri.joinPath(basedir, file), anns.map(ann => utils.annotationAsDiagnostic(basedir, ann))) }) }) } @@ -126,7 +133,7 @@ function watchAnnotationsFile(diagnostics: vscode.DiagnosticCollection, cfg: Ann watcher.onDidChange(addAnnotations) watcher.onDidCreate(addAnnotations) - watcher.onDidDelete(diagnostics.delete) + watcher.onDidDelete(clearAnnotations) return watcher }) || [] @@ -135,7 +142,7 @@ function watchAnnotationsFile(diagnostics: vscode.DiagnosticCollection, cfg: Ann } namespace utils { - export function annotationAsDiagnostic(ann: Annotation): vscode.Diagnostic { + export function annotationAsDiagnostic(basedir: vscode.Uri, ann: Annotation): vscode.Diagnostic { const range = new vscode.Range( new vscode.Position(ann.startLine - 1, ann.startColumn - 1), new vscode.Position(ann.endLine - 1, ann.endColumn - 1) @@ -144,7 +151,7 @@ namespace utils { // we are abusing the relatedInformation field to store replacements // we look them up later when we need to create quick fixes const relatedInformation = ann.replacements.map(replacement => { - const uri = vscode.Uri.file(ann.file) + const uri = vscode.Uri.joinPath(basedir, ann.file) const location = new vscode.Location(uri, range) return new vscode.DiagnosticRelatedInformation(location, replacement) }) diff --git a/src/client.ts b/src/client.ts index eac093c..e386165 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,4 +1,3 @@ -import * as child_process from 'child_process' import * as vscode from 'vscode' import * as lsp from 'vscode-languageclient/node' @@ -39,25 +38,24 @@ export function makeClient(config: LanguageConfig): vscode.Disposable { workspaceFolder: vscode.workspace.workspaceFolders?.[0] } - output.append(`${alloglot.root} debug: Starting language client...\n`) - let client = new lsp.LanguageClient( clientId, - `${alloglot.root} language client for ${languageId}`, + `${alloglot.root}-${languageId}`, serverOptions, clientOptions, false ) + output.append(`${alloglot.root}: Starting language client...\n`) client.start() - output.append(`${alloglot.root} debug: Language client started.\n`) + output.append(`${alloglot.root}: Language client started.\n`) return vscode.Disposable.from( { dispose: () => { - output.append(`${alloglot.root} debug: Stopping language client...\n`) + output.append(`${alloglot.root}: Stopping language client...\n`) client.stop() - output.append(`${alloglot.root} debug: Language client stopped.\n`) + output.append(`${alloglot.root}: Language client stopped.\n`) } }, output