From 0f40eb9bed03f0535ed107492cd222086f6cbc6b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 10 Mar 2014 13:18:27 +0100 Subject: [PATCH] new inference: exact method reference is not pertinent to applicability when target type is type parameter (cherry picked from commit 8b3512a097ef1124a5cede6ade95b4e50017c7b9) --- .../graphInference/InferenceSession.java | 39 ++++++++++++------- ...eferencePertinentToApplicabilityCheck.java | 30 ++++++++++++++ .../lambda/NewMethodRefHighlightingTest.java | 4 ++ 3 files changed, 59 insertions(+), 14 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/ExactMethodReferencePertinentToApplicabilityCheck.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index 90b868d1cb8d..31332b704b54 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -113,14 +113,22 @@ public class InferenceSession { return null; } + /** + * Definition from 15.12.2.2 Phase 1: Identify Matching Arity Methods Applicable by Subtyping Strict Invocation + * An argument expression is considered pertinent to applicability for a potentially-applicable method m unless it has one of the following forms: + + 1) An implicitly-typed lambda expression (15.27.1). + 2) An inexact method reference (15.13.1). + 3) If m is a generic method and the method invocation does not provide explicit type arguments, an explicitly-typed lambda expression or + an exact method reference for which the corresponding target type (as derived from the signature of m) is a type parameter of m. + 4) An explicitly-typed lambda expression whose body is an expression that is not pertinent to applicability. + 5) An explicitly-typed lambda expression whose body is a block, where at least one result expression is not pertinent to applicability. + 6) A parenthesized expression (15.8.5) whose contained expression is not pertinent to applicability. + 7) A conditional expression (15.25) whose second or third operand is not pertinent to applicability. + */ public static boolean isPertinentToApplicability(PsiExpression expr, PsiMethod method) { - if (expr instanceof PsiLambdaExpression) { - if (!((PsiLambdaExpression)expr).hasFormalParameterTypes()) { - return false; - } - for (PsiExpression expression : LambdaUtil.getReturnExpressions((PsiLambdaExpression)expr)) { - if (!isPertinentToApplicability(expression, method)) return false; - } + if (expr instanceof PsiLambdaExpression && ((PsiLambdaExpression)expr).hasFormalParameterTypes() || + expr instanceof PsiMethodReferenceExpression && ((PsiMethodReferenceExpression)expr).isExact()) { if (method != null && method.getTypeParameters().length > 0) { final PsiElement parent = PsiUtil.skipParenthesizedExprUp(expr.getParent()); if (parent instanceof PsiExpressionList) { @@ -136,16 +144,19 @@ public class InferenceSession { else { paramType = parameters[idx].getType(); } - final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(paramType); + final PsiClass psiClass = PsiUtil.resolveClassInType(paramType); //accept ellipsis here if (psiClass instanceof PsiTypeParameter && ((PsiTypeParameter)psiClass).getOwner() == method) return false; } } - - for (PsiExpression expression : LambdaUtil.getReturnExpressions((PsiLambdaExpression)expr)) { - if (PsiPolyExpressionUtil.isPolyExpression(expression)) { - return false; - } - } + } + return true; + } + if (expr instanceof PsiLambdaExpression) { + if (!((PsiLambdaExpression)expr).hasFormalParameterTypes()) { + return false; + } + for (PsiExpression expression : LambdaUtil.getReturnExpressions((PsiLambdaExpression)expr)) { + if (!isPertinentToApplicability(expression, method)) return false; } return true; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/ExactMethodReferencePertinentToApplicabilityCheck.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/ExactMethodReferencePertinentToApplicabilityCheck.java new file mode 100644 index 000000000000..c76e109aa0ff --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/ExactMethodReferencePertinentToApplicabilityCheck.java @@ -0,0 +1,30 @@ + +import java.util.*; + +class Test { + { + List> a = asList(String::intern); + } + + public static List asList(Ta a) { + return null; + } + + interface UnaryOperator { + T apply(T t); + } +} + +class TestVarargs { + { + List> a = asList(String::intern); + } + + public static List asList(Ta... a) { + return null; + } + + interface UnaryOperator { + T apply(T t); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index 84cecc1b2d7d..14d4aa94ce2f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -185,6 +185,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testExactMethodReferencePertinentToApplicabilityCheck() throws Exception { + doTest(); + } + private void doTest() { doTest(false); }