From f937991590beff04f6dba20ce9a2d4bcd4f3e4c7 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 5 Apr 2011 11:47:21 +0400 Subject: [PATCH] usage view group speed optimisation --- .../psi/impl/PsiSuperMethodImplUtil.java | 47 ++++++++++++++++++ .../search/MethodDeepestSuperSearcher.java | 43 ++++++++-------- .../impl/rules/JavaUsageTypeProvider.java | 49 +++++++++++++++++-- 3 files changed, 112 insertions(+), 27 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java index 06909b936df0..170a40d624c2 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java @@ -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 superMethodProcessor) { + //boolean old = PsiSuperMethodUtil.isSuperMethod(method, superMethod); + + PsiClass aClass = method.getContainingClass(); + if (aClass == null) return false; + + if (!canHaveSuperMethod(method, true, false)) return false; + + Map cachedMap = SIGNATURES_KEY.getCachedValueOrNull(aClass); + if (cachedMap != null) { + HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY)); + if (signature != null) { + List 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 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); diff --git a/java/java-impl/src/com/intellij/psi/impl/search/MethodDeepestSuperSearcher.java b/java/java-impl/src/com/intellij/psi/impl/search/MethodDeepestSuperSearcher.java index d076408b6475..1ca6f3b59abe 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/MethodDeepestSuperSearcher.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/MethodDeepestSuperSearcher.java @@ -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 { - public boolean execute(@NotNull final PsiMethod method, @NotNull final Processor consumer) { - final Set methods = new LinkedHashSet(); - 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 consumer) { + final Set methods = new THashSet(); + methods.add(method); + return findDeepestSuperOrSelfSignature(method, methods, null, consumer); + } + + private static boolean findDeepestSuperOrSelfSignature(PsiMethod method, + Set set, + Set guard, + Processor 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(); + guard.add(method); } + if (!findDeepestSuperOrSelfSignature(superMethod, set, guard, processor)) return false; } return true; } - - private static void findDeepestSuperOrSelfSignature(PsiMethod method, final Set set, Set 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(); - findDeepestSuperOrSelfSignature(superMethod, set, guard); - } - } - } } diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java index a18d81062410..23e09d131548 100644 --- a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java +++ b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java @@ -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 supers1Q = new ArrayDeque(); supers1Q.add(m1); + final Queue supers2Q = new ArrayDeque(); supers2Q.add(m1); + Set supers1 = new THashSet(); + Set supers2 = new THashSet(); + while (true) { + PsiMethod me1; + if ((me1 = supers1Q.poll()) != null) { + if (supers2.contains(me1)) return true; + supers1.add(me1); + PsiSuperMethodImplUtil.processDirectSuperMethodsSmart(me1, new Processor() { + @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() { + @Override + public boolean process(PsiMethod psiMethod) { + supers2Q.add(psiMethod); + return true; + } + }); + } + if (me1 == null && me2==null) break; + } + return false; + /* HashSet s1 = new HashSet(Arrays.asList(m1.findDeepestSuperMethods())); s1.add(m1); @@ -102,6 +140,7 @@ public class JavaUsageTypeProvider implements UsageTypeProvider { s1.retainAll(s2); return !s1.isEmpty(); + */ } @Nullable