From 3546317c4dc87bfe3e30f01cd16d5eb5adaa5b15 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 6 Nov 2013 12:21:47 +0100 Subject: [PATCH] new overload resolution --- .../intellij/psi/PsiMethodReferenceUtil.java | 5 +++++ .../intellij/psi/infos/MethodCandidateInfo.java | 17 +++++++++++++++++ .../JavaMethodsConflictResolver.java | 8 ++++---- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java index 9bbb84e83020..f5f0bf96d95b 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java @@ -18,6 +18,7 @@ package com.intellij.psi; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.util.*; import com.intellij.util.Function; import com.sun.tools.javac.code.Kinds; @@ -163,6 +164,10 @@ public class PsiMethodReferenceUtil { public static boolean isAcceptable(@Nullable final PsiMethodReferenceExpression methodReferenceExpression, PsiType left) { if (methodReferenceExpression == null) return false; + final PsiElement argsList = PsiTreeUtil.getParentOfType(methodReferenceExpression, PsiExpressionList.class); + if (MethodCandidateInfo.ourOverloadGuard.currentStack().contains(argsList)) { + if (!methodReferenceExpression.isExact()) return true; + } if (left instanceof PsiIntersectionType) { for (PsiType conjunct : ((PsiIntersectionType)left).getConjuncts()) { if (isAcceptable(methodReferenceExpression, conjunct)) return true; diff --git a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java index 3a0bfddaf36f..8e4a13026514 100644 --- a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java +++ b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java @@ -18,8 +18,10 @@ package com.intellij.psi.infos; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.JavaVersionService; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.RecursionGuard; +import com.intellij.openapi.util.RecursionManager; import com.intellij.openapi.util.registry.Registry; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; @@ -37,6 +39,7 @@ import java.util.Map; * @author ik, dsl */ public class MethodCandidateInfo extends CandidateInfo{ + public static final RecursionGuard ourOverloadGuard = RecursionManager.createGuard("overload.guard"); public static final ThreadLocal>> CURRENT_CANDIDATE = new ThreadLocal>>(); @ApplicabilityLevelConstant private int myApplicabilityLevel = 0; private final PsiElement myArgumentList; @@ -95,6 +98,20 @@ public class MethodCandidateInfo extends CandidateInfo{ return myApplicabilityLevel; } + @ApplicabilityLevelConstant + public int getPertinentApplicabilityLevel() { + final PsiMethod method = getElement(); + if (method != null && method.hasTypeParameters() || myArgumentList == null || !PsiUtil.isLanguageLevel8OrHigher(myArgumentList)) { + return getApplicabilityLevel(); + } + return ourOverloadGuard.doPreventingRecursion(myArgumentList, false, new Computable() { + @Override + public Integer compute() { + return getApplicabilityLevelInner(); + } + }); + } + public PsiSubstitutor getSiteSubstitutor() { return super.getSubstitutor(); } diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java index 084ad32c5d56..224185117c4f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java @@ -394,7 +394,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ for (Iterator iterator = conflicts.iterator(); iterator.hasNext();) { ProgressManager.checkCanceled(); CandidateInfo info = iterator.next(); - final int level = preferVarargs(info); + final int level = preferVarargs((MethodCandidateInfo)info); if (level < maxApplicabilityLevel) { iterator.remove(); } @@ -404,10 +404,10 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ return maxApplicabilityLevel; } - private static int preferVarargs(CandidateInfo info) { - final int level = ((MethodCandidateInfo)info).getApplicabilityLevel(); + private static int preferVarargs(MethodCandidateInfo info) { + final int level = info.getPertinentApplicabilityLevel(); if (level == MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY) { - final PsiMethod psiMethod = (PsiMethod)info.getElement(); + final PsiMethod psiMethod = info.getElement(); if (psiMethod != null && psiMethod.isVarArgs() && JavaVersionService.getInstance().isAtLeast(psiMethod, JavaSdkVersion.JDK_1_7)) { return level + 1; }