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 97e4d77e9495..98716b199593 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -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; + } } } } 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 17cb593b58a7..1a73fd6e64bb 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 @@ -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 currentSubstitution; if (argumentType instanceof PsiLambdaExpressionType) { currentSubstitution = inferSubstitutionFromLambda(typeParameter, (PsiLambdaExpressionType)argumentType, lowerBound); + if (rawType && currentSubstitution == FAILED_INFERENCE || nullPassed && currentSubstitution == null) return new Pair(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); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/LambdaOnVarargPlace.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/LambdaOnVarargPlace.java index 69a2478853d6..614065c91b0d 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/LambdaOnVarargPlace.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/LambdaOnVarargPlace.java @@ -1,14 +1,21 @@ -class Test { +class TestData {} +interface TerminalOp extends IntermediateOp {} +interface IntermediateOp { boolean _(L1 l, M1 m);} + +class Test { protected U exerciseOps(TestData data, TerminalOp terminal, IntermediateOp... ops) { return exerciseOps(data, terminal, (u, v) -> u.equals(v)); } +} - - - class TestData {} - interface TerminalOp extends IntermediateOp { - +class Test1 { + protected U exerciseOps(TestData data, TerminalOp terminal, IntermediateOp... ops) { + return exerciseOps(data, terminal, (u, v) -> u.equals(v)); } - interface IntermediateOp { boolean _(L1 l, M1 m);} +} -} \ No newline at end of file +class Test2 { + protected U exerciseOps(TestData data, TerminalOp terminal, IntermediateOp... ops) { + return exerciseOps(data, terminal, (u, v) -> u.equals(v)); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/LambdaRawOrNot.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/LambdaRawOrNot.java new file mode 100644 index 000000000000..f4dfd65eed29 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/LambdaRawOrNot.java @@ -0,0 +1,36 @@ +import java.util.*; +class TestData {} +interface TerminalOp extends IntermediateOp {} +interface IntermediateOp { boolean _(L1 l, M1 m);} + + +class Test1 { + protected U exerciseOps(TestData data, TerminalOp terminal, IntermediateOp... ops) { + return exerciseOps(data, (u, v) -> u.equals(v), terminal); + } +} + +class Test2 { + protected U exerciseOps(TestData data, TerminalOp terminal, IntermediateOp... ops) { + return exerciseOps(data, (u, v) -> u.equals(v), terminal); + } +} + +class Test3 { + interface I { + void m(Y y); + } + + static void bar(I i, List l){ + bar(x -> {}, l); + bar(x -> {}, null); + bar((I)x -> {}, null); + bar((T x) -> {}, null); + bar(x -> {}, new ArrayList()); + bar(x -> {}, new ArrayList()); + } + + static { + bar(x->{}, new ArrayList()); + } +} 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 4bb0ec0c0744..21f944434442 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 @@ -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();