usage view group speed optimisation

This commit is contained in:
Alexey Kudravtsev
2011-04-05 17:54:07 +04:00
parent f77616df3a
commit f937991590
3 changed files with 112 additions and 27 deletions
@@ -23,6 +23,7 @@ import com.intellij.psi.search.searches.DeepestSuperMethodsSearch;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.*;
import com.intellij.util.NotNullFunction;
import com.intellij.util.Processor;
import com.intellij.util.SmartList;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
@@ -314,6 +315,52 @@ public class PsiSuperMethodImplUtil {
}
// uses hierarchy signature tree if available, traverses class structure by itself otherwise
public static boolean processDirectSuperMethodsSmart(@NotNull PsiMethod method, @NotNull Processor<PsiMethod> superMethodProcessor) {
//boolean old = PsiSuperMethodUtil.isSuperMethod(method, superMethod);
PsiClass aClass = method.getContainingClass();
if (aClass == null) return false;
if (!canHaveSuperMethod(method, true, false)) return false;
Map<MethodSignature, HierarchicalMethodSignature> cachedMap = SIGNATURES_KEY.getCachedValueOrNull(aClass);
if (cachedMap != null) {
HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY));
if (signature != null) {
List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
for (HierarchicalMethodSignature superSignature : superSignatures) {
if (!superMethodProcessor.process(superSignature.getMethod())) return false;
}
return true;
}
}
PsiClassType[] directSupers = aClass.getSuperTypes();
for (PsiClassType directSuper : directSupers) {
PsiClassType.ClassResolveResult resolveResult = directSuper.resolveGenerics();
if (resolveResult.getSubstitutor() != PsiSubstitutor.EMPTY) {
// generics
break;
}
PsiClass directSuperClass = resolveResult.getElement();
if (directSuperClass == null) continue;
PsiMethod[] candidates = directSuperClass.findMethodsBySignature(method, false);
for (PsiMethod candidate : candidates) {
if (PsiUtil.canBeOverriden(candidate)) {
if (!superMethodProcessor.process(candidate)) return false;
}
}
return true;
}
List<HierarchicalMethodSignature> superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures();
for (HierarchicalMethodSignature superSignature : superSignatures) {
if (!superMethodProcessor.process(superSignature.getMethod())) return false;
}
return true;
}
// uses hierarchy signature tree if available, traverses class structure by itself otherwise
public static boolean isSuperMethodSmart(@NotNull PsiMethod method, @NotNull PsiMethod superMethod) {
//boolean old = PsiSuperMethodUtil.isSuperMethod(method, superMethod);
@@ -6,36 +6,35 @@ import com.intellij.util.QueryExecutor;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* @author peter
*/
public class MethodDeepestSuperSearcher implements QueryExecutor<PsiMethod, PsiMethod> {
public boolean execute(@NotNull final PsiMethod method, @NotNull final Processor<PsiMethod> consumer) {
final Set<PsiMethod> methods = new LinkedHashSet<PsiMethod>();
findDeepestSuperOrSelfSignature(method, methods, null);
for (final PsiMethod psiMethod : methods) {
if (psiMethod != method && !consumer.process(psiMethod)) {
return false;
public boolean execute(@NotNull PsiMethod method, @NotNull Processor<PsiMethod> consumer) {
final Set<PsiMethod> methods = new THashSet<PsiMethod>();
methods.add(method);
return findDeepestSuperOrSelfSignature(method, methods, null, consumer);
}
private static boolean findDeepestSuperOrSelfSignature(PsiMethod method,
Set<PsiMethod> set,
Set<PsiMethod> guard,
Processor<PsiMethod> processor) {
if (guard != null && !guard.add(method)) return true;
PsiMethod[] supers = method.findSuperMethods();
if (supers.length == 0 && set.add(method) && !processor.process(method)) {
return false;
}
for (PsiMethod superMethod : supers) {
if (guard == null) {
guard = new THashSet<PsiMethod>();
guard.add(method);
}
if (!findDeepestSuperOrSelfSignature(superMethod, set, guard, processor)) return false;
}
return true;
}
private static void findDeepestSuperOrSelfSignature(PsiMethod method, final Set<PsiMethod> set, Set<PsiMethod> guard) {
if (guard != null && !guard.add(method)) return;
PsiMethod[] supers = method.findSuperMethods();
if (supers.length == 0) {
set.add(method);
}
else {
for (PsiMethod superMethod : supers) {
if (guard == null) guard = new THashSet<PsiMethod>();
findDeepestSuperOrSelfSignature(superMethod, set, guard);
}
}
}
}
@@ -16,13 +16,17 @@
package com.intellij.usages.impl.rules;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiSuperMethodImplUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.Processor;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Set;
/**
* @author yole
@@ -51,6 +55,9 @@ public class JavaUsageTypeProvider implements UsageTypeProvider {
if (p instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)p;
final PsiMethod calledMethod = callExpression.resolveMethod();
if (calledMethod == containerMethod) {
return UsageType.RECURSION;
}
if (qualifier != null && !(qualifier instanceof PsiThisExpression) && calledMethod != null) {
if (haveCommonSuperMethod(containerMethod, calledMethod)) {
boolean parametersDelegated = parametersDelegated(containerMethod, callExpression);
@@ -63,9 +70,6 @@ public class JavaUsageTypeProvider implements UsageTypeProvider {
}
}
}
else if (calledMethod == containerMethod) {
return UsageType.RECURSION;
}
}
}
}
@@ -94,6 +98,40 @@ public class JavaUsageTypeProvider implements UsageTypeProvider {
}
private static boolean haveCommonSuperMethod(@NotNull PsiMethod m1, @NotNull PsiMethod m2) {
final Queue<PsiMethod> supers1Q = new ArrayDeque<PsiMethod>(); supers1Q.add(m1);
final Queue<PsiMethod> supers2Q = new ArrayDeque<PsiMethod>(); supers2Q.add(m1);
Set<PsiMethod> supers1 = new THashSet<PsiMethod>();
Set<PsiMethod> supers2 = new THashSet<PsiMethod>();
while (true) {
PsiMethod me1;
if ((me1 = supers1Q.poll()) != null) {
if (supers2.contains(me1)) return true;
supers1.add(me1);
PsiSuperMethodImplUtil.processDirectSuperMethodsSmart(me1, new Processor<PsiMethod>() {
@Override
public boolean process(PsiMethod psiMethod) {
supers1Q.add(psiMethod);
return true;
}
});
}
PsiMethod me2;
if ((me2 = supers2Q.poll()) != null) {
if (supers1.contains(me2)) return true;
supers2.add(me2);
PsiSuperMethodImplUtil.processDirectSuperMethodsSmart(me2, new Processor<PsiMethod>() {
@Override
public boolean process(PsiMethod psiMethod) {
supers2Q.add(psiMethod);
return true;
}
});
}
if (me1 == null && me2==null) break;
}
return false;
/*
HashSet<PsiMethod> s1 = new HashSet<PsiMethod>(Arrays.asList(m1.findDeepestSuperMethods()));
s1.add(m1);
@@ -102,6 +140,7 @@ public class JavaUsageTypeProvider implements UsageTypeProvider {
s1.retainAll(s2);
return !s1.isEmpty();
*/
}
@Nullable