mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-386630 [java-highlighting] Failed bounds check of type parameters on constructor calls leads to an error on the wrong part
GitOrigin-RevId: 06e1223d74cc9e040245cffe33b66a42ba75ec7f
This commit is contained in:
committed by
intellij-monorepo-bot
parent
3077e0155e
commit
bfaf4a4a18
+28
-21
@@ -32,6 +32,7 @@ import com.intellij.psi.PsiArrayType;
|
||||
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 @@ final class ExpressionChecker {
|
||||
}
|
||||
|
||||
void checkInferredTypeArguments(@NotNull PsiTypeParameterListOwner listOwner,
|
||||
@NotNull PsiMethodCallExpression call,
|
||||
@NotNull PsiCallExpression call,
|
||||
@NotNull PsiSubstitutor substitutor) {
|
||||
PsiTypeParameter[] typeParameters = listOwner.getTypeParameters();
|
||||
Pair<PsiTypeParameter, PsiType> inferredTypeArgument = GenericsUtil.findTypeParameterWithBoundError(
|
||||
@@ -1268,24 +1269,15 @@ final class ExpressionChecker {
|
||||
|
||||
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();
|
||||
}
|
||||
if (staticFactory instanceof MethodCandidateInfo info && info.isApplicable()) {
|
||||
result = info;
|
||||
if (constructor == null) {
|
||||
constructor = info.getElement();
|
||||
}
|
||||
else {
|
||||
applicable = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
applicable = result != null && result.isApplicable();
|
||||
}
|
||||
}
|
||||
catch (IndexNotReadyException ignored) {
|
||||
@@ -1300,24 +1292,39 @@ final class ExpressionChecker {
|
||||
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,
|
||||
|
||||
+5
-4
@@ -33,6 +33,7 @@ import com.intellij.psi.PsiAssertStatement;
|
||||
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 @@ public final class 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<PsiMethodCallExpression, TypeParameterBoundMismatchContext>
|
||||
public static final Parameterized<PsiCallExpression, TypeParameterBoundMismatchContext>
|
||||
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<PsiMethodCallExpression, TypeParameterBoundMismatchContext>
|
||||
public static final Parameterized<PsiCallExpression, TypeParameterBoundMismatchContext>
|
||||
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())));
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import java.util.function.Function;
|
||||
|
||||
class A {
|
||||
private <T extends Number> A(T t) {}
|
||||
|
||||
private static <T extends Number> void use(T t) {}
|
||||
|
||||
static {
|
||||
new <<error descr="Type parameter 'java.lang.String' is not within its bound; should extend 'java.lang.Number'">String</error>>A();
|
||||
A.<<error descr="Type parameter 'java.lang.String' is not within its bound; should extend 'java.lang.Number'">String</error>>use();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
static {
|
||||
new <error descr="Wrong number of type arguments: 2; required: 1">< String , Number ></error> <error descr="'A(java.lang.String)' has private access in 'A'">A</error> ( ) ;
|
||||
A . <error descr="Wrong number of type arguments: 2; required: 1">< String , Number ></error> <error descr="'use(java.lang.String)' has private access in 'A'">use</error> ( ) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class C {
|
||||
static {
|
||||
<error descr="Inferred type 'B' for type parameter 'B' is not within its bound; should extend 'C.Builder<C.Alfa>'">new C(C::string)</error>;
|
||||
<error descr="Inferred type 'B' for type parameter 'B' is not within its bound; should extend 'C.Builder<C.Alfa>'">C.use(C::string)</error>;
|
||||
}
|
||||
|
||||
private static <T extends Alfa, B extends Builder<T>> void use(final Function<B, String> f1) {}
|
||||
|
||||
private <T extends Alfa, B extends Builder<T>> C(final Function<B, String> f1) {}
|
||||
|
||||
private static String string(final Builder<? extends Beta> builder) {
|
||||
return "";
|
||||
}
|
||||
|
||||
static class Alfa {}
|
||||
static class Beta extends Alfa {}
|
||||
|
||||
static class Builder<T> {}
|
||||
}
|
||||
+3
@@ -1213,4 +1213,7 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
|
||||
|
||||
@TestFor(issues = "IDEA-385574")
|
||||
public void testIDEA385574(){ doTest(); }
|
||||
|
||||
@TestFor(issues = "IDEA-386630")
|
||||
public void testIDEA386630(){ doTest(); }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user