diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index c630d666059f..a8a4ae72797d 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -1202,12 +1202,22 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression) .descriptionAndTooltip(HighlightUtil.buildProblemWithAccessDescription(expression, resolveResult)).create()); } - } - if (functionalInterfaceType != null && LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType) != null && !myHolder.hasErrorResults()) { - final String errorMessage = PsiMethodReferenceUtil.checkMethodReferenceContext(expression); - if (errorMessage != null) { - myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(errorMessage).create()); + final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); + if (interfaceMethod != null) { + if (!myHolder.hasErrorResults()) { + final String errorMessage = PsiMethodReferenceUtil.checkMethodReferenceContext(expression); + if (errorMessage != null) { + myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(errorMessage).create()); + } + } + + if (!myHolder.hasErrorResults()) { + final String badReturnTypeMessage = PsiMethodReferenceUtil.checkReturnType(expression, result, functionalInterfaceType); + if (badReturnTypeMessage != null) { + myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(badReturnTypeMessage).create()); + } + } } } } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java index 5727fe05524a..df72de732a5d 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java @@ -45,6 +45,36 @@ public class PsiMethodReferenceUtil { return false; } + public static String checkReturnType(PsiMethodReferenceExpression expression, JavaResolveResult result, PsiType functionalInterfaceType) { + final QualifierResolveResult qualifierResolveResult = getQualifierResolveResult(expression); + final PsiElement resolve = result.getElement(); + if (resolve instanceof PsiMethod) { + PsiSubstitutor subst = PsiSubstitutor.EMPTY; + subst = subst.putAll(qualifierResolveResult.getSubstitutor()); + subst = subst.putAll(result.getSubstitutor()); + + final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType); + + PsiType returnType = PsiTypesUtil.patchMethodGetClassReturnType(expression, expression, + (PsiMethod)resolve, null, + PsiUtil.getLanguageLevel(expression)); + if (returnType == null) { + returnType = ((PsiMethod)resolve).getReturnType(); + } + PsiType methodReturnType = subst.substitute(returnType); + if (interfaceReturnType != null && interfaceReturnType != PsiType.VOID) { + if (methodReturnType == null) { + methodReturnType = + JavaPsiFacade.getElementFactory(expression.getProject()).createType(((PsiMethod)resolve).getContainingClass(), subst); + } + if (!TypeConversionUtil.isAssignable(interfaceReturnType, methodReturnType, false)) { + return "Bad return type in method reference: cannot convert " + methodReturnType.getCanonicalText() + " to " + interfaceReturnType.getCanonicalText(); + } + } + } + return null; + } + public static class QualifierResolveResult { private final PsiClass myContainingClass; private final PsiSubstitutor mySubstitutor; @@ -178,7 +208,7 @@ public class PsiMethodReferenceUtil { if (methodReturnType == null) { methodReturnType = JavaPsiFacade.getElementFactory(methodReferenceExpression.getProject()).createType(((PsiMethod)resolve).getContainingClass(), subst); } - if (!TypeConversionUtil.isAssignable(interfaceReturnType, methodReturnType, false)) return false; + //if (!TypeConversionUtil.isAssignable(interfaceReturnType, methodReturnType, false)) return false; } if (areAcceptable(signature1, signature2, qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor(), ((PsiMethod)resolve).isVarArgs())) return true; } else if (resolve instanceof PsiClass) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/AccessModifiers.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/AccessModifiers.java index a00d50183870..bc235b224c31 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/AccessModifiers.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/AccessModifiers.java @@ -64,12 +64,12 @@ class MyTest1 { } void foo(Object[] arr) { - I1 c1 = arr :: clone; + I1 c1 = arr :: clone; I2 c2 = arr :: clone; - I3 c3 = arr::clone; - I4 c5 = arr::clone; + I3 c3 = arr::clone; + I4 c5 = arr::clone; I5 c4 = this::getClass; - I6 c6 = this::getClass; + I6 c6 = this::getClass; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/GetClassSpecifics.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/GetClassSpecifics.java index 6c5a26f6a87f..868fada42363 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/GetClassSpecifics.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/GetClassSpecifics.java @@ -10,6 +10,6 @@ class GetClassTest { void test(int[] iarr, List ls) { GetCl c4 = ls::getClass; - GetClReturnTypeProblems c5 = ls::getClass; + GetClReturnTypeProblems c5 = ls::getClass; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/InferenceFromReturnType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/InferenceFromReturnType.java index d158b7478f52..69fea2d6a671 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/InferenceFromReturnType.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/InferenceFromReturnType.java @@ -45,11 +45,11 @@ class MyTestConstructor { } private static void foo(I1 i) {System.out.println(i);} - private static void foo(I2 i) {System.out.println(i);} + private static void foo(I2 i) {System.out.println(i);} private static void foo(I3 i) {System.out.println(i);} static { - foo(Foo::new); + foo(Foo::new); } } @@ -74,10 +74,10 @@ class MyTestMethod { static Foo m() { return null; } private static void foo(I1 i) {System.out.println(i);} - private static void foo(I2 i) {System.out.println(i);} + private static void foo(I2 i) {System.out.println(i);} private static void foo(I3 i) {System.out.println(i);} static { - foo(MyTestMethod::m); + foo(MyTestMethod::m); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java index a86f8040ed5f..249114c65b88 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java @@ -20,7 +20,7 @@ class MyTest { System.out.println(i); } - private static void foo(I2 i) { + private static void foo(I2 i) { System.out.println(i); } @@ -29,7 +29,7 @@ class MyTest { } public static void main(String[] args) { - foo(Foo::m); + foo(Foo::m); } }