mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
inference: skip constraints that depend on ignored constraints
when type of lambda parameter is calculated, the containing lambda doesn't end in the constraints set; if some other constraints depend on it's output variables, inside those constraints e.g. method calls may be cached based on incomplete inference results which would lead to blinking of highlighting
This commit is contained in:
+25
-1
@@ -415,7 +415,14 @@ public class InferenceSession {
|
||||
if (arg instanceof PsiLambdaExpression && ignoreConstraintTree(ignoredConstraints, arg, parameterType)) {
|
||||
continue;
|
||||
}
|
||||
additionalConstraints.add(new ExpressionCompatibilityConstraint(arg, parameterType));
|
||||
|
||||
ExpressionCompatibilityConstraint compatibilityConstraint = new ExpressionCompatibilityConstraint(arg, parameterType);
|
||||
if (dependsOnIgnoredConstraint(ignoredConstraints, compatibilityConstraint)) {
|
||||
ignoredConstraints.add(compatibilityConstraint);
|
||||
continue;
|
||||
}
|
||||
|
||||
additionalConstraints.add(compatibilityConstraint);
|
||||
}
|
||||
additionalConstraints.add(new CheckedExceptionCompatibilityConstraint(arg, parameterType));
|
||||
if (arg instanceof PsiCall) {
|
||||
@@ -437,6 +444,23 @@ public class InferenceSession {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean dependsOnIgnoredConstraint(Set<ConstraintFormula> ignoredConstraints, ExpressionCompatibilityConstraint compatibilityConstraint) {
|
||||
if (!ignoredConstraints.isEmpty()) {
|
||||
Set<InferenceVariable> inputVariables = compatibilityConstraint.getInputVariables(this);
|
||||
|
||||
if (inputVariables != null) {
|
||||
for (ConstraintFormula ignoredConstraint : ignoredConstraints) {
|
||||
if (ignoredConstraint instanceof InputOutputConstraintFormula) {
|
||||
Set<InferenceVariable> inputsOfIgnored = ((InputOutputConstraintFormula)ignoredConstraint).getInputVariables(this);
|
||||
Set<InferenceVariable> outputVariables = ((InputOutputConstraintFormula)ignoredConstraint).getOutputVariables(inputsOfIgnored, this);
|
||||
if (outputVariables != null && ContainerUtil.intersects(outputVariables, inputVariables)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean ignoreConstraintTree(Set<? super ConstraintFormula> ignoredConstraints, PsiExpression arg, PsiType parameterType) {
|
||||
for (Object expr : MethodCandidateInfo.ourOverloadGuard.currentStack()) {
|
||||
if (PsiTreeUtil.getParentOfType((PsiElement)expr, PsiLambdaExpression.class) == arg) {
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import java.util.function.Function;
|
||||
|
||||
class TestClass {
|
||||
|
||||
<H> void foo(Function<A, H> f, Function<H, String> toStr) {}
|
||||
|
||||
{
|
||||
foo(o1 -> A.getB(o1), o2 -> o2.getId());
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
static B getB(A a) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface B {
|
||||
String getId();
|
||||
}
|
||||
+8
@@ -82,7 +82,15 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
|
||||
doTestAllMethodCallExpressions();
|
||||
}
|
||||
|
||||
public void testLambdaParameterDeterminesNeighbourLambdaType() {
|
||||
doTestParametersSideEffects();
|
||||
}
|
||||
|
||||
public void testLambdaParameterTypeSideEffects() {
|
||||
doTestParametersSideEffects();
|
||||
}
|
||||
|
||||
private void doTestParametersSideEffects() {
|
||||
configureByFile(BASE_PATH + "/" + getTestName(false) + ".java");
|
||||
Collection<PsiParameter> parameters = PsiTreeUtil.findChildrenOfType(getFile(), PsiParameter.class);
|
||||
for (PsiParameter parameter : parameters) {
|
||||
|
||||
Reference in New Issue
Block a user