diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ExpressionChecker.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ExpressionChecker.java index 2013e2d0d7f1f..196afa8fc5d98 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ExpressionChecker.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ExpressionChecker.java @@ -32,6 +32,7 @@ import com.intellij.psi.PsiAssignmentExpression; import com.intellij.psi.PsiBreakStatement; import com.intellij.psi.PsiCall; +import com.intellij.psi.PsiCallExpression; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClassObjectAccessExpression; import com.intellij.psi.PsiClassType; @@ -424,7 +425,7 @@ void checkMethodCall(@NotNull PsiMethodCallExpression methodCall) { } void checkInferredTypeArguments(@NotNull PsiTypeParameterListOwner listOwner, - @NotNull PsiMethodCallExpression call, + @NotNull PsiCallExpression call, @NotNull PsiSubstitutor substitutor) { PsiTypeParameter[] typeParameters = listOwner.getTypeParameters(); Pair inferredTypeArgument = GenericsUtil.findTypeParameterWithBoundError( @@ -1268,25 +1269,16 @@ else if (aClass.isInterface() && constructorCall instanceof PsiNewExpression new PsiMethod constructor = result == null ? null : result.getElement(); - boolean applicable = true; try { PsiDiamondType diamondType = constructorCall instanceof PsiNewExpression newExpression ? PsiDiamondType.getDiamondType(newExpression) : null; JavaResolveResult staticFactory = diamondType != null ? diamondType.getStaticFactory() : null; - if (staticFactory instanceof MethodCandidateInfo info) { - if (info.isApplicable()) { - result = info; - if (constructor == null) { - constructor = info.getElement(); - } - } - else { - applicable = false; + if (staticFactory instanceof MethodCandidateInfo info && info.isApplicable()) { + result = info; + if (constructor == null) { + constructor = info.getElement(); } } - else { - applicable = result != null && result.isApplicable(); - } } catch (IndexNotReadyException ignored) { } @@ -1300,24 +1292,39 @@ else if (aClass.isInterface() && constructorCall instanceof PsiNewExpression new constructorCall, new JavaErrorKinds.UnresolvedConstructorContext(aClass, results))); return; } + + if (constructorCall instanceof PsiNewExpression newExpression) { + PsiReferenceParameterList typeArgumentList = newExpression.getTypeArgumentList(); + myVisitor.myGenericsChecker.checkReferenceTypeArgumentList(constructor, typeArgumentList, result.getSubstitutor()); + } + if (classReference != null && !constructor.isDefaultConstructor() && (!result.isAccessible() || constructor.hasModifierProperty(PsiModifier.PROTECTED) && callingProtectedConstructorFromDerivedClass(constructorCall, aClass))) { myVisitor.myModifierChecker.reportAccessProblem(classReference, constructor, result); return; } - if (!applicable) { - checkIncompatibleCall(list, result); + if (myVisitor.hasErrorResults()) return; + + if (result.isApplicable()) { + checkVarargParameterErasureToBeAccessible(result, constructorCall); if (myVisitor.hasErrorResults()) return; + checkIncompatibleType(constructorCall, result, constructorCall); + } + else if (result.isTypeArgumentsApplicable()) { + checkIncompatibleCall(list, result); } else if (constructorCall instanceof PsiNewExpression newExpression) { + PsiReferenceParameterList typeArgumentList = newExpression.getTypeArgumentList(); - myVisitor.myGenericsChecker.checkReferenceTypeArgumentList(constructor, typeArgumentList, result.getSubstitutor()); - if (myVisitor.hasErrorResults()) return; + PsiSubstitutor applicabilitySubstitutor = result.getSubstitutor(false); + if (typeArgumentList.getTypeArguments().length == 0 && constructor.hasTypeParameters()) { + checkInferredTypeArguments(constructor, newExpression, applicabilitySubstitutor); + } + else { + myVisitor.myGenericsChecker.checkReferenceTypeArgumentList(constructor, typeArgumentList, applicabilitySubstitutor); + } } - checkVarargParameterErasureToBeAccessible(result, constructorCall); - if (myVisitor.hasErrorResults()) return; - checkIncompatibleType(constructorCall, result, constructorCall); } private static boolean callingProtectedConstructorFromDerivedClass(@NotNull PsiConstructorCall place, diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java index 236fa4642da24..cac56780c72f1 100644 --- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java +++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorKinds.java @@ -33,6 +33,7 @@ import com.intellij.psi.PsiAssignmentExpression; import com.intellij.psi.PsiBreakStatement; import com.intellij.psi.PsiCall; +import com.intellij.psi.PsiCallExpression; import com.intellij.psi.PsiCaseLabelElement; import com.intellij.psi.PsiCaseLabelElementList; import com.intellij.psi.PsiCatchSection; @@ -730,15 +731,15 @@ private JavaErrorKinds() {} parameterized(PsiMethodCallExpression.class, IncompatibleIntersectionContext.class, "type.parameter.incompatible.upper.bounds") .withRange((call, ctx) -> getRange(call)) .withDescription((call, ctx) -> message("type.parameter.incompatible.upper.bounds", ctx.parameter().getName(), ctx.message())); - public static final Parameterized + public static final Parameterized TYPE_PARAMETER_INFERRED_TYPE_NOT_WITHIN_EXTEND_BOUND = - parameterized(PsiMethodCallExpression.class, TypeParameterBoundMismatchContext.class, + parameterized(PsiCallExpression.class, TypeParameterBoundMismatchContext.class, "type.parameter.inferred.type.not.within.extend.bound") .withDescription((call, ctx) -> message("type.parameter.inferred.type.not.within.extend.bound", formatClass(ctx.parameter()), formatType(ctx.bound()), formatType(ctx.actualType()))); - public static final Parameterized + public static final Parameterized TYPE_PARAMETER_INFERRED_TYPE_NOT_WITHIN_IMPLEMENT_BOUND = - parameterized(PsiMethodCallExpression.class, TypeParameterBoundMismatchContext.class, + parameterized(PsiCallExpression.class, TypeParameterBoundMismatchContext.class, "type.parameter.inferred.type.not.within.implement.bound") .withDescription((call, ctx) -> message("type.parameter.inferred.type.not.within.implement.bound", formatClass(ctx.parameter()), formatType(ctx.bound()), formatType(ctx.actualType()))); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA386630.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA386630.java new file mode 100644 index 0000000000000..3bffded5cd40d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA386630.java @@ -0,0 +1,41 @@ +import java.util.function.Function; + +class A { + private A(T t) {} + + private static void use(T t) {} + + static { + new <String>A(); + A.<String>use(); + + } +} + +class B { + static { + new < String , Number > A ( ) ; + A . < String , Number > use ( ) ; + } +} + + +class C { + static { + new C(C::string); + C.use(C::string); + } + + private static > void use(final Function f1) {} + + private > C(final Function f1) {} + + private static String string(final Builder builder) { + return ""; + } + + static class Alfa {} + static class Beta extends Alfa {} + + static class Builder {} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GenericsHighlighting8Test.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GenericsHighlighting8Test.java index 49bec2abe0755..67f9297616325 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GenericsHighlighting8Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/lambda/GenericsHighlighting8Test.java @@ -1213,4 +1213,7 @@ public void testTooltipComponents() { @TestFor(issues = "IDEA-385574") public void testIDEA385574(){ doTest(); } + + @TestFor(issues = "IDEA-386630") + public void testIDEA386630(){ doTest(); } }