diff --git a/java/java-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java index 24d624ff2920..9b1f92c478d5 100644 --- a/java/java-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java +++ b/java/java-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java @@ -21,11 +21,13 @@ import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.scope.PsiConflictResolver; import com.intellij.psi.util.*; -import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; +import gnu.trove.TIntArrayList; -import java.util.*; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; /** * Created by IntelliJ IDEA. @@ -37,15 +39,10 @@ import java.util.*; public class JavaMethodsConflictResolver implements PsiConflictResolver{ private final PsiElement myArgumentsList; private final PsiType[] myActualParameterTypes; - private static final Function EXPRESSION_TO_TYPE = new Function() { - public PsiType fun(final PsiExpression expression) { - return expression.getType(); - } - }; public JavaMethodsConflictResolver(PsiExpressionList list) { myArgumentsList = list; - myActualParameterTypes = ContainerUtil.map2Array(list.getExpressions(), PsiType.class, EXPRESSION_TO_TYPE); + myActualParameterTypes = list.getExpressionTypes(); } public JavaMethodsConflictResolver(final PsiElement argumentsList, final PsiType[] actualParameterTypes) { @@ -53,11 +50,10 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ myActualParameterTypes = actualParameterTypes; } - public CandidateInfo resolveConflict(List conflicts){ - if (conflicts.isEmpty()) return null; + public CandidateInfo resolveConflict(List conflicts){ if (conflicts.isEmpty()) return null; if (conflicts.size() == 1) return conflicts.get(0); - checkParametersNumber(conflicts, myActualParameterTypes.length, true); + boolean atLeastOneMatch = checkParametersNumber(conflicts, myActualParameterTypes.length, true); if (conflicts.size() == 1) return conflicts.get(0); checkSameSignatures(conflicts); @@ -72,6 +68,10 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ final int applicabilityLevel = checkApplicability(conflicts); if (conflicts.size() == 1) return conflicts.get(0); + // makes no sense to do further checks, because if no one candidate matches by parameters count + // then noone can be more specific + if (!atLeastOneMatch) return null; + checkSpecifics(conflicts, applicabilityLevel); if (conflicts.size() == 1) return conflicts.get(0); @@ -199,32 +199,40 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ return ((MethodCandidateInfo)info).isApplicable(); } - private static void checkParametersNumber(final List conflicts, + private static boolean checkParametersNumber(final List conflicts, final int argumentsCount, - boolean checkForStaticAccessProblem) { - boolean parametersNumberMatch = false; - for (CandidateInfo info : conflicts) { - if (checkForStaticAccessProblem && !info.isStaticsScopeCorrect()) return; - if (info instanceof MethodCandidateInfo) { - final PsiMethod method = ((MethodCandidateInfo)info).getElement(); - if (method.isVarArgs()) return; - if (method.getParameterList().getParametersCount() == argumentsCount) { - parametersNumberMatch = true; + boolean ignoreIfStaticsProblem) { + boolean atLeastOneMatch = false; + TIntArrayList unmatchedIndices = null; + for (int i = 0; i < conflicts.size(); i++) { + CandidateInfo info = conflicts.get(i); + if (ignoreIfStaticsProblem && !info.isStaticsScopeCorrect()) return true; + if (!(info instanceof MethodCandidateInfo)) continue; + PsiMethod method = ((MethodCandidateInfo)info).getElement(); + if (method.isVarArgs()) return true; + if (method.getParameterList().getParametersCount() == argumentsCount) { + // remove all unmatched before + if (unmatchedIndices != null) { + for (int u=unmatchedIndices.size()-1; u>=0; u--) { + int index = unmatchedIndices.get(u); + conflicts.remove(index); + i--; + } + unmatchedIndices = null; } + atLeastOneMatch = true; + } + else if (atLeastOneMatch) { + conflicts.remove(i); + i--; + } + else { + if (unmatchedIndices == null) unmatchedIndices = new TIntArrayList(conflicts.size()-i); + unmatchedIndices.add(i); } } - if (parametersNumberMatch) { - for (Iterator iterator = conflicts.iterator(); iterator.hasNext();) { - CandidateInfo info = iterator.next(); - if (info instanceof MethodCandidateInfo) { - final PsiMethod method = ((MethodCandidateInfo)info).getElement(); - if (method.getParameterList().getParametersCount() != argumentsCount) { - iterator.remove(); - } - } - } - } + return atLeastOneMatch; } private static int checkApplicability(List conflicts) {