From 1fa0a6ade43f67aa64b6f6343c1d0fa67010eea4 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 17 Aug 2012 22:44:31 +0400 Subject: [PATCH] lambda: void return type compatibility (initial); functional interfaces without method params error messages --- .../src/com/intellij/psi/LambdaUtil.java | 33 ++++++++++------- .../source/resolve/PsiResolveHelperImpl.java | 11 ++++-- .../highlighting/ReturnTypeCompatibility.java | 2 +- .../TypeArgsConsistencyWithoutParams.java | 36 +++++++++++++++++++ .../daemon/lambda/LambdaHighlightingTest.java | 4 +++ 5 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistencyWithoutParams.java diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index d315730c807d..aba0c13d4589 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -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 returnExpressions = lambdaExpression.getReturnExpressions(); + for (PsiExpression returnValue : returnExpressions) { + if (returnValue.getType() != PsiType.VOID) return false; + } } } return true; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java index 5bb8634d7044..62d12a4a38d9 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java @@ -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); + } } } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java index eb2acb162cdd..b1d08e6f04ad 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java @@ -57,7 +57,7 @@ class ReturnTypeCompatibility { } public static void main(String[] args) { - call(i-> {return i;}); + call(i-> {return i;}); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistencyWithoutParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistencyWithoutParams.java new file mode 100644 index 000000000000..c0f95dcba9f9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/TypeArgsConsistencyWithoutParams.java @@ -0,0 +1,36 @@ +import java.util.*; +class Test4 { + interface I { + List foo(); + } + + static void bar(I i){} + + { + bar(() -> null); + } +} + +class Test5 { + interface I { + void foo(K k); + } + + static void bar(I i){} + + { + bar(() -> null); + } +} +class Test6 { + interface I { + void foo(); + } + + static void bar(I i){} + + { + bar(() -> null); + bar(() -> {}); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index ee15e97780c8..03d0d87c7731 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -49,6 +49,10 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testTypeArgsConsistencyWithoutParams() throws Exception { + doTest(); + } + public void testWildcardBounds() throws Exception { doTest(); }