faster overriding method search

This commit is contained in:
peter
2015-06-03 10:21:31 +02:00
parent 4400bf00b7
commit 2846f01914
2 changed files with 45 additions and 29 deletions
@@ -28,11 +28,9 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* @author ven
*/
@@ -41,13 +39,14 @@ public class JavaAllOverridingMethodsSearcher implements QueryExecutor<Pair<PsiM
public boolean execute(@NotNull final AllOverridingMethodsSearch.SearchParameters p, @NotNull final Processor<Pair<PsiMethod, PsiMethod>> consumer) {
final PsiClass psiClass = p.getPsiClass();
final List<PsiMethod> methods = ApplicationManager.getApplication().runReadAction(new Computable<List<PsiMethod>>() {
final MultiMap<String, PsiMethod> methods = ApplicationManager.getApplication().runReadAction(new Computable<MultiMap<String, PsiMethod>>() {
@Override
public List<PsiMethod> compute() {
PsiMethod[] methodsArray = psiClass.getMethods();
final List<PsiMethod> methods = new ArrayList<PsiMethod>(methodsArray.length);
for (PsiMethod method : methodsArray) {
if (PsiUtil.canBeOverriden(method)) methods.add(method);
public MultiMap<String, PsiMethod> compute() {
final MultiMap<String, PsiMethod> methods = MultiMap.create();
for (PsiMethod method : psiClass.getMethods()) {
if (PsiUtil.canBeOverriden(method)) {
methods.putValue(method.getName(), method);
}
}
return methods;
}
@@ -59,17 +58,27 @@ public class JavaAllOverridingMethodsSearcher implements QueryExecutor<Pair<PsiM
Processor<PsiClass> inheritorsProcessor = new Processor<PsiClass>() {
@Override
public boolean process(PsiClass inheritor) {
//could be null if not java inheritor, TODO only JavaClassInheritors are needed
PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(psiClass, inheritor, PsiSubstitutor.EMPTY);
if (substitutor == null) return true;
PsiSubstitutor substitutor = null;
for (String name : methods.keySet()) {
if (inheritor.findMethodsByName(name, false).length == 0) continue;
for (PsiMethod method : methods.get(name)) {
if (method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) &&
!JavaPsiFacade.getInstance(inheritor.getProject()).arePackagesTheSame(psiClass, inheritor)) continue;
if (substitutor == null) {
//could be null if not java inheritor, TODO only JavaClassInheritors are needed
substitutor = TypeConversionUtil.getClassSubstitutor(psiClass, inheritor, PsiSubstitutor.EMPTY);
if (substitutor == null) return true;
}
MethodSignature signature = method.getSignature(substitutor);
PsiMethod inInheritor = MethodSignatureUtil.findMethodBySuperSignature(inheritor, signature, false);
if (inInheritor != null && !inInheritor.hasModifierProperty(PsiModifier.STATIC)) {
if (!consumer.process(Pair.create(method, inInheritor))) return false;
}
for (PsiMethod method : methods) {
if (method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) &&
!JavaPsiFacade.getInstance(inheritor.getProject()).arePackagesTheSame(psiClass, inheritor)) continue;
MethodSignature signature = method.getSignature(substitutor);
PsiMethod inInheritor = MethodSignatureUtil.findMethodBySuperSignature(inheritor, signature, false);
if (inInheritor == null || inInheritor.hasModifierProperty(PsiModifier.STATIC)) {
if (psiClass.isInterface() && !inheritor.isInterface()) { //check for sibling implementation
final PsiClass superClass = inheritor.getSuperClass();
if (superClass != null && !superClass.isInheritor(psiClass, true)) {
@@ -79,9 +88,7 @@ public class JavaAllOverridingMethodsSearcher implements QueryExecutor<Pair<PsiM
}
}
}
continue;
}
if (!consumer.process(Pair.create(method, inInheritor))) return false;
}
return true;
@@ -50,18 +50,18 @@ public class JavaOverridingMethodsSearcher implements QueryExecutor<PsiMethod, O
@Nullable
private static PsiMethod findOverridingMethod(PsiClass inheritor, @NotNull PsiClass parentClass, PsiMethod method) {
PsiSubstitutor substitutor = inheritor.isInheritor(parentClass, true) ?
TypeConversionUtil.getSuperClassSubstitutor(parentClass, inheritor, PsiSubstitutor.EMPTY) :
PsiSubstitutor.EMPTY;
MethodSignature signature = method.getSignature(substitutor);
PsiMethod found = MethodSignatureUtil.findMethodBySuperSignature(inheritor, signature, false);
if (found != null && isAcceptable(found, method)) {
return found;
String name = method.getName();
if (inheritor.findMethodsByName(name, false).length > 0) {
PsiMethod found = MethodSignatureUtil.findMethodBySuperSignature(inheritor, getSuperSignature(inheritor, parentClass, method), false);
if (found != null && isAcceptable(found, method)) {
return found;
}
}
if (parentClass.isInterface() && !inheritor.isInterface()) { //check for sibling implementation
final PsiClass superClass = inheritor.getSuperClass();
if (superClass != null && !superClass.isInheritor(parentClass, true)) {
if (superClass != null && !superClass.isInheritor(parentClass, true) && superClass.findMethodsByName(name, true).length > 0) {
MethodSignature signature = getSuperSignature(inheritor, parentClass, method);
PsiMethod derived = MethodSignatureUtil.findMethodInSuperClassBySignatureInDerived(inheritor, superClass, signature, true);
if (derived != null && isAcceptable(derived, method)) {
return derived;
@@ -71,6 +71,15 @@ public class JavaOverridingMethodsSearcher implements QueryExecutor<PsiMethod, O
return null;
}
@NotNull
private static MethodSignature getSuperSignature(PsiClass inheritor, @NotNull PsiClass parentClass, PsiMethod method) {
PsiSubstitutor substitutor = inheritor.isInheritor(parentClass, true) ?
TypeConversionUtil.getSuperClassSubstitutor(parentClass, inheritor, PsiSubstitutor.EMPTY) :
PsiSubstitutor.EMPTY;
return method.getSignature(substitutor);
}
private static boolean isAcceptable(final PsiMethod found, final PsiMethod method) {
return !found.hasModifierProperty(PsiModifier.STATIC) &&
(!method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) ||