mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
new inference: process additional constraints one after another and use data from previous results (IDEA-124983)
This commit is contained in:
+63
-36
@@ -267,11 +267,9 @@ public class InferenceSession {
|
||||
boolean varargs, boolean toplevel) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (args[i] != null) {
|
||||
InferenceSession session = myNestedSessions.get(PsiTreeUtil.getParentOfType(args[i], PsiCallExpression.class));
|
||||
if (session == null) {
|
||||
session = this;
|
||||
}
|
||||
PsiType parameterType = session.substituteWithInferenceVariables(getParameterType(parameters, i, siteSubstitutor, varargs));
|
||||
final InferenceSession nestedCallSession = findNestedCallSession(args[i]);
|
||||
final PsiType parameterType =
|
||||
nestedCallSession.substituteWithInferenceVariables(getParameterType(parameters, i, siteSubstitutor, varargs));
|
||||
if (!isPertinentToApplicability(args[i], parentMethod)) {
|
||||
additionalConstraints.add(new ExpressionCompatibilityConstraint(args[i], parameterType));
|
||||
}
|
||||
@@ -881,45 +879,66 @@ public class InferenceSession {
|
||||
//extract subset of constraints
|
||||
final Set<ConstraintFormula> subset = buildSubset(additionalConstraints);
|
||||
|
||||
//collect all input variables of selection
|
||||
//collect all input variables of selection
|
||||
final Set<InferenceVariable> varsToResolve = new LinkedHashSet<InferenceVariable>();
|
||||
for (ConstraintFormula formula : subset) {
|
||||
if (formula instanceof InputOutputConstraintFormula) {
|
||||
final Set<InferenceVariable> inputVariables = ((InputOutputConstraintFormula)formula).getInputVariables(this);
|
||||
if (inputVariables != null) {
|
||||
for (InferenceVariable inputVariable : inputVariables) {
|
||||
varsToResolve.addAll(inputVariable.getDependencies(this));
|
||||
}
|
||||
varsToResolve.addAll(inputVariables);
|
||||
}
|
||||
collectVarsToResolve(varsToResolve, (InputOutputConstraintFormula)formula);
|
||||
}
|
||||
}
|
||||
|
||||
//resolve input variables
|
||||
PsiSubstitutor substitutor = resolveSubset(varsToResolve, siteSubstitutor);
|
||||
if (substitutor == null) {
|
||||
for (ConstraintFormula formula : subset) {
|
||||
if (!processOneConstraint(formula, siteSubstitutor, varsToResolve)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void collectVarsToResolve(Set<InferenceVariable> varsToResolve, InputOutputConstraintFormula formula) {
|
||||
final Set<InferenceVariable> inputVariables = formula.getInputVariables(this);
|
||||
if (inputVariables != null) {
|
||||
for (InferenceVariable inputVariable : inputVariables) {
|
||||
varsToResolve.addAll(inputVariable.getDependencies(this));
|
||||
}
|
||||
varsToResolve.addAll(inputVariables);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean processOneConstraint(ConstraintFormula formula, PsiSubstitutor siteSubstitutor, Set<InferenceVariable> varsToResolve) {
|
||||
if (formula instanceof ExpressionCompatibilityConstraint) {
|
||||
final PsiExpression expression = ((ExpressionCompatibilityConstraint)formula).getExpression();
|
||||
final PsiCallExpression callExpression = PsiTreeUtil.getParentOfType(expression, PsiCallExpression.class, false);
|
||||
if (callExpression != null) {
|
||||
final InferenceSession session = myNestedSessions.get(callExpression);
|
||||
if (session != null) {
|
||||
formula.apply(session.myInferenceSubstitution, true);
|
||||
collectVarsToResolve(varsToResolve, (InputOutputConstraintFormula)formula);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//resolve input variables
|
||||
PsiSubstitutor substitutor = resolveSubset(varsToResolve, siteSubstitutor);
|
||||
if (substitutor == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (myContext instanceof PsiCallExpression) {
|
||||
PsiExpressionList argumentList = ((PsiCallExpression)myContext).getArgumentList();
|
||||
LOG.assertTrue(argumentList != null);
|
||||
MethodCandidateInfo.updateSubstitutor(argumentList, substitutor);
|
||||
}
|
||||
|
||||
try {
|
||||
formula.apply(substitutor, true);
|
||||
|
||||
myConstraints.add(formula);
|
||||
if (!repeatInferencePhases(true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (myContext instanceof PsiCallExpression) {
|
||||
PsiExpressionList argumentList = ((PsiCallExpression)myContext).getArgumentList();
|
||||
LOG.assertTrue(argumentList != null);
|
||||
MethodCandidateInfo.updateSubstitutor(argumentList, substitutor);
|
||||
}
|
||||
|
||||
try {
|
||||
for (ConstraintFormula additionalConstraint : subset) {
|
||||
additionalConstraint.apply(substitutor, true);
|
||||
}
|
||||
|
||||
myConstraints.addAll(subset);
|
||||
if (!repeatInferencePhases(true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
LambdaUtil.ourFunctionTypes.set(null);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
LambdaUtil.ourFunctionTypes.set(null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1316,6 +1335,14 @@ public class InferenceSession {
|
||||
return myInferenceSubstitution.substitute(type);
|
||||
}
|
||||
|
||||
public InferenceSession findNestedCallSession(PsiExpression arg) {
|
||||
InferenceSession session = myNestedSessions.get(PsiTreeUtil.getParentOfType(arg, PsiCallExpression.class));
|
||||
if (session == null) {
|
||||
session = this;
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
public PsiType startWithFreshVars(PsiType type) {
|
||||
PsiSubstitutor s = PsiSubstitutor.EMPTY;
|
||||
for (InferenceVariable variable : myInferenceVariables) {
|
||||
|
||||
+4
-2
@@ -3,6 +3,7 @@ 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.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
|
||||
import java.util.List;
|
||||
@@ -62,8 +63,9 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul
|
||||
if (returnExpressions.isEmpty() && !myExpression.isValueCompatible()) { //not value-compatible
|
||||
return false;
|
||||
}
|
||||
returnType = session.substituteWithInferenceVariables(substitutor.substitute(returnType));
|
||||
if (!session.isProperType(returnType)) {
|
||||
InferenceSession callsession = session.findNestedCallSession(myExpression);
|
||||
returnType = callsession.substituteWithInferenceVariables(substitutor.substitute(returnType));
|
||||
if (!callsession.isProperType(returnType)) {
|
||||
for (PsiExpression returnExpression : returnExpressions) {
|
||||
constraints.add(new ExpressionCompatibilityConstraint(returnExpression, returnType));
|
||||
}
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
|
||||
abstract class NoFormalParams {
|
||||
interface I<T> {
|
||||
T a(int a);
|
||||
}
|
||||
|
||||
<F> I<F> foo(I<F> i) { return null;}
|
||||
|
||||
{
|
||||
I<Integer> i = foo(a -> foo(b -> 1)).a(0);
|
||||
foo(a -> foo(b -> 1)).a(0);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class NoFormalParamTypeInferenceNeeded {
|
||||
interface I<T> {
|
||||
T a(int a);
|
||||
}
|
||||
|
||||
abstract <RR> RR map(I<RR> mapper);
|
||||
abstract <R, V> R zip(Function<V, R> zipper);
|
||||
|
||||
{
|
||||
map(a -> zip(text -> text));
|
||||
zip(a -> zip(text -> text));
|
||||
Integer zip = zip(<error descr="Cyclic inference">a -> zip(text -> text)</error>);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class IDEA124983 {
|
||||
private final Group gridGroup = new Group();
|
||||
void createGrid() {
|
||||
IntStream.range(0, 4)
|
||||
.mapToObj(i -> IntStream.range(0, 4).mapToObj(j -> {
|
||||
Rectangle rect2 = new Rectangle(i * 64, j * 64, 64, 64);
|
||||
return rect2;
|
||||
}))
|
||||
.flatMap(s -> s)
|
||||
.forEach(gridGroup.getChildren()::add);
|
||||
}
|
||||
|
||||
void simplified(final IntStream range) {
|
||||
range.mapToObj(i -> range.mapToObj(j -> 1)).flatMap(s -> s);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -76,7 +76,6 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testIDEA122616() { doTest(); }
|
||||
public void testIDEA122700() { doTest(); }
|
||||
public void testIDEA122406() { doTest(); }
|
||||
@Bombed(day = 30, month = Calendar.SEPTEMBER)
|
||||
public void testNestedCallsInsideLambdaReturnExpression() { doTest(); }
|
||||
@Bombed(day = 30, month = Calendar.SEPTEMBER)
|
||||
public void testIDEA123731() { doTest(); }
|
||||
@@ -95,6 +94,7 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testIDEA126809() { doTest(); }
|
||||
public void testIDEA124424() { doTest(); }
|
||||
public void testNestedLambdaExpressions1() { doTest(); }
|
||||
public void testNestedLambdaExpressionsNoFormalParams() { doTest(); }
|
||||
|
||||
public void testIDEA127596() throws Exception {
|
||||
doTest();
|
||||
|
||||
Reference in New Issue
Block a user