From 4f4df61f882e711fc13a99f0929ae68612341a10 Mon Sep 17 00:00:00 2001 From: azerr Date: Thu, 10 Aug 2023 17:46:19 +0200 Subject: [PATCH] fix: Too many non-blocking read actions submitted at once in LSPDiagnosticHandler Fixes #1089 Signed-off-by: azerr --- .../diagnostics/LSPDiagnosticHandler.java | 16 +++++++++++--- .../ClasspathResourceChangedNotifier.java | 21 ++++++++++++++----- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/diagnostics/LSPDiagnosticHandler.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/diagnostics/LSPDiagnosticHandler.java index 67f271dfc..720023465 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/diagnostics/LSPDiagnosticHandler.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/operations/diagnostics/LSPDiagnosticHandler.java @@ -17,6 +17,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; @@ -45,12 +46,21 @@ public LSPDiagnosticHandler(LanguageServerWrapper languageServerWrapper) { @Override public void accept(PublishDiagnosticsParams params) { + Project project = languageServerWrapper.getProject(); + if(project.isDisposed()) { + return; + } if (ApplicationManager.getApplication().isReadAccessAllowed()) { updateDiagnostics(params); } else { - ReadAction.nonBlocking(() -> updateDiagnostics(params)) - .submit(AppExecutorUtil.getAppExecutorService()); - + var executeInSmartMode = DumbService.getInstance(languageServerWrapper.getProject()).isDumb(); + var action = ReadAction.nonBlocking(() -> updateDiagnostics(params)) + .expireWith(languageServerWrapper) + .coalesceBy(params); + if (executeInSmartMode) { + action.inSmartMode(project); + } + action.submit(AppExecutorUtil.getAppExecutorService()); } } diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedNotifier.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedNotifier.java index 35fb93c36..f5f0e1608 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedNotifier.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/classpath/ClasspathResourceChangedNotifier.java @@ -35,7 +35,7 @@ /** * Source file change notifier with a debounce mode. */ -public class ClasspathResourceChangedNotifier implements Disposable { +public class ClasspathResourceChangedNotifier implements Disposable { private static final long DEBOUNCE_DELAY = 1000; @@ -46,7 +46,8 @@ public class ClasspathResourceChangedNotifier implements Disposable { private final Set> sourceFiles; private boolean librariesChanged; -private final List processBeforeLibrariesChanged; + private final List processBeforeLibrariesChanged; + private boolean disposed; public ClasspathResourceChangedNotifier(Project project, List preprocessors) { this.project = project; @@ -74,6 +75,9 @@ public synchronized void addSourceFile(Pair pair) { } private void asyncNotifyChanges() { + if (isDisposed()) { + return; + } if (ApplicationManager.getApplication().isUnitTestMode()) { notifyChanges(); } else { @@ -93,6 +97,9 @@ public void run() { } private void notifyChanges() { + if (isDisposed()) { + return; + } synchronized (sourceFiles) { // Java, config sources files has changed project.getMessageBus().syncPublisher(ClasspathResourceChangedManager.TOPIC).sourceFilesChanged(sourceFiles); @@ -121,8 +128,7 @@ public void run(@NotNull ProgressIndicator progressIndicator) { for (var runnable : processBeforeLibrariesChanged) { runnable.run(progressIndicator); } - } - finally { + } finally { // Send the libraries changed event project.getMessageBus().syncPublisher(ClasspathResourceChangedManager.TOPIC).librariesChanged(); librariesChanged = false; @@ -134,12 +140,17 @@ public void run(@NotNull ProgressIndicator progressIndicator) { } } + public boolean isDisposed() { + return disposed; + } + @Override public void dispose() { + this.disposed = true; if (debounceTask != null) { debounceTask.cancel(); } - if(debounceTimer != null) { + if (debounceTimer != null) { debounceTimer.cancel(); } }