mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
new inference: collect nested calls from lambda return statements (JDK-8038747)
This commit is contained in:
+38
-14
@@ -56,6 +56,8 @@ public class InferenceSession {
|
||||
private final InferenceIncorporationPhase myIncorporationPhase = new InferenceIncorporationPhase(this);
|
||||
|
||||
private final PsiElement myContext;
|
||||
|
||||
private final PsiTypeParameter[] myParamsToInfer;
|
||||
|
||||
public InferenceSession(PsiTypeParameter[] typeParams,
|
||||
PsiType[] leftTypes,
|
||||
@@ -68,6 +70,7 @@ public class InferenceSession {
|
||||
myContext = context;
|
||||
|
||||
initBounds(typeParams);
|
||||
myParamsToInfer = typeParams;
|
||||
|
||||
LOG.assertTrue(leftTypes.length == rightTypes.length);
|
||||
for (int i = 0; i < leftTypes.length; i++) {
|
||||
@@ -87,6 +90,11 @@ public class InferenceSession {
|
||||
myContext = context;
|
||||
|
||||
initBounds(typeParams);
|
||||
myParamsToInfer = typeParams;
|
||||
}
|
||||
|
||||
public PsiTypeParameter[] getParamsToInfer() {
|
||||
return myParamsToInfer;
|
||||
}
|
||||
|
||||
public void initExpressionConstraints(PsiParameter[] parameters, PsiExpression[] args, PsiElement parent, PsiMethod method) {
|
||||
@@ -217,7 +225,7 @@ public class InferenceSession {
|
||||
if (parameters != null && args != null) {
|
||||
final Set<ConstraintFormula> additionalConstraints = new HashSet<ConstraintFormula>();
|
||||
if (parameters.length > 0) {
|
||||
collectAdditionalConstraints(parameters, args, properties.getMethod(), PsiSubstitutor.EMPTY, additionalConstraints, properties.isVarargs());
|
||||
collectAdditionalConstraints(parameters, args, properties.getMethod(), PsiSubstitutor.EMPTY, additionalConstraints, properties.isVarargs(), true);
|
||||
}
|
||||
|
||||
if (!additionalConstraints.isEmpty() && !proceedWithAdditionalConstraints(additionalConstraints)) {
|
||||
@@ -250,7 +258,7 @@ public class InferenceSession {
|
||||
PsiMethod parentMethod,
|
||||
PsiSubstitutor siteSubstitutor,
|
||||
Set<ConstraintFormula> additionalConstraints,
|
||||
boolean varargs) {
|
||||
boolean varargs, boolean toplevel) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (args[i] != null) {
|
||||
PsiType parameterType = getParameterType(parameters, i, siteSubstitutor, varargs);
|
||||
@@ -262,18 +270,15 @@ public class InferenceSession {
|
||||
//If the expression is a poly class instance creation expression (15.9) or a poly method invocation expression (15.12),
|
||||
//the set contains all constraint formulas that would appear in the set C when determining the poly expression's invocation type.
|
||||
final PsiCallExpression callExpression = (PsiCallExpression)args[i];
|
||||
final PsiExpressionList argumentList = callExpression.getArgumentList();
|
||||
if (argumentList != null) {
|
||||
final JavaResolveResult result = callExpression.resolveMethodGenerics();
|
||||
if (result instanceof MethodCandidateInfo) {
|
||||
final PsiMethod method = ((MethodCandidateInfo)result).getElement();
|
||||
//need to get type parameters for 2 level nested expressions (they won't be covered by expression constraints on this level?!)
|
||||
initBounds(method.getTypeParameters());
|
||||
final PsiExpression[] newArgs = argumentList.getExpressions();
|
||||
final PsiParameter[] newParams = method.getParameterList().getParameters();
|
||||
if (newParams.length > 0) {
|
||||
collectAdditionalConstraints(newParams, newArgs, method, ((MethodCandidateInfo)result).getSiteSubstitutor(),
|
||||
additionalConstraints, ((MethodCandidateInfo)result).isVarargs());
|
||||
collectAdditionalConstraints(additionalConstraints, callExpression);
|
||||
} else if (args[i] instanceof PsiLambdaExpression && toplevel) {
|
||||
final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(parameterType);
|
||||
if (interfaceReturnType != null) {
|
||||
final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions((PsiLambdaExpression)args[i]);
|
||||
for (PsiExpression returnExpression : returnExpressions) {
|
||||
if (returnExpression instanceof PsiCallExpression) {
|
||||
final PsiCallExpression callExpression = (PsiCallExpression)returnExpression;
|
||||
collectAdditionalConstraints(additionalConstraints, callExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,6 +287,25 @@ public class InferenceSession {
|
||||
}
|
||||
}
|
||||
|
||||
private void collectAdditionalConstraints(Set<ConstraintFormula> additionalConstraints,
|
||||
PsiCallExpression callExpression) {
|
||||
PsiExpressionList argumentList = callExpression.getArgumentList();
|
||||
if (argumentList != null) {
|
||||
final JavaResolveResult result = callExpression.resolveMethodGenerics();
|
||||
if (result instanceof MethodCandidateInfo) {
|
||||
final PsiMethod method = ((MethodCandidateInfo)result).getElement();
|
||||
//need to get type parameters for 2 level nested expressions (they won't be covered by expression constraints on this level?!)
|
||||
initBounds(method.getTypeParameters());
|
||||
final PsiExpression[] newArgs = argumentList.getExpressions();
|
||||
final PsiParameter[] newParams = method.getParameterList().getParameters();
|
||||
if (newParams.length > 0) {
|
||||
collectAdditionalConstraints(newParams, newArgs, method, ((MethodCandidateInfo)result).getSiteSubstitutor(),
|
||||
additionalConstraints, ((MethodCandidateInfo)result).isVarargs(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PsiSubstitutor retrieveNonPrimitiveEqualsBounds(Collection<InferenceVariable> variables) {
|
||||
PsiSubstitutor substitutor = mySiteSubstitutor;
|
||||
for (InferenceVariable variable : variables) {
|
||||
|
||||
+2
-1
@@ -23,6 +23,7 @@ import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -103,7 +104,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
|
||||
|
||||
if (typeParams != null) {
|
||||
|
||||
final HashSet<PsiTypeParameter> oldBounds = new HashSet<PsiTypeParameter>(session.getTypeParams());
|
||||
final Set<PsiTypeParameter> oldBounds = ContainerUtil.newHashSet(session.getParamsToInfer());
|
||||
final boolean sameMethodCall = session.initBounds(typeParams);
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
final HashSet<InferenceVariable> variables = new HashSet<InferenceVariable>();
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
abstract class Play {
|
||||
public void main(Stream<String> stream, Stream<String> anotherStream) {
|
||||
Stream<String> stringStream = stream.map(o -> foo(i -> "")).flatMap(l -> l);
|
||||
}
|
||||
|
||||
abstract <RF > Stream<RF> foo(Function<Integer, ? extends RF> mapper);
|
||||
|
||||
static int foo() {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class SimplePlay {
|
||||
{
|
||||
foo(y -> bar(x -> "")).substring(0);
|
||||
}
|
||||
|
||||
interface Res<R> {
|
||||
R apply(String s);
|
||||
}
|
||||
|
||||
<T> T foo(Res<T> f) {return null;}
|
||||
<K> K bar(Res<K> f) {return null;}
|
||||
}
|
||||
|
||||
class Test19 {
|
||||
interface Seq<E> extends Iterable<E> {
|
||||
static <E> Seq<E> of(Iterable<? extends E> source) {
|
||||
return null;
|
||||
}
|
||||
|
||||
<R> Seq<R> map(Function<? super E, ? extends R> mapper);
|
||||
<R, V> Seq<R> zip(BiFunction<? super E, ? super V, ? extends R> zipper, Seq<V> other);
|
||||
}
|
||||
|
||||
interface S extends Seq<String> {
|
||||
static S copyOf(Iterable<String> source) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface D extends S {
|
||||
|
||||
}
|
||||
|
||||
void test(Seq<D> dseq) {
|
||||
BiFunction<D, List<Integer>, Seq<S>> f =
|
||||
(d, nums) -> dseq.map(s -> s.zip((text, num) -> text + num, Seq.of(nums)))
|
||||
.map(s -> S.copyOf(s));
|
||||
}
|
||||
}
|
||||
+4
@@ -182,6 +182,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNestedCallsInsideLambdaReturnExpression() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user