new inference: postpone argument types calculation

This commit is contained in:
Anna Kozlova
2014-03-06 10:15:21 +01:00
parent 9142df3c73
commit a70f8239c8
3 changed files with 62 additions and 37 deletions
@@ -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<Integer>() {
@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;
@@ -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<CandidateInfo> 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<CandidateInfo> 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]);
@@ -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) {