parallelize java slow marker pass a bit

This commit is contained in:
peter
2016-06-14 17:36:47 +02:00
parent a61e8cfdc6
commit 66f472e53f
2 changed files with 49 additions and 30 deletions
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.daemon.*;
import com.intellij.concurrency.JobLauncher;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
@@ -26,7 +27,10 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.editor.markup.SeparatorPlacement;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -40,16 +44,15 @@ import com.intellij.psi.util.PsiExpressionTrimRenderer;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import com.intellij.util.FunctionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
protected final DaemonCodeAnalyzerSettings myDaemonSettings;
@@ -163,7 +166,9 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
public void collectSlowLineMarkers(@NotNull final List<PsiElement> elements, @NotNull final Collection<LineMarkerInfo> result) {
ApplicationManager.getApplication().assertReadAccessAllowed();
Collection<PsiMethod> methods = new THashSet<>();
List<Computable<List<LineMarkerInfo>>> tasks = new ArrayList<>();
MultiMap<PsiClass, PsiMethod> byClass = MultiMap.create();
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < elements.size(); i++) {
PsiElement element = elements.get(i);
@@ -172,30 +177,40 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
PsiElement parent = element.getParent();
if (parent instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)parent;
if (PsiUtil.canBeOverriden(method)) {
methods.add(method);
PsiClass psiClass = method.getContainingClass();
if (PsiUtil.canBeOverriden(method) && psiClass != null) {
byClass.putValue(psiClass, method);
}
}
else if (parent instanceof PsiClass && !(parent instanceof PsiTypeParameter)) {
collectInheritingClasses((PsiClass)parent, result);
tasks.add(() -> collectInheritingClasses((PsiClass)parent));
}
}
if (!methods.isEmpty()) {
collectSiblingInheritedMethods(methods, result);
collectOverridingMethods(methods, result);
for (PsiClass psiClass : byClass.keySet()) {
List<PsiMethod> methods = new ArrayList<>(byClass.get(psiClass));
tasks.add(() -> collectSiblingInheritedMethods(methods));
tasks.add(() -> collectOverridingMethods(methods));
}
Object lock = new Object();
ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator();
JobLauncher.getInstance().invokeConcurrentlyUnderProgress(tasks, indicator, true, computable -> {
List<LineMarkerInfo> infos = computable.compute();
synchronized (lock) {
result.addAll(infos);
}
return true;
});
}
private static void collectSiblingInheritedMethods(@NotNull final Collection<PsiMethod> methods,
@NotNull Collection<LineMarkerInfo> result) {
private static List<LineMarkerInfo> collectSiblingInheritedMethods(@NotNull final Collection<PsiMethod> methods) {
Map<PsiMethod, FindSuperElementsHelper.SiblingInfo> map = FindSuperElementsHelper.getSiblingInheritanceInfos(methods);
for (PsiMethod method : map.keySet()) {
return ContainerUtil.map(map.keySet(), method -> {
PsiElement range = getMethodRange(method);
ArrowUpLineMarkerInfo upInfo = new ArrowUpLineMarkerInfo(range, AllIcons.Gutter.ImplementingMethod, MarkerType.SIBLING_OVERRIDING_METHOD,
Pass.UPDATE_OVERRIDDEN_MARKERS);
LineMarkerInfo info = NavigateAction.setNavigateAction(upInfo, "Go to super method", IdeActions.ACTION_GOTO_SUPER);
result.add(info);
}
Pass.UPDATE_OVERRIDDEN_MARKERS);
return NavigateAction.setNavigateAction(upInfo, "Go to super method", IdeActions.ACTION_GOTO_SUPER);
});
}
@NotNull
@@ -216,22 +231,23 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
return range;
}
protected void collectInheritingClasses(@NotNull PsiClass aClass,
@NotNull Collection<LineMarkerInfo> result) {
protected List<LineMarkerInfo> collectInheritingClasses(@NotNull PsiClass aClass) {
if (aClass.hasModifierProperty(PsiModifier.FINAL)) {
return;
return Collections.emptyList();
}
if (CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) {
return Collections.emptyList(); // It's useless to have overridden markers for object.
}
if (CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) return; // It's useless to have overridden markers for object.
PsiClass subClass = DirectClassInheritorsSearch.search(aClass).findFirst();
if (subClass != null || FunctionalExpressionSearch.search(aClass).findFirst() != null) {
final Icon icon;
if (aClass.isInterface()) {
if (!myImplementedOption.isEnabled()) return;
if (!myImplementedOption.isEnabled()) return Collections.emptyList();
icon = AllIcons.Gutter.ImplementedMethod;
}
else {
if (!myOverriddenOption.isEnabled()) return;
if (!myOverriddenOption.isEnabled()) return Collections.emptyList();
icon = AllIcons.Gutter.OverridenMethod;
}
PsiElement range = aClass.getNameIdentifier();
@@ -244,12 +260,13 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
type.getNavigationHandler(),
GutterIconRenderer.Alignment.RIGHT);
NavigateAction.setNavigateAction(info, aClass.isInterface() ? "Go to implementation(s)" : "Go to subclass(es)", IdeActions.ACTION_GOTO_IMPLEMENTATION);
result.add(info);
return Collections.singletonList(info);
}
return Collections.emptyList();
}
private void collectOverridingMethods(@NotNull final Collection<PsiMethod> methods, @NotNull Collection<LineMarkerInfo> result) {
if (!myOverriddenOption.isEnabled() && !myImplementedOption.isEnabled()) return;
private List<LineMarkerInfo> collectOverridingMethods(@NotNull final Collection<PsiMethod> methods) {
if (!myOverriddenOption.isEnabled() && !myImplementedOption.isEnabled()) return Collections.emptyList();
final Set<PsiMethod> overridden = new HashSet<>();
Set<PsiClass> methodContainingClasses = new THashSet<>();
for (PsiMethod method : methods) {
@@ -283,14 +300,15 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
}
}
List<LineMarkerInfo> result = new ArrayList<>();
for (PsiMethod method : overridden) {
ProgressManager.checkCanceled();
boolean overrides = !method.hasModifierProperty(PsiModifier.ABSTRACT);
if (overrides) {
if (!myOverriddenOption.isEnabled()) return;
if (!myOverriddenOption.isEnabled()) return Collections.emptyList();
}
else {
if (!myImplementedOption.isEnabled()) return;
if (!myImplementedOption.isEnabled()) return Collections.emptyList();
}
PsiElement range = getMethodRange(method);
final MarkerType type = MarkerType.OVERRIDDEN_METHOD;
@@ -302,6 +320,7 @@ public class JavaLineMarkerProvider extends LineMarkerProviderDescriptor {
NavigateAction.setNavigateAction(info, overrides ? "Go to overriding methods" : "Go to implementation(s)", IdeActions.ACTION_GOTO_IMPLEMENTATION);
result.add(info);
}
return result;
}
@Override