From 061c17f9766e16f7955c8bdee289fb1a015ad31f Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 23 Nov 2015 16:07:58 +0100 Subject: [PATCH] overload resolution: don't calculate types to check if (un)boxing took place, formal types are enough --- .../psi/infos/MethodCandidateInfo.java | 8 --- .../graphInference/PsiPolyExpressionUtil.java | 23 ++++++++ .../JavaMethodsConflictResolver.java | 56 ++++++++----------- 3 files changed, 46 insertions(+), 41 deletions(-) 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 8184484f4a7d..b72aeeae8f18 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 @@ -208,14 +208,6 @@ public class MethodCandidateInfo extends CandidateInfo{ return true; } - public PsiType[] getPertinentArgumentTypes() { - return computeForOverloadedCandidate(new Computable() { - public PsiType[] compute() { - return getArgumentTypes(); - } - }, getSubstitutor(false)); - } - private T computeForOverloadedCandidate(final Computable computable, final PsiSubstitutor substitutor) { Map map = CURRENT_CANDIDATE.get(); if (map == null) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java index dea85ffd2af7..d62f29b8b336 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java @@ -152,6 +152,29 @@ public class PsiPolyExpressionUtil { context instanceof PsiLambdaExpression; } + public static boolean isExpressionOfPrimitiveType(@Nullable PsiExpression arg) { + if (arg != null && !isPolyExpression(arg)) { + return arg.getType() instanceof PsiPrimitiveType; + } + else if (arg instanceof PsiNewExpression || arg instanceof PsiFunctionalExpression) { + return false; + } + else if (arg instanceof PsiParenthesizedExpression) { + return isExpressionOfPrimitiveType(((PsiParenthesizedExpression)arg).getExpression()); + } + else if (arg instanceof PsiConditionalExpression) { + return isBooleanOrNumeric(arg) != null; + } + else if (arg instanceof PsiMethodCallExpression) { + final PsiMethod method = ((PsiMethodCallExpression)arg).resolveMethod(); + return method != null && method.getReturnType() instanceof PsiPrimitiveType; + } + else { + assert false : arg; + return false; + } + } + private enum ConditionalKind { BOOLEAN, NUMERIC } 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 3fa26842dece..8a22ce5ef129 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 @@ -26,6 +26,7 @@ import com.intellij.psi.*; import com.intellij.psi.impl.PsiSuperMethodImplUtil; import com.intellij.psi.impl.source.PsiImmediateClassType; import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession; +import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.scope.PsiConflictResolver; @@ -523,14 +524,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ NEITHER } - private static boolean isBoxingHappened(PsiType argType, PsiType parameterType, @NotNull LanguageLevel languageLevel) { - if (parameterType instanceof PsiClassType) { - parameterType = ((PsiClassType)parameterType).setLanguageLevel(languageLevel); - } - - return argType != null && TypeConversionUtil.boxingConversionApplicable(parameterType, argType); - } - private Specifics isMoreSpecific(@NotNull MethodCandidateInfo info1, @NotNull MethodCandidateInfo info2, @MethodCandidateInfo.ApplicabilityLevelConstant int applicabilityLevel, @@ -579,31 +572,31 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ } boolean sameBoxing = true; - int[] boxingHappened = new int[2]; - final PsiType[] argTypes1 = myActualParameterTypes != null ? myActualParameterTypes : info1.getPertinentArgumentTypes(); - final PsiType[] argTypes2 = myActualParameterTypes != null ? myActualParameterTypes : info2.getPertinentArgumentTypes(); + boolean[] boxingHappened = new boolean [2]; + + final PsiExpression[] args = myArgumentsList instanceof PsiExpressionList ? ((PsiExpressionList)myArgumentsList).getExpressions() : null; + for (int i = 0; i < types1.length; i++) { ProgressManager.checkCanceled(); - PsiType type1 = classSubstitutor1.substitute(types1[i]); - PsiType type2 = classSubstitutor2.substitute(types2[i]); - final PsiType argType1 = i < getActualParametersLength() ? argTypes1[i] : null; - final PsiType argType2 = i < getActualParametersLength() ? argTypes2[i] : null; + final PsiExpression arg = args != null && i < args.length ? args[i] : null; + final PsiType argType = myActualParameterTypes != null && i < getActualParametersLength() ? myActualParameterTypes[i] : null; + if (arg == null && argType == null) continue; boolean boxingInFirst = false; - if (isBoxingHappened(argType1, type1, languageLevel)) { - boxingHappened[0] += 1; + if (isBoxingUsed(classSubstitutor1.substitute(types1[i]), argType, arg)) { + boxingHappened[0] |= true; boxingInFirst = true; } boolean boxingInSecond = false; - if (isBoxingHappened(argType2, type2, languageLevel)) { - boxingHappened[1] += 1; + if (isBoxingUsed(classSubstitutor2.substitute(types2[i]), argType, arg)) { + boxingHappened[1] |= true; boxingInSecond = true; } sameBoxing &= boxingInFirst == boxingInSecond; } - if (boxingHappened[0] == 0 && boxingHappened[1] > 0) return Specifics.FIRST; - if (boxingHappened[0] > 0 && boxingHappened[1] == 0) return Specifics.SECOND; + if (!boxingHappened[0] && boxingHappened[1]) return Specifics.FIRST; + if (boxingHappened[0] && !boxingHappened[1]) return Specifics.SECOND; if (sameBoxing) { final PsiSubstitutor siteSubstitutor1 = info1.getSiteSubstitutor(); @@ -698,14 +691,21 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ return Specifics.NEITHER; } + private static boolean isBoxingUsed(PsiType parameterType, @Nullable PsiType argType, PsiExpression arg) { + ProgressManager.checkCanceled(); + final boolean isExpressionTypePrimitive = argType != null ? argType instanceof PsiPrimitiveType + : PsiPolyExpressionUtil.isExpressionOfPrimitiveType(arg); + return parameterType instanceof PsiPrimitiveType ^ isExpressionTypePrimitive; + } + private static boolean isSubSignature(PsiMethod method1, PsiMethod method2, PsiSubstitutor classSubstitutor1, PsiSubstitutor classSubstitutor2, - int[] boxingHappened) { + boolean[] boxingHappened) { return MethodSignatureUtil.areErasedParametersEqual(method1.getSignature(PsiSubstitutor.EMPTY), method2.getSignature(PsiSubstitutor.EMPTY)) && MethodSignatureUtil.isSubsignature(method1.getSignature(classSubstitutor1), method2.getSignature(classSubstitutor2)) || - method1.hasModifierProperty(PsiModifier.STATIC) && method2.hasModifierProperty(PsiModifier.STATIC) && boxingHappened[0] == 0; + method1.hasModifierProperty(PsiModifier.STATIC) && method2.hasModifierProperty(PsiModifier.STATIC) && !boxingHappened[0]; } private boolean isApplicableTo(@NotNull PsiType[] types2AtSite, @@ -833,16 +833,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ } } - @Nullable - private static PsiType getFunctionalType(int functionalTypeIdx, @NotNull CandidateInfo candidateInfo) { - final PsiMethod psiMethod = (PsiMethod)candidateInfo.getElement(); - LOG.assertTrue(true); - final PsiParameter[] methodParameters = psiMethod.getParameterList().getParameters(); - if (methodParameters.length == 0) return null; - final PsiParameter param = functionalTypeIdx < methodParameters.length ? methodParameters[functionalTypeIdx] : methodParameters[methodParameters.length - 1]; - return ((MethodCandidateInfo)candidateInfo).getSiteSubstitutor().substitute(param.getType()); - } - @NotNull private static Specifics isFunctionalTypeMoreSpecific(PsiExpression expr, PsiType sType, PsiType tType) { if (expr instanceof PsiParenthesizedExpression) {