summaryrefslogtreecommitdiff
path: root/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java')
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java95
1 files changed, 90 insertions, 5 deletions
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
index a0e6a767d8f2..7084538c17c7 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
@@ -15,18 +15,22 @@
*/
package com.intellij.psi.impl.source.resolve.graphInference.constraints;
+import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
+import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
+import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl;
+import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.NotNull;
-import java.util.List;
+import java.util.*;
/**
* User: anna
*/
-public class ExpressionCompatibilityConstraint implements ConstraintFormula {
+public class ExpressionCompatibilityConstraint extends InputOutputConstraintFormula {
private PsiExpression myExpression;
private PsiType myT;
@@ -36,7 +40,7 @@ public class ExpressionCompatibilityConstraint implements ConstraintFormula {
}
@Override
- public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints, List<ConstraintFormula> delayedConstraints) {
+ public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) {
if (session.isProperType(myT)) {
return TypeConversionUtil.areTypesAssignmentCompatible(myT, myExpression);
}
@@ -69,11 +73,59 @@ public class ExpressionCompatibilityConstraint implements ConstraintFormula {
}
if (myExpression instanceof PsiCallExpression) {
- //todo
+ final PsiExpressionList argumentList = ((PsiCallExpression)myExpression).getArgumentList();
+ if (argumentList != null) {
+ final Map<PsiElement,Pair<PsiMethod,PsiSubstitutor>> map = MethodCandidateInfo.CURRENT_CANDIDATE.get();
+ final Pair<PsiMethod,PsiSubstitutor> pair = map != null ? map.get(argumentList) : null;
+ final PsiMethod method = pair != null ? pair.first : ((PsiCallExpression)myExpression).resolveMethod();
+ PsiType returnType = null;
+ InferenceSession callSession = null;
+ if (method != null) {
+ returnType = method.getReturnType();
+ final PsiParameter[] parameters = method.getParameterList().getParameters();
+ if (returnType != null) {
+ callSession = new InferenceSession(method.getTypeParameters(), parameters,
+ argumentList.getExpressions(),
+ PsiSubstitutor.EMPTY, null, myExpression.getManager());
+
+ }
+ } else if (myExpression instanceof PsiNewExpression) { //default constructor
+ final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)myExpression).getClassOrAnonymousClassReference();
+ if (classReference != null) {
+ final PsiElement psiClass = classReference.resolve();
+ if (psiClass instanceof PsiClass) {
+ returnType = JavaPsiFacade.getElementFactory(argumentList.getProject()).createType((PsiClass)psiClass, PsiSubstitutor.EMPTY);
+ callSession = new InferenceSession(((PsiClass)psiClass).getTypeParameters(),
+ PsiParameter.EMPTY_ARRAY,
+ argumentList.getExpressions(),
+ PsiSubstitutor.EMPTY, null, myExpression.getManager());
+ }
+ }
+ }
+
+ if (callSession != null) {
+
+ for (PsiTypeParameter typeParameter : session.getTypeParams()) {
+ callSession.addCapturedVariable(typeParameter);
+ }
+ callSession.addConstraint(new TypeCompatibilityConstraint(myT, returnType));
+ final PsiSubstitutor callSubstitutor = callSession.infer();
+
+ if (myExpression instanceof PsiMethodCallExpression) {
+ returnType = PsiMethodCallExpressionImpl.captureReturnType((PsiMethodCallExpression)myExpression, method, returnType, callSubstitutor);
+ }
+ else {
+ returnType = callSubstitutor.substitute(returnType);
+ }
+ constraints.add(new TypeCompatibilityConstraint(myT, returnType)); //todo primitive types
+ }
+ }
+ return true;
}
if (myExpression instanceof PsiMethodReferenceExpression) {
- //todo
+ constraints.add(new PsiMethodReferenceCompatibilityConstraint(((PsiMethodReferenceExpression)myExpression), myT));
+ return true;
}
if (myExpression instanceof PsiLambdaExpression) {
@@ -104,4 +156,37 @@ public class ExpressionCompatibilityConstraint implements ConstraintFormula {
result = 31 * result + myT.hashCode();
return result;
}
+
+ @Override
+ public PsiExpression getExpression() {
+ return myExpression;
+ }
+
+ @Override
+ public PsiType getT() {
+ return myT;
+ }
+
+ @Override
+ protected InputOutputConstraintFormula createSelfConstraint(PsiType type, PsiExpression expression) {
+ return new ExpressionCompatibilityConstraint(expression, type);
+ }
+
+ protected void collectReturnTypeVariables(InferenceSession session,
+ PsiExpression psiExpression,
+ PsiMethod interfaceMethod,
+ Set<InferenceVariable> result) {
+ if (psiExpression instanceof PsiLambdaExpression) {
+ final PsiType returnType = interfaceMethod.getReturnType();
+ if (returnType != PsiType.VOID) {
+ final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions((PsiLambdaExpression)psiExpression);
+ for (PsiExpression expression : returnExpressions) {
+ final Set<InferenceVariable> resultInputVars = createSelfConstraint(returnType, expression).getInputVariables(session);
+ if (resultInputVars != null) {
+ result.addAll(resultInputVars);
+ }
+ }
+ }
+ }
+ }
}