From 7878a20a75cf76aa5bb7e4ccaec2e86408b2a5cf Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 17 Aug 2017 13:46:46 +0300 Subject: [PATCH] inspections cancelability: assert that long processes like find in files or find usages are running under the cancelable indicator --- .../java/index/ConcurrentIndexTest.groovy | 23 ++++++++++++++----- .../progress/impl/CoreProgressManager.java | 8 +++++++ .../psi/impl/search/PsiSearchHelperImpl.java | 4 ++++ .../usages/impl/SearchForUsagesRunnable.java | 8 +++++-- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/java/index/ConcurrentIndexTest.groovy b/java/java-tests/testSrc/com/intellij/java/index/ConcurrentIndexTest.groovy index 5a4c6f46b122..15ba9ccf9195 100644 --- a/java/java-tests/testSrc/com/intellij/java/index/ConcurrentIndexTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/index/ConcurrentIndexTest.groovy @@ -19,6 +19,10 @@ import com.intellij.lang.FCTSBackedLighterAST import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ReadAction import com.intellij.openapi.command.WriteCommandAction +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.progress.Task +import com.intellij.openapi.progress.impl.CoreProgressManager import com.intellij.psi.* import com.intellij.psi.impl.PsiDocumentManagerBase import com.intellij.psi.impl.search.JavaNullMethodArgumentUtil @@ -30,6 +34,7 @@ import com.intellij.testFramework.SkipSlowTestLocally import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase import com.intellij.util.ref.GCUtil import groovy.transform.CompileStatic +import org.jetbrains.annotations.NotNull import java.util.concurrent.CountDownLatch import java.util.concurrent.Future @@ -200,12 +205,18 @@ class ConcurrentIndexTest extends JavaCodeInsightFixtureTestCase { assert file.node.lighterAST instanceof FCTSBackedLighterAST List futures = [] - futures << ApplicationManager.application.executeOnPooledThread { ReadAction.run { - assert !JavaNullMethodArgumentUtil.hasNullArgument(clazz.methods[0], 0) - } } - futures << ApplicationManager.application.executeOnPooledThread { ReadAction.run { - assert JavaPsiFacade.getInstance(project).findClass('Foo', GlobalSearchScope.allScope(project)) - } } + futures << ((CoreProgressManager)ProgressManager.instance).runProcessWithProgressAsynchronously(new Task.Backgroundable(myFixture.project, "hasNull") { + @Override + void run(@NotNull ProgressIndicator indicator) { ReadAction.run { + assert !JavaNullMethodArgumentUtil.hasNullArgument(clazz.methods[0], 0) + }} + }) + futures << ((CoreProgressManager)ProgressManager.instance).runProcessWithProgressAsynchronously(new Task.Backgroundable(myFixture.project, "findClass") { + @Override + void run(@NotNull ProgressIndicator indicator) { ReadAction.run { + assert JavaPsiFacade.getInstance(project).findClass('Foo', GlobalSearchScope.allScope(project)) + }} + }) futures.each { it.get() } } } diff --git a/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java b/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java index a13a34d582b1..4341e03e44ab 100644 --- a/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java +++ b/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java @@ -741,4 +741,12 @@ public class CoreProgressManager extends ProgressManager implements Disposable { boolean runHook(@Nullable ProgressIndicator indicator); } + public static void assertUnderProgress(@NotNull ProgressIndicator indicator) { + synchronized (threadsUnderIndicator) { + Set threads = threadsUnderIndicator.get(indicator); + if (threads == null || !threads.contains(Thread.currentThread())) { + throw new IllegalStateException("Must be executed under progress indicator: "+indicator+". Please see e.g. ProgressManager.runProcess()"); + } + } + } } diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index ed88931c5a91..4ef9dadfb307 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -28,6 +28,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.*; +import com.intellij.openapi.progress.impl.CoreProgressManager; import com.intellij.openapi.progress.util.TooManyUsagesStatus; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; @@ -340,6 +341,9 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { @NotNull final Processor localProcessor) { ApplicationEx app = (ApplicationEx)ApplicationManager.getApplication(); final AtomicBoolean canceled = new AtomicBoolean(false); + if (!app.isDispatchThread()) { + CoreProgressManager.assertUnderProgress(progress); + } while (true) { ProgressManager.checkCanceled(); diff --git a/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java b/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java index cf6d32b5a99e..6adeba04e3e3 100644 --- a/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java +++ b/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java @@ -31,6 +31,7 @@ import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.module.UnloadedModuleDescription; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.impl.CoreProgressManager; import com.intellij.openapi.progress.util.ProgressWrapper; import com.intellij.openapi.progress.util.TooManyUsagesStatus; import com.intellij.openapi.project.Project; @@ -351,7 +352,10 @@ class SearchForUsagesRunnable implements Runnable { private void searchUsages(@NotNull final AtomicBoolean findStartedBalloonShown) { ProgressIndicator indicator = ProgressWrapper.unwrap(ProgressManager.getInstance().getProgressIndicator()); - assert indicator != null : "must run find usages under progress"; + if (indicator == null) throw new IllegalStateException("must run find usages under progress"); + if (!ApplicationManager.getApplication().isDispatchThread()) { + CoreProgressManager.assertUnderProgress(indicator); + } TooManyUsagesStatus.createFor(indicator); Alarm findUsagesStartedBalloon = new Alarm(); findUsagesStartedBalloon.addRequest(() -> { @@ -363,7 +367,7 @@ class SearchForUsagesRunnable implements Runnable { usageSearcher.generate(usage -> { ProgressIndicator indicator1 = ProgressWrapper.unwrap(ProgressManager.getInstance().getProgressIndicator()); - assert indicator1 != null : "must run find usages under progress"; + if (indicator1 == null) throw new IllegalStateException("must run find usages under progress"); if (indicator1.isCanceled()) return false; if (!UsageViewManagerImpl.isInScope(usage, mySearchScopeToWarnOfFallingOutOf)) {