summaryrefslogtreecommitdiff
path: root/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java')
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java112
1 files changed, 112 insertions, 0 deletions
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java
new file mode 100644
index 000000000000..d06538c06b41
--- /dev/null
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.psi.impl.source.resolve.graphInference.constraints;
+
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
+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.util.PsiUtil;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * User: anna
+ * Date: 9/25/13
+ */
+public abstract class InputOutputConstraintFormula implements ConstraintFormula {
+
+ protected abstract PsiExpression getExpression();
+ protected abstract PsiType getT();
+ protected abstract InputOutputConstraintFormula createSelfConstraint(PsiType type, PsiExpression expression);
+ protected abstract void collectReturnTypeVariables(InferenceSession session,
+ PsiExpression psiExpression,
+ PsiMethod interfaceMethod,
+ Set<InferenceVariable> result);
+
+ public Set<InferenceVariable> getInputVariables(InferenceSession session) {
+ final PsiExpression psiExpression = getExpression();
+ if (PsiPolyExpressionUtil.isPolyExpression(psiExpression)) {
+ final PsiType type = getT();
+ if (psiExpression instanceof PsiLambdaExpression || psiExpression instanceof PsiMethodReferenceExpression) {
+ final InferenceVariable inferenceVariable = session.getInferenceVariable(type);
+ if (inferenceVariable != null) {
+ return Collections.singleton(inferenceVariable);
+ }
+ final PsiType functionalInterfaceType = psiExpression instanceof PsiLambdaExpression
+ ? ((PsiLambdaExpression)psiExpression).getFunctionalInterfaceType()
+ : ((PsiMethodReferenceExpression)psiExpression).getFunctionalInterfaceType();
+ if (functionalInterfaceType != null) {
+ final PsiType functionType =
+ psiExpression instanceof PsiLambdaExpression
+ ? FunctionalInterfaceParameterizationUtil.getFunctionalType(functionalInterfaceType, (PsiLambdaExpression)psiExpression)
+ : functionalInterfaceType;
+ final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionType);
+ final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
+ if (interfaceMethod != null) {
+
+ final Set<InferenceVariable> result = new HashSet<InferenceVariable>();
+ final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, resolveResult);
+ for (PsiParameter parameter : interfaceMethod.getParameterList().getParameters()) {
+ session.collectDependencies(substitutor.substitute(parameter.getType()), result, true);
+ }
+
+ collectReturnTypeVariables(session, psiExpression, interfaceMethod, result);
+
+ return result;
+ }
+ }
+ }
+
+ if (psiExpression instanceof PsiParenthesizedExpression) {
+ final PsiExpression expression = ((PsiParenthesizedExpression)psiExpression).getExpression();
+ return expression != null ? createSelfConstraint(type, expression).getInputVariables(session) : null;
+ }
+
+ if (psiExpression instanceof PsiConditionalExpression) {
+ final PsiExpression thenExpression = ((PsiConditionalExpression)psiExpression).getThenExpression();
+ final PsiExpression elseExpression = ((PsiConditionalExpression)psiExpression).getElseExpression();
+ final Set<InferenceVariable> thenResult = thenExpression != null ? createSelfConstraint(type, thenExpression).getInputVariables(session) : null;
+ final Set<InferenceVariable> elseResult = elseExpression != null ? createSelfConstraint(type, elseExpression).getInputVariables(session) : null;
+ if (thenResult == null) {
+ return elseResult;
+ } else if (elseResult == null) {
+ return thenResult;
+ } else {
+ thenResult.addAll(elseResult);
+ return thenResult;
+ }
+ }
+ }
+ return null;
+ }
+
+
+ @Nullable
+ public Set<InferenceVariable> getOutputVariables(Set<InferenceVariable> inputVariables, InferenceSession session) {
+ if (!PsiPolyExpressionUtil.isPolyExpression(getExpression())) {
+ final HashSet<InferenceVariable> mentionedVariables = new HashSet<InferenceVariable>();
+ session.collectDependencies(getT(), mentionedVariables, true);
+ mentionedVariables.removeAll(inputVariables);
+ return mentionedVariables;
+ }
+ return null;
+ }
+}