IDEA-198819 "Show affected tests" shouldn't traverse PSI in EDT

This commit is contained in:
Sergey Ignatov
2018-09-13 20:16:40 +03:00
parent 87a1a6c846
commit b9f075c3dc
2 changed files with 48 additions and 47 deletions

View File

@@ -4,6 +4,7 @@ package com.intellij.execution.testDiscovery;
import com.intellij.execution.testDiscovery.actions.ShowAffectedTestsAction;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.project.DumbService;
@@ -121,14 +122,16 @@ public class AffectedTestsInChangeListPainter implements ChangeListDecorator, Pr
Collection<Change> changes = list.getChanges();
if (changes.isEmpty()) continue;
PsiMethod[] methods = ShowAffectedTestsAction.findMethods(myProject, ArrayUtil.toObjectArray(changes, Change.class));
List<String> paths = ShowAffectedTestsAction.getRelativeAffectedPaths(myProject, changes);
if (methods.length == 0 && paths.isEmpty()) continue;
ReadAction.run(
() -> ShowAffectedTestsAction.processMethods(myProject, methods, paths, (clazz, method, parameter) -> {
myCache.add(list.getId());
return false;
}, this::scheduleRefresh));
ApplicationManager.getApplication().executeOnPooledThread(() -> {
PsiMethod[] methods = ShowAffectedTestsAction.findMethods(myProject, ArrayUtil.toObjectArray(changes, Change.class));
List<String> paths = ShowAffectedTestsAction.getRelativeAffectedPaths(myProject, changes);
if (methods.length == 0 && paths.isEmpty()) return;
ReadAction.run(
() -> ShowAffectedTestsAction.processMethods(myProject, methods, paths, (clazz, method, parameter) -> {
myCache.add(list.getId());
return false;
}, this::scheduleRefresh));
});
}
}
}

View File

@@ -67,8 +67,10 @@ import com.intellij.util.ui.tree.TreeModelAdapter;
import com.intellij.vcsUtil.VcsFileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.uast.*;
import org.jetbrains.uast.visitor.AbstractUastVisitor;
import org.jetbrains.uast.UClass;
import org.jetbrains.uast.UMethod;
import org.jetbrains.uast.UastContextKt;
import org.jetbrains.uast.UastUtils;
import javax.swing.*;
import javax.swing.event.TreeModelEvent;
@@ -141,9 +143,9 @@ public class ShowAffectedTestsAction extends AnAction {
if (key == null) return;
DataContext dataContext = DataManager.getInstance().getDataContext(e.getRequiredData(EDITOR).getContentComponent());
FeatureUsageTracker.getInstance().triggerFeatureUsed("test.discovery");
String presentableName =
PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_NAME, 0);
showDiscoveredTestsByMethods(project, dataContext, presentableName, Collections.emptyList(), method);
String presentableName = PsiFormatUtil.formatMethod(method, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_NAME, 0);
DiscoveredTestsTree tree = showTree(project, dataContext, presentableName);
processMethods(project, new PsiMethod[]{method}, Collections.emptyList(), createTreeProcessor(tree), () -> tree.setPaintBusy(false));
}
private static void showDiscoveredTestsByChanges(@NotNull AnActionEvent e) {
@@ -157,39 +159,44 @@ public class ShowAffectedTestsAction extends AnAction {
@NotNull Change[] changes,
@NotNull String title,
@NotNull DataContext dataContext) {
PsiMethod[] asJavaMethods = findMethods(project, changes);
List<String> filePaths = getRelativeAffectedPaths(project, Arrays.asList(changes));
DiscoveredTestsTree tree = showTree(project, dataContext, title);
FeatureUsageTracker.getInstance().triggerFeatureUsed("test.discovery.selected.changes");
showDiscoveredTestsByMethods(project, dataContext, title, filePaths, asJavaMethods);
ApplicationManager.getApplication().executeOnPooledThread(() -> {
PsiMethod[] methods = findMethods(project, changes);
List<String> filePaths = getRelativeAffectedPaths(project, Arrays.asList(changes));
processMethods(project, methods, filePaths, createTreeProcessor(tree), () -> tree.setPaintBusy(false));
});
}
@NotNull
public static PsiMethod[] findMethods(@NotNull Project project, @NotNull Change... changes) {
UastMetaLanguage jvmLanguage = Language.findInstance(UastMetaLanguage.class);
List<PsiElement> methods = FormatChangedTextUtil.getInstance().getChangedElements(project, changes, file -> {
if (DumbService.isDumb(project) || project.isDisposed() || !file.isValid()) return null;
ProjectFileIndex index = ProjectFileIndex.getInstance(project);
if (!index.isInSource(file)) return null;
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
if (psiFile == null || !jvmLanguage.matchesLanguage(psiFile.getLanguage())) return null;
Document document = FileDocumentManager.getInstance().getDocument(file);
if (document == null) return null;
UFile uFile = UastContextKt.toUElement(psiFile, UFile.class);
if (uFile == null) return null;
List<PsiElement> methods = PsiDocumentManager.getInstance(project).commitAndRunReadAction(
() ->
FormatChangedTextUtil.getInstance().getChangedElements(project, changes, file -> {
if (DumbService.isDumb(project) || project.isDisposed() || !file.isValid()) return null;
ProjectFileIndex index = ProjectFileIndex.getInstance(project);
if (!index.isInSource(file)) return null;
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
if (psiFile == null || !jvmLanguage.matchesLanguage(psiFile.getLanguage())) return null;
Document document = FileDocumentManager.getInstance().getDocument(file);
if (document == null) return null;
PsiDocumentManager.getInstance(project).commitDocument(document);
List<PsiElement> physicalMethods = new ArrayList<>();
uFile.accept(new AbstractUastVisitor() {
@Override
public boolean visitMethod(@NotNull UMethod node) {
ContainerUtil.addAllNotNull(physicalMethods, node.getSourcePsi());
return true;
}
});
return physicalMethods;
});
List<PsiElement> physicalMethods = ContainerUtil.newSmartList();
psiFile.accept(new PsiRecursiveElementWalkingVisitor() {
@Override
public void visitElement(PsiElement element) {
UMethod method = UastContextKt.toUElement(element, UMethod.class);
if (method != null) {
ContainerUtil.addAllNotNull(physicalMethods, method.getSourcePsi());
}
super.visitElement(element);
}
});
return physicalMethods;
}));
return methods
.stream()
@@ -231,15 +238,6 @@ public class ShowAffectedTestsAction extends AnAction {
return at;
}
private static void showDiscoveredTestsByMethods(@NotNull Project project,
@NotNull DataContext dataContext,
@NotNull String title,
@NotNull List<String> filePaths,
@NotNull PsiMethod... methods) {
DiscoveredTestsTree tree = showTree(project, dataContext, title);
processMethods(project, methods, filePaths, createTreeProcessor(tree), () -> tree.setPaintBusy(false));
}
@NotNull
private static DiscoveredTestsTree showTree(@NotNull Project project,
@NotNull DataContext dataContext,