From a70f8239c8de35f69fb0004373990fa128cc77e9 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 5 Mar 2014 19:43:13 +0100 Subject: [PATCH] new inference: postpone argument types calculation --- .../psi/infos/MethodCandidateInfo.java | 51 ++++++++++--------- .../JavaMethodsConflictResolver.java | 41 ++++++++++----- .../processor/MethodCandidatesProcessor.java | 7 ++- 3 files changed, 62 insertions(+), 37 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 2afc76a5d060..2831025839e3 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 @@ -82,9 +82,11 @@ public class MethodCandidateInfo extends CandidateInfo{ @ApplicabilityLevelConstant private int getApplicabilityLevelInner() { - if (myArgumentTypes == null) return ApplicabilityLevel.NOT_APPLICABLE; + final PsiType[] argumentTypes = getArgumentTypes(); - int level = PsiUtil.getApplicabilityLevel(getElement(), getSubstitutor(), myArgumentTypes, myLanguageLevel); + if (argumentTypes == null) return ApplicabilityLevel.NOT_APPLICABLE; + + int level = PsiUtil.getApplicabilityLevel(getElement(), getSubstitutor(), argumentTypes, myLanguageLevel); if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable()) level = ApplicabilityLevel.NOT_APPLICABLE; return level; } @@ -104,18 +106,17 @@ public class MethodCandidateInfo extends CandidateInfo{ return getApplicabilityLevel(); } - if (myArgumentTypes == null) { - return ApplicabilityLevel.NOT_APPLICABLE; - } - @ApplicabilityLevelConstant int level; Integer boxedLevel = ourOverloadGuard.doPreventingRecursion(myArgumentList, false, new Computable() { @Override public Integer compute() { - - final PsiMethod method = getElement(); - if (method != null && method.hasTypeParameters() || myArgumentList == null || !PsiUtil.isLanguageLevel8OrHigher(myArgumentList)) { - return PsiUtil.getApplicabilityLevel(getElement(), getSubstitutor(false), myArgumentTypes, myLanguageLevel); + if (PsiUtil.isLanguageLevel8OrHigher(myArgumentList)) { + final PsiType[] argumentTypes = getArgumentTypes(); + if (argumentTypes == null) { + return ApplicabilityLevel.NOT_APPLICABLE; + } + + return PsiUtil.getApplicabilityLevel(getElement(), getSubstitutor(false), argumentTypes, myLanguageLevel); } return getApplicabilityLevelInner(); } @@ -127,7 +128,17 @@ public class MethodCandidateInfo extends CandidateInfo{ } public PsiSubstitutor getSiteSubstitutor() { - return super.getSubstitutor(); + PsiSubstitutor incompleteSubstitutor = super.getSubstitutor(); + if (myTypeArguments != null) { + PsiMethod method = getElement(); + if (method != null) { + PsiTypeParameter[] typeParams = method.getTypeParameters(); + for (int i = 0; i < myTypeArguments.length && i < typeParams.length; i++) { + incompleteSubstitutor = incompleteSubstitutor.put(typeParams[i], myTypeArguments[i]); + } + } + } + return incompleteSubstitutor; } @NotNull @@ -206,22 +217,10 @@ public class MethodCandidateInfo extends CandidateInfo{ return inferTypeArguments(policy, arguments, true); } else { - return typeArgumentsSubstitutor(); + return getSiteSubstitutor(); } } - public PsiSubstitutor typeArgumentsSubstitutor() { - PsiSubstitutor incompleteSubstitutor = super.getSubstitutor(); - PsiMethod method = getElement(); - if (method != null) { - PsiTypeParameter[] typeParams = method.getTypeParameters(); - for (int i = 0; i < myTypeArguments.length && i < typeParams.length; i++) { - incompleteSubstitutor = incompleteSubstitutor.put(typeParams[i], myTypeArguments[i]); - } - } - return incompleteSubstitutor; - } - @NotNull public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy, @NotNull PsiExpression[] arguments, @@ -283,6 +282,10 @@ public class MethodCandidateInfo extends CandidateInfo{ } } + public PsiType[] getArgumentTypes() { + return myArgumentTypes; + } + public static class ApplicabilityLevel { public static final int NOT_APPLICABLE = 1; public static final int VARARGS = 2; 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 406abbf9ee7a..81cfc0ab4799 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 @@ -72,7 +72,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ if (conflicts.isEmpty()) return null; if (conflicts.size() == 1) return conflicts.get(0); - boolean atLeastOneMatch = checkParametersNumber(conflicts, getActualParameterTypes().length, true); + boolean atLeastOneMatch = checkParametersNumber(conflicts, getActualParametersLength(), true); if (conflicts.size() == 1) return conflicts.get(0); checkSameSignatures(conflicts); @@ -81,7 +81,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ checkAccessStaticLevels(conflicts, true); if (conflicts.size() == 1) return conflicts.get(0); - checkParametersNumber(conflicts, getActualParameterTypes().length, false); + checkParametersNumber(conflicts, getActualParametersLength(), false); if (conflicts.size() == 1) return conflicts.get(0); final int applicabilityLevel = checkApplicability(conflicts); @@ -97,7 +97,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ checkSpecifics(conflicts, applicabilityLevel, myLanguageLevel); if (conflicts.size() == 1) return conflicts.get(0); - checkPrimitiveVarargs(conflicts, getActualParameterTypes().length); + checkPrimitiveVarargs(conflicts, getActualParametersLength()); if (conflicts.size() == 1) return conflicts.get(0); checkAccessStaticLevels(conflicts, false); @@ -110,10 +110,19 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ private void checkLambdaApplicable(@NotNull List conflicts, @NotNull LanguageLevel languageLevel) { if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) return; - for (int i = 0; i < getActualParameterTypes().length; i++) { - PsiType parameterType = getActualParameterTypes()[i]; - if (parameterType instanceof PsiLambdaExpressionType) { - final PsiLambdaExpression lambdaExpression = ((PsiLambdaExpressionType)parameterType).getExpression(); + for (int i = 0; i < getActualParametersLength(); i++) { + + PsiExpression expression; + if (myArgumentsList instanceof PsiExpressionList) { + expression = ((PsiExpressionList)myArgumentsList).getExpressions()[i]; + } + else { + final PsiType argType = getActualParameterTypes()[i]; + expression = argType instanceof PsiLambdaExpressionType ? ((PsiLambdaExpressionType)argType).getExpression() : null; + } + + if (expression instanceof PsiLambdaExpression) { + final PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)expression; for (Iterator iterator = conflicts.iterator(); iterator.hasNext(); ) { ProgressManager.checkCanceled(); final CandidateInfo conflict = iterator.next(); @@ -411,6 +420,14 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ return myActualParameterTypes; } + private int getActualParametersLength() { + if (myActualParameterTypes == null) { + LOG.assertTrue(myArgumentsList instanceof PsiExpressionList, myArgumentsList); + return ((PsiExpressionList)myArgumentsList).getExpressions().length; + } + return myActualParameterTypes.length; + } + protected PsiType[] getArgumentTypes() { return ((PsiExpressionList)myArgumentsList).getExpressionTypes(); } @@ -500,8 +517,8 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ final PsiSubstitutor siteSubstitutor1 = info1.getSiteSubstitutor(); final PsiSubstitutor siteSubstitutor2 = info2.getSiteSubstitutor(); - final PsiType[] types2AtSite = typesAtSite(types2, siteSubstitutor2, typeParameters2); - final PsiType[] types1AtSite = typesAtSite(types1, siteSubstitutor1, typeParameters1); + final PsiType[] types2AtSite = typesAtSite(types2, siteSubstitutor2); + final PsiType[] types1AtSite = typesAtSite(types1, siteSubstitutor1); final PsiSubstitutor methodSubstitutor1 = calculateMethodSubstitutor(typeParameters1, method1, siteSubstitutor1, types1, types2AtSite, languageLevel); @@ -538,7 +555,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && myArgumentsList instanceof PsiExpressionList && (typeParameters1.length == 0 || typeParameters2.length == 0)) { boolean toCompareFunctional = false; - for (int i = 0; i < myActualParameterTypes.length; i++) { + for (int i = 0; i < getActualParametersLength(); i++) { if (types1.length > 0 && LambdaUtil.isFunctionalType(types1[Math.min(i, types1.length - 1)]) && types2.length > 0 && LambdaUtil.isFunctionalType(types2[Math.min(i, types2.length - 1)])) { types1AtSite[Math.min(i, types1.length - 1)] = PsiType.NULL; @@ -555,7 +572,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ if (applicable12ignoreFunctionalType || applicable21ignoreFunctionalType) { Specifics specifics = null; - for (int i = 0; i < myActualParameterTypes.length; i++) { + for (int i = 0; i < getActualParametersLength(); i++) { if (types1.length > 0 && types1AtSite[Math.min(i, types1.length - 1)] == PsiType.NULL && types2.length > 0 && types2AtSite[Math.min(i, types2.length - 1)] == PsiType.NULL) { Specifics specific = isFunctionalTypeMoreSpecific(info1, info2, ((PsiExpressionList)myArgumentsList).getExpressions()[i], i); @@ -642,7 +659,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ return applicabilityLevel > MethodCandidateInfo.ApplicabilityLevel.NOT_APPLICABLE; } - private static PsiType[] typesAtSite(PsiType[] types1, PsiSubstitutor siteSubstitutor1, PsiTypeParameter[] typeParameters1) { + private static PsiType[] typesAtSite(PsiType[] types1, PsiSubstitutor siteSubstitutor1) { final PsiType[] types = PsiType.createArray(types1.length); for (int i = 0; i < types1.length; i++) { types[i] = siteSubstitutor1.substitute(types1[i]); diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java index ad0e7358842c..8607ff43c60e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java @@ -63,7 +63,12 @@ public class MethodCandidatesProcessor extends MethodsProcessor{ final boolean staticProblem, final boolean accessible) { final PsiExpressionList argumentList = getArgumentList(); return new MethodCandidateInfo(method, substitutor, !accessible, staticProblem, argumentList, myCurrentFileContext, - getExpressionTypes(argumentList), getTypeArguments(), getLanguageLevel()); + null, getTypeArguments(), getLanguageLevel()) { + @Override + public PsiType[] getArgumentTypes() { + return getExpressionTypes(argumentList); + } + }; } protected PsiType[] getExpressionTypes(PsiExpressionList argumentList) {