From e6884b1ff99bd78d771ca82c840907a596858ac1 Mon Sep 17 00:00:00 2001 From: Mickael Istria Date: Tue, 28 Mar 2023 13:17:28 +0200 Subject: [PATCH] Match diagnostics with empty ranges In Eclipse, we set a minimal range of 1 character, even for diagnostics that have an empty range (just a position); so this fixes ensure such markers and diagnostics are still matched together upon update, to avoid re-creating diagnostics. --- org.eclipse.lsp4e.tests.mock/META-INF/MANIFEST.MF | 2 +- .../lsp4e/tests/mock/MockTextDocumentService.java | 15 +++++++++++---- .../diagnostics/LSPDiagnosticsToMarkers.java | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/org.eclipse.lsp4e.tests.mock/META-INF/MANIFEST.MF b/org.eclipse.lsp4e.tests.mock/META-INF/MANIFEST.MF index 9b52a91ed..21506a9a2 100644 --- a/org.eclipse.lsp4e.tests.mock/META-INF/MANIFEST.MF +++ b/org.eclipse.lsp4e.tests.mock/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Mock Language Server to test LSP4E Bundle-SymbolicName: org.eclipse.lsp4e.tests.mock -Bundle-Version: 0.16.1.qualifier +Bundle-Version: 0.16.2.qualifier Bundle-Vendor: Eclipse LSP4E Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.lsp4j;bundle-version="[0.20.0,0.21.0)", diff --git a/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockTextDocumentService.java b/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockTextDocumentService.java index 585877509..15221bea8 100644 --- a/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockTextDocumentService.java +++ b/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockTextDocumentService.java @@ -238,10 +238,17 @@ public void didOpen(DidOpenTextDocumentParams params) { } if (this.diagnostics != null && !this.diagnostics.isEmpty()) { - // 'collect(Collectors.toSet()` is added here in order to prevent a - // ConcurrentModificationException appearance - this.remoteProxies.stream().collect(Collectors.toSet()).forEach(p -> p.publishDiagnostics( - new PublishDiagnosticsParams(params.getTextDocument().getUri(), this.diagnostics))); + // we're not sure which remote proxy to use, but we know we should only use one + // per didOpen + // for proper LS interaction; so a strategy is to use the first one and rotate + // the others + // for further executions + synchronized (this.remoteProxies) { + // and we synchronize to avoid concurrent read/write on the list + this.remoteProxies.get(0).publishDiagnostics( + new PublishDiagnosticsParams(params.getTextDocument().getUri(), this.diagnostics)); + Collections.rotate(this.remoteProxies, 1); + } } } diff --git a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java index 8ad27877f..bbd2f8918 100644 --- a/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java +++ b/org.eclipse.lsp4e/src/org/eclipse/lsp4e/operations/diagnostics/LSPDiagnosticsToMarkers.java @@ -207,7 +207,7 @@ private IMarker getExistingMarkerFor(IDocument document, Diagnostic diagnostic, for (IMarker marker : remainingMarkers) { try { if (LSPEclipseUtils.toOffset(diagnostic.getRange().getStart(), document) == MarkerUtilities.getCharStart(marker) - && LSPEclipseUtils.toOffset(diagnostic.getRange().getEnd(), document) == MarkerUtilities.getCharEnd(marker) + && (LSPEclipseUtils.toOffset(diagnostic.getRange().getEnd(), document) == MarkerUtilities.getCharEnd(marker) || Objects.equals(diagnostic.getRange().getStart(), diagnostic.getRange().getEnd())) && Objects.equals(marker.getAttribute(IMarker.MESSAGE), diagnostic.getMessage()) && Objects.equals(marker.getAttribute(LANGUAGE_SERVER_ID), this.languageServerId)) { return marker;