mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 09:19:13 +07:00
lambda: replace raw inference from lambda with Object when it doesn't matter (IDEA-101788)
This commit is contained in:
+45
-4
@@ -205,6 +205,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
sortLambdaExpressionsLast(paramTypes, argTypes);
|
||||
boolean rawType = false;
|
||||
boolean nullPassed = false;
|
||||
boolean lambdaRaw = false;
|
||||
for (int j = 0; j < argTypes.length; j++) {
|
||||
PsiType argumentType = argTypes[j];
|
||||
if (argumentType == null) continue;
|
||||
@@ -228,6 +229,12 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
if (currentSubstitution == FAILED_INFERENCE || (currentSubstitution == null && lowerBound == PsiType.NULL)) return RAW_INFERENCE;
|
||||
}
|
||||
if (nullPassed && currentSubstitution == null) return RAW_INFERENCE;
|
||||
if (currentSubstitution != null && currentSubstitution.first == null) {
|
||||
lambdaRaw = true;
|
||||
}
|
||||
if (currentSubstitution == null && lambdaRaw) {
|
||||
return new Pair<PsiType, ConstraintType>(PsiType.getJavaLangObject(typeParameter.getManager(), typeParameter.getResolveScope()), ConstraintType.EQUALS);
|
||||
}
|
||||
} else if (argumentType instanceof PsiMethodReferenceType) {
|
||||
final PsiMethodReferenceExpression referenceExpression = ((PsiMethodReferenceType)argumentType).getExpression();
|
||||
currentSubstitution = inferConstraintFromFunctionalInterfaceMethod(typeParameter, referenceExpression, partialSubstitutor.substitute(parameterType), partialSubstitutor, policy);
|
||||
@@ -998,7 +1005,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Pair<PsiType, ConstraintType> inferMethodTypeParameterFromParent(PsiElement parent,
|
||||
private static Pair<PsiType, ConstraintType> inferMethodTypeParameterFromParent(final PsiElement parent,
|
||||
PsiExpression methodCall,
|
||||
final PsiTypeParameter typeParameter,
|
||||
PsiSubstitutor substitutor,
|
||||
@@ -1065,16 +1072,24 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
}
|
||||
}
|
||||
} else if (parent instanceof PsiLambdaExpression) {
|
||||
expectedType = LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)parent).getFunctionalInterfaceType());
|
||||
expectedType = ourGraphGuard.doPreventingRecursion(methodCall, true, new Computable<PsiType>() {
|
||||
@Override
|
||||
public PsiType compute() {
|
||||
return LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)parent).getFunctionalInterfaceType());
|
||||
}
|
||||
});
|
||||
if (expectedType == null) {
|
||||
return getFailedInferenceConstraint(typeParameter);
|
||||
return null;
|
||||
}
|
||||
} else if (parent instanceof PsiTypeCastExpression) {
|
||||
expectedType = ((PsiTypeCastExpression)parent).getType();
|
||||
} else if (parent instanceof PsiConditionalExpression) {
|
||||
if (PsiUtil.isLanguageLevel8OrHigher(parent)) {
|
||||
try {
|
||||
return inferMethodTypeParameterFromParent(PsiUtil.skipParenthesizedExprUp(parent.getParent()), (PsiExpression)parent, typeParameter, substitutor, policy);
|
||||
final Pair<PsiType, ConstraintType> pair = inferFromConditionalExpression(parent, methodCall, typeParameter, substitutor, policy);
|
||||
if (pair != null) {
|
||||
return pair;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
GraphInferencePolicy.forget(parent);
|
||||
@@ -1175,6 +1190,32 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Pair<PsiType, ConstraintType> inferFromConditionalExpression(PsiElement parent,
|
||||
PsiExpression methodCall,
|
||||
PsiTypeParameter typeParameter,
|
||||
PsiSubstitutor substitutor,
|
||||
ParameterTypeInferencePolicy policy) {
|
||||
Pair<PsiType, ConstraintType> pair =
|
||||
inferMethodTypeParameterFromParent(PsiUtil.skipParenthesizedExprUp(parent.getParent()), (PsiExpression)parent, typeParameter, substitutor, policy);
|
||||
if (pair == null) {
|
||||
final PsiExpression thenExpression = ((PsiConditionalExpression)parent).getThenExpression();
|
||||
final PsiExpression elseExpression = ((PsiConditionalExpression)parent).getElseExpression();
|
||||
final PsiType[] paramTypes = {((PsiMethod)typeParameter.getOwner()).getReturnType()};
|
||||
if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(elseExpression)) && thenExpression != null) {
|
||||
final PsiType thenType = thenExpression.getType();
|
||||
if (thenType != null) {
|
||||
pair = inferTypeForMethodTypeParameterInner(typeParameter, paramTypes, new PsiType[] {thenType}, substitutor, null, policy);
|
||||
}
|
||||
} else if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(thenExpression)) && elseExpression != null) {
|
||||
final PsiType elseType = elseExpression.getType();
|
||||
if (elseType != null) {
|
||||
pair = inferTypeForMethodTypeParameterInner(typeParameter, paramTypes, new PsiType[] {elseType}, substitutor, null, policy);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pair;
|
||||
}
|
||||
|
||||
private static final ProcessCandidateParameterTypeInferencePolicy GRAPH_INFERENCE_POLICY = new GraphInferencePolicy();
|
||||
|
||||
private static Pair<PsiType, ConstraintType> graphInferenceFromCallContext(@NotNull final PsiExpression methodCall,
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
public class CyclicReferenceTest {
|
||||
void test(Match<String, Integer> match) {
|
||||
Match<String, Integer> matcher = match.or(s -> Optional.empty(), i -> 2);
|
||||
Match<String, Integer> matcher1 = match.or(s -> s.startsWith("_") ? Optional.of(1) : Optional.empty(), i -> 2);
|
||||
}
|
||||
}
|
||||
|
||||
class Match<T, V> {
|
||||
public <W> Match<T, V> or(Extractor<T, W> e, Function<W, V> c) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
interface Extractor<T, W> {
|
||||
Optional<W> unapply(T t);
|
||||
}
|
||||
|
||||
interface Function<W, V> {
|
||||
public V apply(W t);
|
||||
}
|
||||
|
||||
class Optional<W> {
|
||||
public static <T> Optional<T> empty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> Optional<T> of(T value) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+4
@@ -216,6 +216,10 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testAcceptRawSubstForLambda() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testCheckFunctionalInterfaceAccess() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user