mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 13:31:28 +07:00
inference: deep nested session based on existing initial substitution (IDEA-167713)
This commit is contained in:
@@ -172,33 +172,37 @@ public class InferenceSessionContainer {
|
||||
if (call != null) {
|
||||
initialInferenceState = compoundInitialState.getInitialState(call);
|
||||
if (initialInferenceState != null) {
|
||||
final int idx = LambdaUtil.getLambdaIdx(call.getArgumentList(), gParent);
|
||||
final PsiMethod method = call.resolveMethod();
|
||||
if (method != null && idx > -1) {
|
||||
final PsiParameter[] methodParameters = method.getParameterList().getParameters();
|
||||
final PsiExpressionList argumentList = call.getArgumentList();
|
||||
final int idx = LambdaUtil.getLambdaIdx(argumentList, gParent);
|
||||
final JavaResolveResult result = call.resolveMethodGenerics();
|
||||
final PsiElement method = result.getElement();
|
||||
if (method instanceof PsiMethod && idx > -1) {
|
||||
LOG.assertTrue(argumentList != null);
|
||||
final PsiParameter[] methodParameters = ((PsiMethod)method).getParameterList().getParameters();
|
||||
if (methodParameters.length == 0) {
|
||||
break;
|
||||
}
|
||||
final PsiType parameterType = PsiTypesUtil.getParameterType(methodParameters, idx, true);
|
||||
final PsiType parameterTypeInTermsOfSession = initialInferenceState.getInferenceSubstitutor().substitute(parameterType);
|
||||
final PsiType lambdaTargetType = compoundInitialState.getInitialSubstitutor().substitute(parameterTypeInTermsOfSession);
|
||||
return LambdaUtil.performWithLambdaTargetType((PsiLambdaExpression)gParent, lambdaTargetType, new Producer<PsiSubstitutor>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiSubstitutor produce() {
|
||||
if (call.equals(PsiTreeUtil.getParentOfType(parent, PsiCall.class, true))) {
|
||||
//parent was mentioned in the top inference session
|
||||
//just proceed with the target type
|
||||
final InferenceSession inferenceSession = new InferenceSession(typeParameters, partialSubstitutor, parent.getManager(), parent, policy);
|
||||
inferenceSession.initExpressionConstraints(parameters, arguments, parent);
|
||||
return inferenceSession.infer(parameters, arguments, parent);
|
||||
if (call.equals(PsiTreeUtil.getParentOfType(parent, PsiCall.class, true))) {
|
||||
return LambdaUtil.performWithLambdaTargetType((PsiLambdaExpression)gParent, partialSubstitutor.substitute(lambdaTargetType), new Producer<PsiSubstitutor>() {
|
||||
@Override
|
||||
public PsiSubstitutor produce() {
|
||||
//parent was mentioned in the top inference session
|
||||
//just proceed with the target type
|
||||
final InferenceSession inferenceSession = new InferenceSession(typeParameters, partialSubstitutor, parent.getManager(), parent, policy);
|
||||
inferenceSession.initExpressionConstraints(parameters, arguments, parent);
|
||||
return inferenceSession.infer(parameters, arguments, parent);
|
||||
}
|
||||
//one of the grand parents were found in the top inference session
|
||||
//start from it as it is the top level call
|
||||
final InferenceSession sessionInsideLambda = startTopLevelInference(call, policy);
|
||||
return inferNested(typeParameters, parameters, arguments, partialSubstitutor, parent, policy, properties, sessionInsideLambda);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//one of the grand parents were found in the top inference session
|
||||
//start from it as it is the top level call
|
||||
final InferenceSession sessionInsideLambda = new InferenceSession(initialInferenceState);
|
||||
sessionInsideLambda.collectAdditionalAndInfer(methodParameters, argumentList.getExpressions(), ((MethodCandidateInfo)result).createProperties(), compoundInitialState.getInitialSubstitutor());
|
||||
return inferNested(typeParameters, parameters, arguments, partialSubstitutor, parent, policy, properties, sessionInsideLambda);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
interface DuallyParametric<A0, B0> {
|
||||
<R> R match(Function<? super A0, ? extends R> aFn, Function<? super B0, ? extends R> bFn);
|
||||
static <Aa, Ba> DuallyParametric<Aa, Ba> a(Aa a) {
|
||||
return null;
|
||||
}
|
||||
|
||||
<Ab, Bb> DuallyParametric<Ab, Bb> b(Bb b);
|
||||
|
||||
<Al, Bl> Bl foldLeft(BiFunction<? super Bl, ? super Al, ? extends Bl> fn, Bl b, Iterable<Al> as);
|
||||
|
||||
default <A, B> DuallyParametric<A, B> merge(DuallyParametric<A, B> first,
|
||||
BiFunction<? super A, ? super A, ? extends A> aFn,
|
||||
BiFunction<? super B, ? super B, ? extends B> bFn,
|
||||
Iterable<DuallyParametric<A, B>> others) {
|
||||
return foldLeft((x, y) -> x.match(a1 -> y.match(a2 -> a(aFn.apply(a1, a2)), b -> a(a1)),
|
||||
b1 -> y.match(DuallyParametric::a, b2 -> b(bFn.apply(b1, b2)))),
|
||||
first,
|
||||
others);
|
||||
}
|
||||
}
|
||||
|
||||
interface DuallyParametric1<A> {
|
||||
default <R> R match(Function<A, R> aFn) {
|
||||
return null;
|
||||
}
|
||||
|
||||
static <Ba> DuallyParametric1<Ba> a() {
|
||||
return null;
|
||||
}
|
||||
|
||||
<Bl> void foldLeft(Function<Bl, Bl> fn, Bl b);
|
||||
|
||||
default void merge() {
|
||||
foldLeft((x) -> x.match(a1 -> match(a2 -> a())), this);
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,10 @@ public class NewInferenceCollectingAdditionalConstraintsTest extends LightDaemon
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNestedLambdaExpressionsChain() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable());
|
||||
doTest(BASE_PATH + "/" + getTestName(false) + ".java", true, false);
|
||||
|
||||
Reference in New Issue
Block a user