lambda & raw types

This commit is contained in:
Anna Kozlova
2012-08-31 18:40:56 +04:00
parent 89ad0dbcbc
commit b199a1b76c
5 changed files with 72 additions and 14 deletions
@@ -76,6 +76,7 @@ public class LambdaUtil {
public static boolean isLambdaFullyInferred(PsiLambdaExpression expression, PsiType functionalInterfaceType) {
if (expression.getParameterList().getParametersCount() > 0 || getFunctionalInterfaceReturnType(functionalInterfaceType) != PsiType.VOID) { //todo check that void lambdas without params check
if (functionalInterfaceType instanceof PsiClassType && ((PsiClassType)functionalInterfaceType).isRaw()) return false;
return !dependsOnTypeParams(functionalInterfaceType, expression);
}
return true;
@@ -144,8 +145,8 @@ public class LambdaUtil {
return false;
}
if (!lambdaFormalType
.isAssignableFrom(GenericsUtil.eliminateWildcards(resolveResult.getSubstitutor().substitute(methodSignature.getSubstitutor().substitute(methodParameterType))))) {
if (!TypeConversionUtil.erasure(lambdaFormalType)
.isAssignableFrom(TypeConversionUtil.erasure(GenericsUtil.eliminateWildcards(resolveResult.getSubstitutor().substitute(methodSignature.getSubstitutor().substitute(methodParameterType)))))) {
return false;
}
}
@@ -433,6 +434,9 @@ public class LambdaUtil {
final PsiElement gParent = parent.getParent();
if (gParent instanceof PsiCallExpression) {
myMethod = ((PsiCallExpression)gParent).resolveMethod();
if (myMethod != null && PsiTreeUtil.isAncestor(myMethod, expression, false)) {
myMethod = null;
}
}
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.psi.impl.source.resolve;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -186,6 +185,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
PsiType upperBound = PsiType.NULL;
if (paramTypes.length > 0) {
sortLambdaExpressionsLast(paramTypes, argTypes);
boolean rawType = false;
boolean nullPassed = false;
for (int j = 0; j < argTypes.length; j++) {
PsiType argumentType = argTypes[j];
if (argumentType == null) continue;
@@ -193,6 +194,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
PsiType parameterType = paramTypes[j];
if (parameterType == null) break;
rawType |= parameterType instanceof PsiClassType && ((PsiClassType)parameterType).isRaw();
nullPassed |= argumentType == PsiType.NULL;
if (parameterType instanceof PsiEllipsisType) {
parameterType = ((PsiEllipsisType)parameterType).getComponentType();
@@ -203,6 +206,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
final Pair<PsiType,ConstraintType> currentSubstitution;
if (argumentType instanceof PsiLambdaExpressionType) {
currentSubstitution = inferSubstitutionFromLambda(typeParameter, (PsiLambdaExpressionType)argumentType, lowerBound);
if (rawType && currentSubstitution == FAILED_INFERENCE || nullPassed && currentSubstitution == null) return new Pair<PsiType, ConstraintType>(null, ConstraintType.EQUALS);
} else {
currentSubstitution = getSubstitutionForTypeParameterConstraint(typeParameter, parameterType,
argumentType, true, PsiUtil.getLanguageLevel(typeParameter));
@@ -592,7 +596,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
if (constraintFromFormalParams != null) return constraintFromFormalParams;
final PsiParameter[] methodParameters = method.getParameterList().getParameters();
final PsiSubstitutor subst = resolveResult.getSubstitutor();
final PsiSubstitutor subst =
TypeConversionUtil.getSuperClassSubstitutor(method.getContainingClass(), resolveResult.getElement(), resolveResult.getSubstitutor());
final boolean methodParamsDependOnTypeParams = methodParamsDependOnTypeParams(lambdaExpression, methodParameters, subst, typeParam);
final PsiType returnType = subst.substitute(method.getReturnType());
if (returnType != null && returnType != PsiType.VOID) {
@@ -891,8 +896,10 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
return getFailedInferenceConstraint(typeParameter);
}
final PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType);
if (method == null || methodParamsDependOnTypeParams((PsiLambdaExpression)expression, method.getParameterList().getParameters(),
PsiUtil.resolveGenericsClassInType(functionalInterfaceType).getSubstitutor(), typeParameter)) {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
if (method == null || methodParamsDependOnTypeParams((PsiLambdaExpression)expression, method.getParameterList().getParameters(),
TypeConversionUtil.getSuperClassSubstitutor(method.getContainingClass(), resolveResult.getElement(), resolveResult.getSubstitutor()), typeParameter)) {
return getFailedInferenceConstraint(typeParameter);
}
}
@@ -1,14 +1,21 @@
class Test <T, U> {
class TestData<K> {}
interface TerminalOp<L, M> extends IntermediateOp<L, M> {}
interface IntermediateOp<L1, M1> { boolean _(L1 l, M1 m);}
class Test<T, U> {
protected U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp<T, U>... ops) {
return exerciseOps(data, terminal, (u, v) -> u.equals(v));
}
}
class TestData<K> {}
interface TerminalOp<L, M> extends IntermediateOp<L, M> {
class Test1 {
protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp... ops) {
return exerciseOps(data, terminal, (u, v) -> u.equals(v));
}
interface IntermediateOp<L1, M1> { boolean _(L1 l, M1 m);}
}
}
class Test2 {
protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp<T, U>... ops) {
return exerciseOps(data, terminal, (u, v) -> u.equals(v));
}
}
@@ -0,0 +1,36 @@
import java.util.*;
class TestData<K> {}
interface TerminalOp<L, M> extends IntermediateOp<L, M> {}
interface IntermediateOp<L1, M1> { boolean _(L1 l, M1 m);}
class Test1 {
protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp<T, U>... ops) {
return exerciseOps(data, (u, v) -> u.equals(v), terminal);
}
}
class Test2 {
protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp... ops) {
return exerciseOps(data, <error descr="Cyclic inference">(u, v) -> u.equals(v)</error>, terminal);
}
}
class Test3 {
interface I<Y> {
void m(Y y);
}
static <T> void bar(I<T> i, List<T> l){
bar(x -> {}, l);
bar(<error descr="Cyclic inference">x -> {}</error>, null);
bar((I<T>)x -> {}, null);
bar((T x) -> {}, null);
bar(x -> {}, new ArrayList<T>());
bar(<error descr="Cyclic inference">x -> {}</error>, new ArrayList());
}
static {
bar(<error descr="Cyclic inference">x->{}</error>, new ArrayList());
}
}
@@ -92,6 +92,10 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testLambdaOnVarargPlace() throws Exception {
doTest();
}
public void testLambdaRawOrNot() throws Exception {
doTest();
}
public void testNoInferenceResult() throws Exception {
doTest();