From 2f3ea4cb1f25e738a2495a6446f87741db6f78bd Mon Sep 17 00:00:00 2001 From: azerr Date: Tue, 3 Oct 2023 15:59:05 +0200 Subject: [PATCH] fix: Deadlock with IDEA EAP 2023-3 EAP Fixes #1192 Signed-off-by: azerr --- .../internal/PromiseToCompletableFuture.java | 2 +- .../codelens/LSPCodelensInlayProvider.java | 56 +++++++++---------- .../inlayhint/LSPInlayHintInlayProvider.java | 17 +++--- .../intellij/quarkus/lsp/QuarkusServer.java | 12 +++- .../intellij/qute/lsp/QuteServer.java | 12 +++- 5 files changed, 61 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/internal/PromiseToCompletableFuture.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/internal/PromiseToCompletableFuture.java index cc293b508..9f830956b 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/internal/PromiseToCompletableFuture.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/internal/PromiseToCompletableFuture.java @@ -91,7 +91,7 @@ private void bind(CancellablePromise> promise) { promise.onError(ex -> { if (ex instanceof ProcessCanceledException || ex instanceof CancellationException) { // Case 2: cancel the completable future - this.cancel(true); + super.cancel(true); } else { // Other case..., mark the completable future as error this.completeExceptionally(ex); diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/codelens/LSPCodelensInlayProvider.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/codelens/LSPCodelensInlayProvider.java index 384e3100c..5d1749956 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/codelens/LSPCodelensInlayProvider.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/codelens/LSPCodelensInlayProvider.java @@ -72,28 +72,33 @@ public boolean collect(@NotNull PsiElement psiElement, @NotNull Editor editor, @ // The project has been closed, don't collect code lenses. return false; } + VirtualFile file = LSPIJUtils.getFile(psiFile); + if (file == null) { + return false; + } + URI fileUri = LSPIJUtils.toUri(file); + if (fileUri == null) { + return false; + } Document document = editor.getDocument(); final CancellationSupport cancellationSupport = new CancellationSupport(); try { - VirtualFile file = LSPIJUtils.getFile(psiElement); - URI docURI = LSPIJUtils.toUri(file); - if (docURI != null) { - CodeLensParams param = new CodeLensParams(new TextDocumentIdentifier(docURI.toString())); - BlockingDeque> pairs = new LinkedBlockingDeque<>(); - CompletableFuture future = collect(file, project, param, pairs, cancellationSupport); - List>> codeLenses = createCodeLenses(document, pairs, future, cancellationSupport); - codeLenses.stream() - .collect(Collectors.groupingBy(p -> p.first)) - .forEach((offset, list) -> - inlayHintsSink.addBlockElement( - offset, - true, - true, - 0, - toPresentation(editor, offset, list, getFactory())) - ); - } + CodeLensParams param = new CodeLensParams(new TextDocumentIdentifier(fileUri.toString())); + BlockingDeque> pairs = new LinkedBlockingDeque<>(); + + CompletableFuture future = collect(file, project, param, pairs, cancellationSupport); + List>> codeLenses = createCodeLenses(document, pairs, future, cancellationSupport); + codeLenses.stream() + .collect(Collectors.groupingBy(p -> p.first)) + .forEach((offset, list) -> + inlayHintsSink.addBlockElement( + offset, + true, + true, + 0, + toPresentation(editor, offset, list, getFactory())) + ); } catch (ProcessCanceledException e) { // Cancel all LSP requests cancellationSupport.cancel(); @@ -109,16 +114,11 @@ public boolean collect(@NotNull PsiElement psiElement, @NotNull Editor editor, @ private List>> createCodeLenses(Document document, BlockingDeque> pairs, CompletableFuture future, CancellationSupport cancellationSupport) throws InterruptedException { List>> codelenses = new ArrayList<>(); while (!future.isDone() || !pairs.isEmpty()) { - try { - ProgressManager.checkCanceled(); - Pair pair = pairs.poll(25, TimeUnit.MILLISECONDS); - if (pair != null) { - int offset = LSPIJUtils.toOffset(pair.getFirst().getRange().getStart(), document); - codelenses.add(Pair.create(offset, pair)); - } - } catch (ProcessCanceledException e) { - cancellationSupport.cancel(); - throw e; + ProgressManager.checkCanceled(); + Pair pair = pairs.poll(25, TimeUnit.MILLISECONDS); + if (pair != null) { + int offset = LSPIJUtils.toOffset(pair.getFirst().getRange().getStart(), document); + codelenses.add(Pair.create(offset, pair)); } } return codelenses; diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/inlayhint/LSPInlayHintInlayProvider.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/inlayhint/LSPInlayHintInlayProvider.java index f89f2965d..ae31aa6bb 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/inlayhint/LSPInlayHintInlayProvider.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/inlayhint/LSPInlayHintInlayProvider.java @@ -69,16 +69,19 @@ public boolean collect(@NotNull PsiElement psiElement, @NotNull Editor editor, @ // The project has been closed, don't collect inlay hints. return false; } + VirtualFile file = LSPIJUtils.getFile(psiFile); + if (file == null) { + return false; + } + URI fileUri = LSPIJUtils.toUri(file); + if (fileUri == null) { + return false; + } Document document = editor.getDocument(); final CancellationSupport cancellationSupport = new CancellationSupport(); try { - VirtualFile file = LSPIJUtils.getFile(psiFile); - if (file == null) { - return false; - } - URI docURI = LSPIJUtils.toUri(file); Range viewPortRange = getViewPortRange(editor); - InlayHintParams param = new InlayHintParams(new TextDocumentIdentifier(docURI.toString()), viewPortRange); + InlayHintParams param = new InlayHintParams(new TextDocumentIdentifier(fileUri.toASCIIString()), viewPortRange); BlockingDeque> pairs = new LinkedBlockingDeque<>(); CompletableFuture future = collect(psiElement.getProject(), file, param, pairs, cancellationSupport); @@ -90,7 +93,7 @@ public boolean collect(@NotNull PsiElement psiElement, @NotNull Editor editor, @ } catch (ProcessCanceledException e) { // Cancel all LSP requests cancellationSupport.cancel(); - throw e; + return false; //throw e; } catch (InterruptedException e) { LOGGER.warn(e.getLocalizedMessage(), e); Thread.currentThread().interrupt(); diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusServer.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusServer.java index 94e6c0688..a7cff9dd0 100644 --- a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusServer.java +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusServer.java @@ -14,11 +14,14 @@ import com.intellij.ide.plugins.PluginManager; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.project.Project; +import com.redhat.devtools.intellij.lsp4ij.operations.codelens.LSPCodelensInlayProvider; import com.redhat.devtools.intellij.lsp4mp4ij.settings.MicroProfileInspectionsInfo; import com.redhat.devtools.intellij.quarkus.TelemetryService; import com.redhat.devtools.intellij.lsp4ij.server.JavaProcessCommandBuilder; import com.redhat.devtools.intellij.lsp4ij.server.ProcessStreamConnectionProvider; import com.redhat.devtools.intellij.lsp4mp4ij.settings.UserDefinedMicroProfileSettings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.net.URI; @@ -32,6 +35,8 @@ */ public class QuarkusServer extends ProcessStreamConnectionProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(QuarkusServer.class); + private final Project project; public QuarkusServer(Project project) { @@ -47,7 +52,12 @@ public QuarkusServer(Project project) { commands.add("-DrunAsync=true"); super.setCommands(commands); - TelemetryService.instance().action(TelemetryService.LSP_PREFIX + "start").send(); + try { + TelemetryService.instance().action(TelemetryService.LSP_PREFIX + "start").send(); + } + catch(Exception e) { + LOGGER.error("Error while consuming telemtry service", e); + } } @Override diff --git a/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteServer.java b/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteServer.java index 38ee1c6c6..5687a711b 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteServer.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteServer.java @@ -18,8 +18,11 @@ import com.redhat.devtools.intellij.quarkus.TelemetryService; import com.redhat.devtools.intellij.lsp4ij.server.JavaProcessCommandBuilder; import com.redhat.devtools.intellij.lsp4ij.server.ProcessStreamConnectionProvider; +import com.redhat.devtools.intellij.quarkus.lsp.QuarkusServer; import com.redhat.devtools.intellij.qute.settings.QuteInspectionsInfo; import com.redhat.devtools.intellij.qute.settings.UserDefinedQuteSettings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.net.URI; @@ -33,6 +36,8 @@ */ public class QuteServer extends ProcessStreamConnectionProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(QuteServer.class); + private final Project project; public QuteServer(Project project) { @@ -46,7 +51,12 @@ public QuteServer(Project project) { commands.add("-DrunAsync=true"); super.setCommands(commands); - TelemetryService.instance().action(TelemetryService.LSP_PREFIX + "startQute").send(); + try { + TelemetryService.instance().action(TelemetryService.LSP_PREFIX + "startQute").send(); + } + catch(Exception e) { + LOGGER.error("Error while consuming telemtry service", e); + } } @Override