optimizations for find usages of method with common name

This commit is contained in:
Alexey Kudravtsev
2011-03-24 15:02:06 +03:00
parent 79374b4c60
commit 8f3551bcae
5 changed files with 131 additions and 33 deletions
@@ -78,8 +78,8 @@ public class PsiSuperMethodImplUtil {
@NotNull
private static List<MethodSignatureBackedByPsiMethod> findSuperMethodSignatures(PsiMethod method,
PsiClass parentClass,
boolean allowStaticMethod) {
PsiClass parentClass,
boolean allowStaticMethod) {
return new ArrayList<MethodSignatureBackedByPsiMethod>(SuperMethodsSearch.search(method, parentClass, true, allowStaticMethod).findAll());
}
@@ -306,4 +306,58 @@ public class PsiSuperMethodImplUtil {
private static Map<MethodSignature, HierarchicalMethodSignature> getSignaturesMap(final PsiClass aClass) {
return SIGNATURES_KEY.getValue(aClass);
}
// 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);
if (method == superMethod) return false;
PsiClass aClass = method.getContainingClass();
PsiClass superClass = superMethod.getContainingClass();
if (aClass == null || superClass == null || superClass == aClass) return false;
if (!canHaveSuperMethod(method, true, false)) return false;
PsiMethod[] superMethods = null;
Map<MethodSignature, HierarchicalMethodSignature> cachedMap = SIGNATURES_KEY.getCachedValueOrNull(aClass);
if (cachedMap != null) {
HierarchicalMethodSignature signature = cachedMap.get(method.getSignature(PsiSubstitutor.EMPTY));
if (signature != null) {
superMethods = MethodSignatureUtil.convertMethodSignaturesToMethods(signature.getSuperSignatures());
}
}
if (superMethods == null) {
PsiClassType[] directSupers = aClass.getSuperTypes();
List<PsiMethod> found = null;
boolean canceled = false;
for (PsiClassType directSuper : directSupers) {
PsiClassType.ClassResolveResult resolveResult = directSuper.resolveGenerics();
if (resolveResult.getSubstitutor() != PsiSubstitutor.EMPTY) {
// generics
canceled = true;
break;
}
PsiClass directSuperClass = resolveResult.getElement();
if (directSuperClass == null) continue;
PsiMethod[] candidates = directSuperClass.findMethodsBySignature(method, false);
if (candidates.length != 0) {
if (found == null) found = new ArrayList<PsiMethod>();
for (PsiMethod candidate : candidates) {
if (PsiUtil.canBeOverriden(candidate)) found.add(candidate);
}
}
}
superMethods = canceled ? null : found == null ? PsiMethod.EMPTY_ARRAY : found.toArray(new PsiMethod[found.size()]);
}
if (superMethods == null) {
superMethods = MethodSignatureUtil.convertMethodSignaturesToMethods(method.getHierarchicalMethodSignature().getSuperSignatures());
}
for (PsiMethod superCandidate : superMethods) {
if (superMethod.equals(superCandidate) || isSuperMethodSmart(superCandidate, superMethod)) return true;
}
return false;
}
}
@@ -332,6 +332,7 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
public boolean isReferenceTo(PsiElement element) {
IElementType i = getLastChildNode().getElementType();
boolean resolvingToMethod = element instanceof PsiMethod;
if (i == JavaTokenType.IDENTIFIER) {
if (!(element instanceof PsiPackage)) {
if (!(element instanceof PsiNamedElement)) return false;
@@ -341,10 +342,15 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
}
}
else if (i == JavaTokenType.SUPER_KEYWORD || i == JavaTokenType.THIS_KEYWORD) {
if (!(element instanceof PsiMethod)) return false;
if (!resolvingToMethod) return false;
if (!((PsiMethod)element).isConstructor()) return false;
}
PsiElement parent = getParent();
boolean parentIsMethodCall = parent instanceof PsiMethodCallExpression;
// optimization: methodCallExpression should resolve to a method
if (parentIsMethodCall != resolvingToMethod) return false;
return element.getManager().areElementsEquivalent(element, resolve());
}
@@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiSuperMethodImplUtil;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.PsiConflictResolver;
@@ -150,7 +151,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
if (!method.hasModifierProperty(PsiModifier.STATIC)) {
for (int k=i-1; k>=0; k--) {
PsiMethod existingMethod = (PsiMethod)conflicts.get(k).getElement();
if (PsiSuperMethodUtil.isSuperMethod(existingMethod, method)) {
if (PsiSuperMethodImplUtil.isSuperMethodSmart(existingMethod, method)) {
conflicts.remove(i);
i--;
continue nextConflict;
@@ -189,12 +190,12 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
// filter out methods with incorrect inferred bounds (for unrelated methods only)
boolean existingTypeParamAgree = areTypeParametersAgree(existing);
boolean infoTypeParamAgree = areTypeParametersAgree(info);
if (existingTypeParamAgree && !infoTypeParamAgree && !PsiSuperMethodUtil.isSuperMethod(method, existingMethod)) {
if (existingTypeParamAgree && !infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(method, existingMethod)) {
conflicts.remove(i);
i--;
continue;
}
else if (!existingTypeParamAgree && infoTypeParamAgree && !PsiSuperMethodUtil.isSuperMethod(existingMethod, method)) {
else if (!existingTypeParamAgree && infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(existingMethod, method)) {
signatures.put(signature, info);
int index = conflicts.indexOf(existing);
conflicts.remove(index);