lambda: void return type compatibility (initial); functional interfaces without method params error messages

This commit is contained in:
Anna Kozlova
2012-08-17 22:45:25 +04:00
parent 321d3b9dd0
commit 1fa0a6ade4
5 changed files with 70 additions and 16 deletions
@@ -126,22 +126,29 @@ public class LambdaUtil {
}
LOG.assertTrue(psiClass != null);
PsiType methodReturnType = getReturnType(psiClass, methodSignature);
if (methodReturnType != null && methodReturnType != PsiType.VOID) {
methodReturnType = resolveResult.getSubstitutor().substitute(methodSignature.getSubstitutor().substitute(methodReturnType));
final PsiElement body = lambdaExpression.getBody();
if (body instanceof PsiCodeBlock) {
final PsiCodeBlock block = (PsiCodeBlock)body;
for (PsiStatement statement : block.getStatements()) {
if (statement instanceof PsiReturnStatement) {
final PsiExpression returnValue = ((PsiReturnStatement)statement).getReturnValue();
if (returnValue != null) {
if (!checkReturnTypeAssignability(returnValue.getType(), parameterTypes, lambdaExpression, methodReturnType)) return false;
if (methodReturnType != null) {
if (methodReturnType != PsiType.VOID) {
methodReturnType = resolveResult.getSubstitutor().substitute(methodSignature.getSubstitutor().substitute(methodReturnType));
final PsiElement body = lambdaExpression.getBody();
if (body instanceof PsiCodeBlock) {
final PsiCodeBlock block = (PsiCodeBlock)body;
for (PsiStatement statement : block.getStatements()) {
if (statement instanceof PsiReturnStatement) {
final PsiExpression returnValue = ((PsiReturnStatement)statement).getReturnValue();
if (returnValue != null) {
if (!checkReturnTypeAssignability(returnValue.getType(), parameterTypes, lambdaExpression, methodReturnType)) return false;
}
}
}
}
}
else if (body instanceof PsiExpression) {
return checkReturnTypeAssignability(((PsiExpression)body).getType(), parameterTypes, lambdaExpression, methodReturnType);
else if (body instanceof PsiExpression) {
return checkReturnTypeAssignability(((PsiExpression)body).getType(), parameterTypes, lambdaExpression, methodReturnType);
}
} else {
final List<PsiExpression> returnExpressions = lambdaExpression.getReturnExpressions();
for (PsiExpression returnValue : returnExpressions) {
if (returnValue.getType() != PsiType.VOID) return false;
}
}
}
return true;
@@ -19,6 +19,7 @@ import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.java.PsiLambdaExpressionImpl;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.MethodProcessorSetupFailedException;
@@ -876,8 +877,14 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
final PsiExpressionList argumentList = methodCall.getArgumentList();
if (argumentList != null && PsiUtil.getLanguageLevel(argumentList).isAtLeast(LanguageLevel.JDK_1_8)) {
for (PsiExpression expression : argumentList.getExpressions()) {
if (expression instanceof PsiLambdaExpression){
return getFailedInferenceConstraint(typeParameter);
if (expression instanceof PsiLambdaExpression) {
if (((PsiLambdaExpression)expression).getParameterList().getParametersCount() > 0){
return getFailedInferenceConstraint(typeParameter);
}
final PsiType functionalInterfaceType = PsiLambdaExpressionImpl.getFunctionalInterfaceType(((PsiLambdaExpression)expression), false);
if (functionalInterfaceType == null || PsiUtil.resolveClassInType(functionalInterfaceType) == typeParameter){
return getFailedInferenceConstraint(typeParameter);
}
}
}
}
@@ -57,7 +57,7 @@ class ReturnTypeCompatibility {
}
public static void main(String[] args) {
call(<error descr="Cyclic inference">i-> {return i;}</error>);
<error descr="Cannot resolve method 'call(<lambda expression>)'">call</error>(i-> {return i;});
}
}
@@ -0,0 +1,36 @@
import java.util.*;
class Test4 {
interface I<K> {
List<K> foo();
}
static <T> void bar(I<T> i){}
{
bar(() -> null);
}
}
class Test5 {
interface I<K> {
void foo(K k);
}
static <T> void bar(I<T> i){}
{
bar<error descr="'bar(Test5.I<T>)' in 'Test5' cannot be applied to '(<lambda expression>)'">(() -> null)</error>;
}
}
class Test6 {
interface I<K> {
void foo();
}
static <T> void bar(I<T> i){}
{
bar<error descr="'bar(Test6.I<java.lang.Object>)' in 'Test6' cannot be applied to '(<lambda expression>)'">(() -> null)</error>;
bar(() -> {});
}
}
@@ -49,6 +49,10 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testTypeArgsConsistencyWithoutParams() throws Exception {
doTest();
}
public void testWildcardBounds() throws Exception {
doTest();
}