inspections cancelability:

assert that long processes like find in files or find usages are running under the cancelable indicator
This commit is contained in:
Alexey Kudravtsev
2017-08-17 13:49:57 +03:00
parent 7b2c8bb8b8
commit 7878a20a75
4 changed files with 35 additions and 8 deletions
@@ -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<Future> 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() }
}
}
@@ -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<Thread> 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()");
}
}
}
}
@@ -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<VirtualFile> localProcessor) {
ApplicationEx app = (ApplicationEx)ApplicationManager.getApplication();
final AtomicBoolean canceled = new AtomicBoolean(false);
if (!app.isDispatchThread()) {
CoreProgressManager.assertUnderProgress(progress);
}
while (true) {
ProgressManager.checkCanceled();
@@ -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)) {