diff --git a/java/execution/impl/intellij.java.execution.impl.iml b/java/execution/impl/intellij.java.execution.impl.iml
index ccea3a44b23f..528e250ee475 100644
--- a/java/execution/impl/intellij.java.execution.impl.iml
+++ b/java/execution/impl/intellij.java.execution.impl.iml
@@ -25,6 +25,7 @@
+
diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/AffectedTestsChangeListDecorator.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/AffectedTestsChangeListDecorator.java
deleted file mode 100644
index d89c3a3707da..000000000000
--- a/java/execution/impl/src/com/intellij/execution/testDiscovery/AffectedTestsChangeListDecorator.java
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-package com.intellij.execution.testDiscovery;
-
-import com.intellij.execution.testDiscovery.actions.ShowDiscoveredTestsAction;
-import com.intellij.ide.DataManager;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.registry.Registry;
-import com.intellij.openapi.vcs.changes.Change;
-import com.intellij.openapi.vcs.changes.ChangeListDecorator;
-import com.intellij.openapi.vcs.changes.LocalChangeList;
-import com.intellij.ui.ColoredTreeCellRenderer;
-import com.intellij.ui.SimpleTextAttributes;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.NotNull;
-
-import static com.intellij.ui.SimpleTextAttributes.STYLE_UNDERLINE;
-
-public class AffectedTestsChangeListDecorator implements ChangeListDecorator {
- private final Project myProject;
-
- public AffectedTestsChangeListDecorator(@NotNull Project project) {
- myProject = project;
- }
-
- @Override
- public void decorateChangeList(LocalChangeList changeList,
- ColoredTreeCellRenderer renderer,
- boolean selected,
- boolean expanded,
- boolean hasFocus) {
- if (!Registry.is("show.affected.tests.in.changelists")) return;
- if (!ShowDiscoveredTestsAction.isEnabled(myProject)) return;
- if (changeList.getChanges().isEmpty()) return;
-
- renderer.append(", ", SimpleTextAttributes.GRAYED_ATTRIBUTES);
- renderer.append("show affected tests", new SimpleTextAttributes(STYLE_UNDERLINE, UIUtil.getInactiveTextColor()), (Runnable)() -> {
- DataContext dataContext = DataManager.getInstance().getDataContext(renderer.getTree());
- Change[] objects = ArrayUtil.toObjectArray(changeList.getChanges(), Change.class);
- ShowDiscoveredTestsAction.showDiscoveredTestsByChanges(myProject, objects, changeList.getName(), dataContext);
- });
- }
-}
\ No newline at end of file
diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/AffectedTestsInChangeListPainter.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/AffectedTestsInChangeListPainter.java
new file mode 100644
index 000000000000..6a57d00d50ac
--- /dev/null
+++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/AffectedTestsInChangeListPainter.java
@@ -0,0 +1,125 @@
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.execution.testDiscovery;
+
+import com.intellij.execution.testDiscovery.actions.ShowDiscoveredTestsAction;
+import com.intellij.ide.DataManager;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.components.ProjectComponent;
+import com.intellij.openapi.project.DumbService;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.vcs.changes.*;
+import com.intellij.psi.PsiMethod;
+import com.intellij.ui.ColoredTreeCellRenderer;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.util.Alarm;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.io.PowerStatus;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static com.intellij.ui.SimpleTextAttributes.STYLE_UNDERLINE;
+
+public class AffectedTestsInChangeListPainter implements ChangeListDecorator, ProjectComponent {
+ private final Project myProject;
+ private final ChangeListManager myChangeListManager;
+ private final ChangeListAdapter myChangeListListener;
+ private final Alarm myAlarm;
+ private final Set myCache = new HashSet<>();
+
+ public AffectedTestsInChangeListPainter(@NotNull Project project, ChangeListManager changeListManager) {
+ myProject = project;
+ myChangeListManager = changeListManager;
+ myChangeListListener = new ChangeListAdapter() {
+ @Override
+ public void changeListsChanged() {
+ scheduleUpdate();
+ }
+
+ @Override
+ public void changeListUpdateDone() {
+ scheduleUpdate();
+ }
+
+ @Override
+ public void defaultListChanged(ChangeList oldDefaultList, ChangeList newDefaultList, boolean automatic) {
+ scheduleUpdate();
+ }
+
+ @Override
+ public void unchangedFileStatusChanged() {
+ scheduleUpdate();
+ }
+ };
+ myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, project);
+ myChangeListManager.addChangeListListener(myChangeListListener);
+ }
+
+ @Override
+ public void projectOpened() {
+ DumbService.getInstance(myProject).runWhenSmart(() -> scheduleUpdate());
+ }
+
+ @Override
+ public void projectClosed() {
+ myAlarm.cancelAllRequests();
+ }
+
+ @Override
+ public void disposeComponent() {
+ myAlarm.cancelAllRequests();
+ myCache.clear();
+ myChangeListManager.removeChangeListListener(myChangeListListener);
+ }
+
+ private static int updateDelay() {
+ return PowerStatus.getPowerStatus() == PowerStatus.AC ? 50 : 300;
+ }
+
+ @Override
+ public void decorateChangeList(LocalChangeList changeList,
+ ColoredTreeCellRenderer renderer,
+ boolean selected,
+ boolean expanded,
+ boolean hasFocus) {
+ if (!Registry.is("show.affected.tests.in.changelists")) return;
+ if (!ShowDiscoveredTestsAction.isEnabled(myProject)) return;
+ if (changeList.getChanges().isEmpty()) return;
+ if (!myCache.contains(changeList.getId())) return;
+
+ renderer.append(", ", SimpleTextAttributes.GRAYED_ATTRIBUTES);
+ renderer.append("show affected tests", new SimpleTextAttributes(STYLE_UNDERLINE, UIUtil.getInactiveTextColor()), (Runnable)() -> {
+ DataContext dataContext = DataManager.getInstance().getDataContext(renderer.getTree());
+ Change[] changes = ArrayUtil.toObjectArray(changeList.getChanges(), Change.class);
+ ShowDiscoveredTestsAction.showDiscoveredTestsByChanges(myProject, changes, changeList.getName(), dataContext);
+ });
+ }
+
+ private void scheduleUpdate() {
+ if (!Registry.is("show.affected.tests.in.changelists")) return;
+ if (!ShowDiscoveredTestsAction.isEnabled(myProject)) return;
+ myAlarm.cancelAllRequests();
+ myAlarm.addRequest(() -> update(), updateDelay());
+ }
+
+ private void update() {
+ myCache.clear();
+ List lists = myChangeListManager.getChangeLists();
+ for (LocalChangeList list : lists) {
+ if (list.getChanges().isEmpty()) continue;
+
+ PsiMethod[] methods = ShowDiscoveredTestsAction.findMethods(myProject, ArrayUtil.toObjectArray(list.getChanges(), Change.class));
+ if (methods.length == 0) continue;
+ ReadAction.run(
+ () -> ShowDiscoveredTestsAction.processMethods(myProject, methods, (clazz, method, parameter) -> {
+ myCache.add(list.getId());
+ return false;
+ }, () -> ChangesViewManager.getInstance(myProject).scheduleRefresh()));
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryProducer.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryProducer.java
index 194bd21a7dea..75e8580e8994 100644
--- a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryProducer.java
+++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryProducer.java
@@ -5,6 +5,8 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Couple;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiMethod;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.ApiStatus;
@@ -32,7 +34,7 @@ public interface TestDiscoveryProducer {
@NotNull String classFQName,
@NotNull String methodName,
byte frameworkId,
- @NotNull TestConsumer consumer) {
+ @NotNull TestProcessor processor) {
MultiMap visitedTests = new MultiMap() {
@NotNull
@Override
@@ -47,7 +49,7 @@ public interface TestDiscoveryProducer {
if (!visitedTests.get(classFQName).contains(methodRawName)) {
visitedTests.putValue(className, methodRawName);
Couple couple = extractParameter(methodRawName);
- consumer.accept(className, couple.first, couple.second);
+ if (!processor.process(className, couple.first, couple.second)) return;
}
}
}
@@ -63,7 +65,12 @@ public interface TestDiscoveryProducer {
}
@FunctionalInterface
- interface TestConsumer {
- boolean accept(@NotNull String className, @NotNull String methodName, @Nullable String parameter);
+ interface TestProcessor {
+ boolean process(@NotNull String className, @NotNull String methodName, @Nullable String parameter);
+ }
+
+ @FunctionalInterface
+ interface PsiTestProcessor {
+ boolean process(@NotNull PsiClass clazz, @NotNull PsiMethod method, @Nullable String parameter);
}
}
diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/actions/DiscoveredTestsTree.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/actions/DiscoveredTestsTree.java
index 3fc8b63f9730..46e19db1d68c 100644
--- a/java/execution/impl/src/com/intellij/execution/testDiscovery/actions/DiscoveredTestsTree.java
+++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/actions/DiscoveredTestsTree.java
@@ -138,6 +138,10 @@ class DiscoveredTestsTree extends Tree implements DataProvider {
return myModel.getTestCount();
}
+ public int getTestClassesCount() {
+ return myModel.getTestClassesCount();
+ }
+
@Nullable
@Override
public Object getData(String dataId) {
diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/actions/DiscoveredTestsTreeModel.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/actions/DiscoveredTestsTreeModel.java
index 09fc877100ac..5d8500aa1b8a 100644
--- a/java/execution/impl/src/com/intellij/execution/testDiscovery/actions/DiscoveredTestsTreeModel.java
+++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/actions/DiscoveredTestsTreeModel.java
@@ -98,6 +98,10 @@ class DiscoveredTestsTreeModel extends BaseTreeModel
- com.intellij.execution.testDiscovery.AffectedTestsChangeListDecorator
+ com.intellij.execution.testDiscovery.AffectedTestsInChangeListPainter