diff --git a/java/codeserver/highlighting/resources/messages/JavaCompilationErrorBundle.properties b/java/codeserver/highlighting/resources/messages/JavaCompilationErrorBundle.properties
index 9516c78968ec..691d386c8725 100644
--- a/java/codeserver/highlighting/resources/messages/JavaCompilationErrorBundle.properties
+++ b/java/codeserver/highlighting/resources/messages/JavaCompilationErrorBundle.properties
@@ -164,12 +164,8 @@ constructor.ambiguous.implicit.call=Ambiguous implicit constructor call: both ''
constructor.no.default=There is no parameterless constructor available in ''{0}''
type.incompatible=Incompatible types. Found: ''{1}'', required: ''{0}''
-# {0} - left raw type, {1} - required type arguments row, {2} - right raw type, {3} - found type arguments row, {4} - reason, {5} - greyed title color
-type.incompatible.html.tooltip=\
-
\
- | Required type: | {0} | {1}
\
- | Provided: | {2} | {3}
\
-
{4}
+type.incompatible.tooltip.required.type=Required type:
+type.incompatible.tooltip.provided.type=Provided:
type.incompatible.reason.ambiguous.method.reference=
reason: method reference is ambiguous: both ''{0}'' and ''{1}'' match
type.incompatible.reason.inference=
reason: {0}
type.void.not.allowed='void' type is not allowed here
@@ -187,6 +183,9 @@ new.expression.diamond.not.allowed=Diamond operator is not allowed here
new.expression.diamond.not.applicable=Diamond operator is not applicable for non-parameterized types
new.expression.diamond.inference.failure={0}
new.expression.diamond.anonymous.inner.non.private=Cannot use '<>' due to non-private method which doesn't override or implement a method from a supertype
+new.expression.anonymous.implements.interface.with.type.arguments=Anonymous class implements interface; cannot have type arguments
+new.expression.arguments.to.default.constructor.call=Default constructor is invoked with arguments
+new.expression.unresolved.constructor=Cannot resolve constructor ''{0}''
reference.type.argument.static.class=Type arguments are not allowed here because class ''{0}'' is static
reference.type.needs.type.arguments=Improperly formed type: ''{0}'' needs type arguments because its qualifier has type arguments
@@ -239,8 +238,6 @@ call.formal.varargs.element.type.inaccessible.here=Formal varargs element type {
call.type.inference.error={0}
call.wrong.arguments=''{0}'' in ''{1}'' cannot be applied to ''{2}''
call.wrong.arguments.count.mismatch=Expected {0, choice, 0#no arguments|1#1 argument|1<{0} arguments} but found {1}
-call.type.mismatch.tooltip.required.type=Required type
-call.type.mismatch.tooltip.provided.type=Provided
array.illegal.initializer=Illegal initializer for ''{0}''
array.initializer.not.allowed=Array initializer is not allowed here
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 92ca65d7e1e8..a7a8c3c134c3 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
@@ -6,6 +6,7 @@ import com.intellij.core.JavaPsiBundle;
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds;
import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext;
import com.intellij.java.codeserver.highlighting.errors.JavaMismatchedCallContext;
+import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.util.Pair;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
@@ -15,6 +16,7 @@ import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.*;
import com.intellij.util.ObjectUtils;
+import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -466,16 +468,17 @@ final class ExpressionChecker {
}
PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
- checkConstructorCall(typeResult, expression, classType, classReference, expression.getArgumentList());
+ checkConstructorCall(typeResult, expression, classType, classReference);
}
void checkAmbiguousConstructorCall(@NotNull PsiJavaCodeReferenceElement ref, PsiElement resolved) {
if (resolved instanceof PsiClass psiClass &&
ref.getParent() instanceof PsiNewExpression newExpression && psiClass.getConstructors().length > 0) {
- if (newExpression.resolveMethod() == null && !PsiTreeUtil.findChildrenOfType(newExpression.getArgumentList(), PsiFunctionalExpression.class).isEmpty()) {
+ PsiExpressionList argumentList = newExpression.getArgumentList();
+ if (newExpression.resolveMethod() == null && !PsiTreeUtil.findChildrenOfType(argumentList, PsiFunctionalExpression.class).isEmpty()) {
PsiType type = newExpression.getType();
if (type instanceof PsiClassType classType) {
- checkConstructorCall(classType.resolveGenerics(), newExpression, type, newExpression.getClassReference(), ref);
+ checkConstructorCall(classType.resolveGenerics(), newExpression, type, newExpression.getClassReference());
}
}
}
@@ -614,11 +617,9 @@ final class ExpressionChecker {
}
void checkConstructorCall(@NotNull PsiClassType.ClassResolveResult typeResolveResult,
- @NotNull PsiConstructorCall constructorCall,
- @NotNull PsiType type,
- @Nullable PsiJavaCodeReferenceElement classReference,
- @Nullable PsiElement elementToHighlight) {
- if (elementToHighlight == null) return;
+ @NotNull PsiConstructorCall constructorCall,
+ @NotNull PsiType type,
+ @Nullable PsiJavaCodeReferenceElement classReference) {
PsiExpressionList list = constructorCall.getArgumentList();
if (list == null) return;
PsiClass aClass = typeResolveResult.getElement();
@@ -634,5 +635,101 @@ final class ExpressionChecker {
if (classReference != null && !resolveHelper.isAccessible(aClass, constructorCall, accessObjectClass)) {
myVisitor.myModifierChecker.reportAccessProblem(classReference, aClass, typeResolveResult);
}
+ PsiMethod[] constructors = aClass.getConstructors();
+ if (constructors.length == 0) {
+ if (!list.isEmpty()) {
+ myVisitor.report(JavaErrorKinds.NEW_EXPRESSION_ARGUMENTS_TO_DEFAULT_CONSTRUCTOR_CALL.create(constructorCall));
+ }
+ else if (classReference != null && aClass.hasModifierProperty(PsiModifier.PROTECTED) &&
+ callingProtectedConstructorFromDerivedClass(constructorCall, aClass)) {
+ myVisitor.myModifierChecker.reportAccessProblem(classReference, aClass, typeResolveResult);
+ }
+ else if (aClass.isInterface() && constructorCall instanceof PsiNewExpression newExpression) {
+ PsiReferenceParameterList typeArgumentList = newExpression.getTypeArgumentList();
+ if (typeArgumentList.getTypeArguments().length > 0) {
+ myVisitor.report(JavaErrorKinds.NEW_EXPRESSION_ANONYMOUS_IMPLEMENTS_INTERFACE_WITH_TYPE_ARGUMENTS.create(typeArgumentList));
+ }
+ }
+ return;
+ }
+ PsiElement place = list;
+ if (constructorCall instanceof PsiNewExpression newExpression) {
+ PsiAnonymousClass anonymousClass = newExpression.getAnonymousClass();
+ if (anonymousClass != null) place = anonymousClass;
+ }
+
+ JavaResolveResult[] results = resolveHelper.multiResolveConstructor((PsiClassType)type, list, place);
+ MethodCandidateInfo result = null;
+ if (results.length == 1) result = (MethodCandidateInfo)results[0];
+
+ 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;
+ }
+ }
+ else {
+ applicable = result != null && result.isApplicable();
+ }
+ }
+ catch (IndexNotReadyException ignored) {
+ }
+ if (constructor == null) {
+ if (IncompleteModelUtil.isIncompleteModel(list) &&
+ ContainerUtil.exists(results, r -> r instanceof MethodCandidateInfo info && info.isPotentiallyCompatible() == ThreeState.YES) &&
+ ContainerUtil.exists(list.getExpressions(), e -> IncompleteModelUtil.mayHaveUnknownTypeDueToPendingReference(e))) {
+ return;
+ }
+ myVisitor.report(JavaErrorKinds.NEW_EXPRESSION_UNRESOLVED_CONSTRUCTOR.create(
+ constructorCall, new JavaErrorKinds.UnresolvedConstructorContext(aClass, results)));
+ return;
+ }
+ if (classReference != null &&
+ (!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;
+ }
+ else if (constructorCall instanceof PsiNewExpression newExpression) {
+ PsiReferenceParameterList typeArgumentList = newExpression.getTypeArgumentList();
+ myVisitor.myGenericsChecker.checkReferenceTypeArgumentList(constructor, typeArgumentList, result.getSubstitutor());
+ if (myVisitor.hasErrorResults()) return;
+ }
+ checkVarargParameterErasureToBeAccessible(result, constructorCall);
+ if (myVisitor.hasErrorResults()) return;
+ checkIncompatibleType(constructorCall, result, constructorCall);
+ }
+
+ private static boolean callingProtectedConstructorFromDerivedClass(@NotNull PsiConstructorCall place,
+ @NotNull PsiClass constructorClass) {
+ // indirect instantiation via anonymous class is ok
+ if (place instanceof PsiNewExpression newExpression && newExpression.getAnonymousClass() != null) return false;
+ PsiElement curElement = place;
+ PsiClass containingClass = constructorClass.getContainingClass();
+ while (true) {
+ PsiClass aClass = PsiTreeUtil.getParentOfType(curElement, PsiClass.class);
+ if (aClass == null) return false;
+ curElement = aClass;
+ if ((aClass.isInheritor(constructorClass, true) || containingClass != null && aClass.isInheritor(containingClass, true))
+ && !JavaPsiFacade.getInstance(aClass.getProject()).arePackagesTheSame(aClass, constructorClass)) {
+ return true;
+ }
+ }
}
}
diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java
index 54094dc770d0..317bb8060500 100644
--- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java
+++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/JavaErrorVisitor.java
@@ -176,7 +176,7 @@ final class JavaErrorVisitor extends JavaElementVisitor {
if (!hasErrorResults()) {
PsiClass containingClass = Objects.requireNonNull(enumConstant.getContainingClass());
PsiClassType type = JavaPsiFacade.getElementFactory(myProject).createType(containingClass);
- myExpressionChecker.checkConstructorCall(type.resolveGenerics(), enumConstant, type, null, enumConstant.getArgumentList());
+ myExpressionChecker.checkConstructorCall(type.resolveGenerics(), enumConstant, type, null);
}
}
diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ModifierChecker.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ModifierChecker.java
index 90875084d21f..7351b3a61f40 100644
--- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ModifierChecker.java
+++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/ModifierChecker.java
@@ -181,6 +181,7 @@ final class ModifierChecker {
void reportAccessProblem(@NotNull PsiJavaCodeReferenceElement ref,
@NotNull PsiModifierListOwner resolved,
@NotNull JavaResolveResult result) {
+ result = withElement(result, resolved);
if (resolved.hasModifierProperty(PsiModifier.PRIVATE)) {
myVisitor.report(JavaErrorKinds.ACCESS_PRIVATE.create(ref, result));
return;
@@ -193,7 +194,7 @@ final class ModifierChecker {
PsiClass packageLocalClass = JavaPsiModifierUtil.getPackageLocalClassInTheMiddle(ref);
if (packageLocalClass != null) {
- result = getDelegate(result, packageLocalClass);
+ result = withElement(result, packageLocalClass);
}
if (resolved.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) || packageLocalClass != null) {
@@ -210,12 +211,12 @@ final class ModifierChecker {
// TODO: JPMS
}
-
- private static @NotNull JavaResolveResult getDelegate(@NotNull JavaResolveResult original, @NotNull PsiClass newClass) {
- return new PsiClassType.ClassResolveResult() {
+ private static @NotNull JavaResolveResult withElement(@NotNull JavaResolveResult original, @NotNull PsiElement newElement) {
+ if (newElement == original.getElement()) return original;
+ return new JavaResolveResult() {
@Override
- public PsiClass getElement() {
- return newClass;
+ public PsiElement getElement() {
+ return newElement;
}
@Override
@@ -225,27 +226,27 @@ final class ModifierChecker {
@Override
public boolean isPackagePrefixPackageReference() {
- return false;
+ return original.isPackagePrefixPackageReference();
}
@Override
public boolean isAccessible() {
- return false;
+ return original.isAccessible();
}
@Override
public boolean isStaticsScopeCorrect() {
- return true;
+ return original.isStaticsScopeCorrect();
}
@Override
public PsiElement getCurrentFileResolveScope() {
- return null;
+ return original.getCurrentFileResolveScope();
}
@Override
public boolean isValidResult() {
- return true;
+ return original.isValidResult();
}
};
}
diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorFormatUtil.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorFormatUtil.java
index 6158fc9d7b68..84dfb29dbddf 100644
--- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorFormatUtil.java
+++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaErrorFormatUtil.java
@@ -67,7 +67,8 @@ final class JavaErrorFormatUtil {
return symbolName == null ? "?" : symbolName;
}
- static @NotNull String formatArgumentTypes(@NotNull PsiExpressionList list, boolean shortNames) {
+ static @NotNull String formatArgumentTypes(@Nullable PsiExpressionList list, boolean shortNames) {
+ if (list == null) return "";
StringBuilder builder = new StringBuilder();
builder.append("(");
PsiExpression[] args = list.getExpressions();
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 4df069ce4638..7f990ccdf41d 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
@@ -418,8 +418,6 @@ public final class JavaErrorKinds {
.withRawDescription((list, owner) -> message("type.parameter.count.mismatch", list.getTypeArgumentCount(),
owner.getTypeParameters().length));
public static final Simple TYPE_PARAMETER_ACTUAL_INFERRED_MISMATCH = error("type.parameter.actual.inferred.mismatch");
- public static final Simple NEW_EXPRESSION_DIAMOND_NOT_APPLICABLE =
- error("new.expression.diamond.not.applicable");
public static final Simple METHOD_DUPLICATE =
error(PsiMethod.class, "method.duplicate")
@@ -592,6 +590,8 @@ public final class JavaErrorKinds {
public static final Simple EXPRESSION_EXPECTED = error("expression.expected");
+ public static final Simple NEW_EXPRESSION_DIAMOND_NOT_APPLICABLE =
+ error("new.expression.diamond.not.applicable");
public static final Simple NEW_EXPRESSION_QUALIFIED_MALFORMED =
error("new.expression.qualified.malformed");
public static final Parameterized NEW_EXPRESSION_QUALIFIED_STATIC_CLASS =
@@ -604,11 +604,21 @@ public final class JavaErrorKinds {
error("new.expression.diamond.not.allowed");
public static final Simple NEW_EXPRESSION_DIAMOND_ANONYMOUS_INNER_NON_PRIVATE =
error("new.expression.diamond.anonymous.inner.non.private");
+ public static final Simple NEW_EXPRESSION_ANONYMOUS_IMPLEMENTS_INTERFACE_WITH_TYPE_ARGUMENTS =
+ error("new.expression.anonymous.implements.interface.with.type.arguments");
public static final Parameterized
NEW_EXPRESSION_DIAMOND_INFERENCE_FAILURE =
parameterized(PsiReferenceParameterList.class, PsiDiamondType.DiamondInferenceResult.class, "new.expression.diamond.inference.failure")
.withRawDescription(
(list, inferenceResult) -> message("new.expression.diamond.inference.failure", inferenceResult.getErrorMessage()));
+ public static final Simple NEW_EXPRESSION_ARGUMENTS_TO_DEFAULT_CONSTRUCTOR_CALL =
+ error(PsiConstructorCall.class, "new.expression.arguments.to.default.constructor.call")
+ .withAnchor(call -> call.getArgumentList());
+ public static final Parameterized NEW_EXPRESSION_UNRESOLVED_CONSTRUCTOR =
+ parameterized(PsiConstructorCall.class, UnresolvedConstructorContext.class, "new.expression.unresolved.constructor")
+ .withAnchor((call, ctx) -> call.getArgumentList())
+ .withRawDescription((call, ctx) -> message("new.expression.unresolved.constructor",
+ ctx.psiClass().getName() + formatArgumentTypes(call.getArgumentList(), true)));
public static final Parameterized REFERENCE_TYPE_ARGUMENT_STATIC_CLASS =
parameterized(PsiReferenceParameterList.class, PsiClass.class, "reference.type.argument.static.class")
@@ -832,4 +842,8 @@ public final class JavaErrorKinds {
@NotNull PsiType actualType) {
}
+
+ public record UnresolvedConstructorContext(@NotNull PsiClass psiClass, @NotNull JavaResolveResult @NotNull [] results) {
+
+ }
}
diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaIncompatibleTypeErrorContext.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaIncompatibleTypeErrorContext.java
index c01e06280f80..1f603f712d0d 100644
--- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaIncompatibleTypeErrorContext.java
+++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaIncompatibleTypeErrorContext.java
@@ -14,6 +14,8 @@ import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import static com.intellij.openapi.util.text.HtmlChunk.*;
+
public record JavaIncompatibleTypeErrorContext(@NotNull PsiType lType, @Nullable PsiType rType,
@Nullable @Nls String reasonForIncompatibleTypes) {
private static final @NlsSafe String ANONYMOUS = "anonymous ";
@@ -44,23 +46,48 @@ public record JavaIncompatibleTypeErrorContext(@NotNull PsiType lType, @Nullable
}
private @NotNull HtmlChunk createTooltip(@NotNull @Nls String reason) {
- String styledReason = reason.isEmpty() ? "" :
- String.format("", reason);
+ HtmlChunk styledReason = reason.isEmpty() ? empty() :
+ tag("table").child(
+ tag("tr").child(
+ tag("td").style("padding-top: 10px; padding-left: 4px;").addRaw(reason)));
IncompatibleTypesTooltipComposer tooltipComposer = (lTypeString, lTypeArguments, rTypeString, rTypeArguments) ->
- HtmlChunk.raw(JavaCompilationErrorBundle.message("type.incompatible.html.tooltip",
- lTypeString, lTypeArguments,
- rTypeString, rTypeArguments,
- styledReason, JavaCompilationError.JAVA_DISPLAY_GRAYED));
+ createRequiredProvidedTypeMessage(lTypeString, lTypeArguments, rTypeString, rTypeArguments, styledReason);
return createIncompatibleTypesTooltip(tooltipComposer);
}
-
+
@NotNull HtmlChunk createDescription() {
PsiType baseLType = PsiUtil.convertAnonymousToBaseType(lType);
PsiType baseRType = rType == null ? null : PsiUtil.convertAnonymousToBaseType(rType);
boolean leftAnonymous = PsiUtil.resolveClassInClassTypeOnly(lType) instanceof PsiAnonymousClass;
String lTypeString = JavaErrorFormatUtil.formatType(leftAnonymous ? lType : baseLType);
String rTypeString = JavaErrorFormatUtil.formatType(leftAnonymous ? rType : baseRType);
- return HtmlChunk.raw(JavaCompilationErrorBundle.message("type.incompatible", lTypeString, rTypeString));
+ return raw(JavaCompilationErrorBundle.message("type.incompatible", lTypeString, rTypeString));
+ }
+
+ static @NotNull HtmlChunk createRequiredProvidedTypeMessage(@NotNull HtmlChunk lType,
+ @Nls @NotNull String lTypeArguments,
+ @NotNull HtmlChunk rType,
+ @Nls @NotNull String rTypeArguments,
+ @NotNull HtmlChunk styledReason) {
+ return html().child(
+ body().children(
+ tag("table").children(
+ tag("tr").children(
+ tag("td").style("padding: 0px 16px 8px 4px;").setClass(JavaCompilationError.JAVA_DISPLAY_GRAYED)
+ .addText(JavaCompilationErrorBundle.message("type.incompatible.tooltip.required.type")),
+ tag("td").style("padding: 0px 4px 8px 0px;").child(lType),
+ raw(lTypeArguments)
+ ),
+ tag("tr").children(
+ tag("td").style("padding: 0px 16px 0px 4px;").setClass(JavaCompilationError.JAVA_DISPLAY_GRAYED)
+ .addText(JavaCompilationErrorBundle.message("type.incompatible.tooltip.provided.type")),
+ tag("td").style("padding: 0px 4px 0px 0px;").child(rType),
+ raw(rTypeArguments)
+ )
+ ),
+ styledReason
+ )
+ );
}
@NotNull
@@ -109,9 +136,9 @@ public record JavaIncompatibleTypeErrorContext(@NotNull PsiType lType, @Nullable
PsiType rRawType = rType instanceof PsiClassType classType ? classType.rawType() : rType;
boolean assignable = rRawType == null || TypeConversionUtil.isAssignable(lRawType, rRawType);
boolean shortType = showShortType(lRawType, rRawType);
- return consumer.consume(redIfNotMatch(lRawType, true, shortType).toString(),
+ return consumer.consume(redIfNotMatch(lRawType, true, shortType),
requiredRow.toString(),
- redIfNotMatch(rRawType, assignable, shortType).toString(),
+ redIfNotMatch(rRawType, assignable, shortType),
foundRow.toString());
}
@@ -132,7 +159,7 @@ public record JavaIncompatibleTypeErrorContext(@NotNull PsiType lType, @Nullable
}
static @NotNull @NlsSafe HtmlChunk redIfNotMatch(@Nullable PsiType type, boolean matches, boolean shortType) {
- if (type == null) return HtmlChunk.empty();
+ if (type == null) return empty();
String typeText;
if (shortType || type instanceof PsiCapturedWildcardType) {
typeText = PsiUtil.resolveClassInClassTypeOnly(type) instanceof PsiAnonymousClass
@@ -142,7 +169,7 @@ public record JavaIncompatibleTypeErrorContext(@NotNull PsiType lType, @Nullable
else {
typeText = type.getCanonicalText();
}
- return HtmlChunk.span()
+ return span()
.setClass(matches ? JavaCompilationError.JAVA_DISPLAY_INFORMATION : JavaCompilationError.JAVA_DISPLAY_ERROR).addText(typeText);
}
@@ -159,9 +186,9 @@ public record JavaIncompatibleTypeErrorContext(@NotNull PsiType lType, @Nullable
interface IncompatibleTypesTooltipComposer {
@NotNull
@NlsContexts.Tooltip
- HtmlChunk consume(@NotNull @NlsSafe String lRawType,
+ HtmlChunk consume(@NotNull HtmlChunk lRawType,
@NotNull @NlsSafe String lTypeArguments,
- @NotNull @NlsSafe String rRawType,
+ @NotNull HtmlChunk rRawType,
@NotNull @NlsSafe String rTypeArguments);
/**
diff --git a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaMismatchedCallContext.java b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaMismatchedCallContext.java
index 4e8401c2cff6..f80ef7920555 100644
--- a/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaMismatchedCallContext.java
+++ b/java/codeserver/highlighting/src/com/intellij/java/codeserver/highlighting/errors/JavaMismatchedCallContext.java
@@ -3,7 +3,6 @@ package com.intellij.java.codeserver.highlighting.errors;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightMessageUtil;
import com.intellij.java.codeserver.highlighting.JavaCompilationErrorBundle;
-import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.text.HtmlBuilder;
import com.intellij.openapi.util.text.HtmlChunk;
import com.intellij.psi.*;
@@ -82,6 +81,23 @@ public record JavaMismatchedCallContext(@NotNull PsiExpressionList list,
return message.wrapWithHtmlBody();
}
+ private @NotNull HtmlChunk createOneArgMismatchTooltip(PsiExpression @NotNull [] expressions, PsiParameter @NotNull [] parameters) {
+ PsiExpression wrongArg = mismatchedExpressions.get(0);
+ PsiType argType = wrongArg != null ? wrongArg.getType() : null;
+ if (argType != null) {
+ int idx = ArrayUtil.find(expressions, wrongArg);
+ if (idx > parameters.length - 1 && !parameters[parameters.length - 1].isVarArgs()) return HtmlChunk.empty();
+ PsiType paramType =
+ candidate.getSubstitutor().substitute(PsiTypesUtil.getParameterType(parameters, idx, candidate.isVarargs()));
+ String errorMessage = candidate.getInferenceErrorMessage();
+ HtmlChunk reason = getTypeMismatchErrorHtml(errorMessage);
+ return new JavaIncompatibleTypeErrorContext(paramType, argType).createIncompatibleTypesTooltip(
+ (lRawType, lTypeArguments, rRawType, rTypeArguments) ->
+ createRequiredProvidedTypeMessage(lRawType, lTypeArguments, rRawType, rTypeArguments, reason));
+ }
+ return HtmlChunk.empty();
+ }
+
private static @NotNull HtmlChunk getTypeMismatchTable(@Nullable MethodCandidateInfo info,
@NotNull PsiSubstitutor substitutor,
PsiParameter @NotNull [] parameters,
@@ -90,10 +106,10 @@ public record JavaMismatchedCallContext(@NotNull PsiExpressionList list,
HtmlChunk.Element td = HtmlChunk.tag("td");
HtmlChunk requiredHeader = td.style("padding-left: 16px; padding-right: 24px;")
.setClass(JavaCompilationError.JAVA_DISPLAY_GRAYED)
- .addText(JavaCompilationErrorBundle.message("call.type.mismatch.tooltip.required.type"));
+ .addText(JavaCompilationErrorBundle.message("type.incompatible.tooltip.required.type"));
HtmlChunk providedHeader = td.style("padding-right: 28px;")
.setClass(JavaCompilationError.JAVA_DISPLAY_GRAYED)
- .addText(JavaCompilationErrorBundle.message("call.type.mismatch.tooltip.provided.type"));
+ .addText(JavaCompilationErrorBundle.message("type.incompatible.tooltip.provided.type"));
table.append(HtmlChunk.tag("tr").children(td, requiredHeader, providedHeader));
String parameterNameStyle = "padding:1px 4px 1px 4px;";
@@ -132,16 +148,16 @@ public record JavaMismatchedCallContext(@NotNull PsiExpressionList list,
}
return table.wrapWith("table");
}
-
+
private static @NotNull HtmlChunk mismatchedExpressionType(PsiType parameterType, @NotNull PsiExpression expression) {
return new JavaIncompatibleTypeErrorContext(parameterType, expression.getType()).createIncompatibleTypesTooltip(
new IncompatibleTypesTooltipComposer() {
- @Override
- public @NotNull HtmlChunk consume(@NotNull @NlsSafe String lRawType,
- @NotNull @NlsSafe String lTypeArguments,
- @NotNull @NlsSafe String rRawType,
- @NotNull @NlsSafe String rTypeArguments) {
- return new HtmlBuilder().appendRaw(rRawType).appendRaw(rTypeArguments).toFragment();
+ @Override
+ public @NotNull HtmlChunk consume(@NotNull HtmlChunk lRawType,
+ @NotNull String lTypeArguments,
+ @NotNull HtmlChunk rRawType,
+ @NotNull String rTypeArguments) {
+ return new HtmlBuilder().append(rRawType).appendRaw(rTypeArguments).toFragment();
}
@Override
@@ -150,25 +166,6 @@ public record JavaMismatchedCallContext(@NotNull PsiExpressionList list,
}
});
}
-
- private @NotNull HtmlChunk createOneArgMismatchTooltip(PsiExpression @NotNull [] expressions, PsiParameter @NotNull [] parameters) {
- PsiExpression wrongArg = mismatchedExpressions.get(0);
- PsiType argType = wrongArg != null ? wrongArg.getType() : null;
- if (argType != null) {
- int idx = ArrayUtil.find(expressions, wrongArg);
- if (idx > parameters.length - 1 && !parameters[parameters.length - 1].isVarArgs()) return HtmlChunk.empty();
- PsiType paramType =
- candidate.getSubstitutor().substitute(PsiTypesUtil.getParameterType(parameters, idx, candidate.isVarargs()));
- String errorMessage = candidate.getInferenceErrorMessage();
- HtmlChunk reason = getTypeMismatchErrorHtml(errorMessage);
- return new JavaIncompatibleTypeErrorContext(paramType, argType).createIncompatibleTypesTooltip(
- (lRawType, lTypeArguments, rRawType, rTypeArguments) ->
- HtmlChunk.raw(JavaCompilationErrorBundle.message("type.incompatible.html.tooltip",
- lRawType, lTypeArguments, rRawType, rTypeArguments, reason,
- JavaCompilationError.JAVA_DISPLAY_GRAYED)));
- }
- return HtmlChunk.empty();
- }
private static @NotNull HtmlChunk createMismatchedArgumentCountTooltip(int expected, int actual) {
return HtmlChunk.text(JavaCompilationErrorBundle.message("call.wrong.arguments.count.mismatch", expected, actual))
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightFixUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightFixUtil.java
index d25619c66ae8..5991c97b6909 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightFixUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightFixUtil.java
@@ -642,21 +642,16 @@ public final class HighlightFixUtil {
static void registerFixesOnInvalidConstructorCall(@NotNull Consumer super CommonIntentionAction> info,
@NotNull PsiConstructorCall constructorCall,
- @Nullable PsiJavaCodeReferenceElement classReference,
- @NotNull PsiExpressionList list,
@NotNull PsiClass aClass,
- PsiMethod @NotNull [] constructors,
JavaResolveResult @NotNull [] results) {
- if (classReference != null) {
- ConstructorParametersFixer.registerFixActions(classReference, constructorCall, info);
- ChangeTypeArgumentsFix.registerIntentions(results, list, info, aClass);
- }
- else if (aClass.isEnum()) {
- ConstructorParametersFixer.registerFixActions(aClass, PsiSubstitutor.EMPTY, constructorCall, info);
- }
+ ConstructorParametersFixer.registerFixActions(constructorCall, info);
+ ChangeTypeArgumentsFix.registerIntentions(results, constructorCall, info, aClass);
+ PsiMethod[] constructors = aClass.getConstructors();
ChangeStringLiteralToCharInMethodCallFix.registerFixes(constructors, constructorCall, info);
IntentionAction action = QuickFixFactory.getInstance().createSurroundWithArrayFix(constructorCall, null);
info.accept(action);
+ PsiExpressionList list = constructorCall.getArgumentList();
+ if (list == null) return;
if (!PermuteArgumentsFix.registerFix(info, constructorCall, toMethodCandidates(results))) {
registerChangeMethodSignatureFromUsageIntentions(results, list, info);
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
index fb7b34d0f942..6c3de627af62 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
@@ -12,15 +12,10 @@ import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixUpdater;
import com.intellij.codeInspection.LocalQuickFixOnPsiElementAsIntentionAdapter;
import com.intellij.core.JavaPsiBundle;
-import com.intellij.java.analysis.JavaAnalysisBundle;
-import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
-import com.intellij.openapi.editor.colors.EditorColorsUtil;
-import com.intellij.openapi.project.IndexNotReadyException;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.projectRoots.JavaSdkVersion;
-import com.intellij.openapi.util.*;
-import com.intellij.openapi.util.text.HtmlBuilder;
-import com.intellij.openapi.util.text.HtmlChunk;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.NlsContexts;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.JavaFeature;
@@ -33,11 +28,10 @@ import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.*;
import com.intellij.refactoring.util.RefactoringChangeUtil;
-import com.intellij.ui.ColorUtil;
-import com.intellij.util.*;
+import com.intellij.util.JavaPsiConstructorUtil;
+import com.intellij.util.ObjectUtils;
+import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.StartupUiUtil;
-import com.intellij.util.ui.UIUtil;
import com.intellij.xml.util.XmlStringUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.intellij.lang.annotations.Language;
@@ -46,10 +40,8 @@ import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.awt.*;
import java.text.MessageFormat;
import java.util.*;
-import java.util.List;
import java.util.function.Consumer;
import static com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil.asConsumer;
@@ -189,90 +181,6 @@ public final class HighlightMethodUtil {
return errorResult;
}
- /**
- * collect highlightInfos per each wrong argument; fixes would be set for the first one with fixRange: methodCall
- * @return highlight info for the first wrong arg expression
- */
- private static List createIncompatibleCallHighlightInfo(@NotNull PsiExpressionList list,
- @NotNull MethodCandidateInfo candidateInfo) {
- if (PsiTreeUtil.hasErrorElements(list)) return null;
- PsiMethod resolvedMethod = candidateInfo.getElement();
- PsiSubstitutor substitutor = candidateInfo.getSubstitutor();
- String methodName = HighlightMessageUtil.getSymbolName(resolvedMethod, substitutor);
- PsiClass parent = resolvedMethod.getContainingClass();
- String containerName = parent == null ? "" : HighlightMessageUtil.getSymbolName(parent, substitutor);
- String argTypes = buildArgTypesList(list, false);
- String description = JavaErrorBundle.message("wrong.method.arguments", methodName, containerName, argTypes);
- String toolTip = null;
- List mismatchedExpressions;
- if (parent != null) {
- PsiExpression[] expressions = list.getExpressions();
- PsiParameter[] parameters = resolvedMethod.getParameterList().getParameters();
- mismatchedExpressions = mismatchedArgs(expressions, substitutor, parameters, candidateInfo.isVarargs());
- if (mismatchedExpressions.size() == 1 && parameters.length > 0) {
- toolTip = createOneArgMismatchTooltip(candidateInfo, mismatchedExpressions, expressions, parameters);
- }
- if (toolTip == null) {
- if ((parameters.length == 0 || !parameters[parameters.length - 1].isVarArgs()) &&
- parameters.length != expressions.length) {
- toolTip = createMismatchedArgumentCountTooltip(parameters.length, expressions.length);
- description = JavaAnalysisBundle.message("arguments.count.mismatch", parameters.length, expressions.length);
- }
- else if (mismatchedExpressions.isEmpty()) {
- if (IncompleteModelUtil.isIncompleteModel(list)) return null;
- toolTip = XmlStringUtil.escapeString(description);
- }
- else {
- toolTip = createMismatchedArgumentsHtmlTooltip(candidateInfo, list);
- }
- }
- }
- else {
- mismatchedExpressions = Collections.emptyList();
- toolTip = XmlStringUtil.escapeString(description);
- }
-
- if (mismatchedExpressions.size() == list.getExpressions().length || mismatchedExpressions.isEmpty()) {
- if (list.getTextRange().isEmpty()) {
- return List.of(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
- .range(ObjectUtils.notNull(list.getPrevSibling(), list))
- .description(description)
- .escapedToolTip(toolTip));
- }
- return List.of(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(list).description(description).escapedToolTip(toolTip).navigationShift(1));
- }
- else {
- List infos = new ArrayList<>();
- for (PsiExpression wrongArg : mismatchedExpressions) {
- HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(wrongArg)
- .description(description)
- .escapedToolTip(toolTip);
- infos.add(info);
- }
- return infos;
- }
- }
-
- private static @NlsContexts.Tooltip String createOneArgMismatchTooltip(@NotNull MethodCandidateInfo candidateInfo,
- @NotNull List extends PsiExpression> mismatchedExpressions,
- PsiExpression @NotNull [] expressions,
- PsiParameter @NotNull [] parameters) {
- PsiExpression wrongArg = mismatchedExpressions.get(0);
- PsiType argType = wrongArg != null ? wrongArg.getType() : null;
- if (argType != null) {
- int idx = ArrayUtil.find(expressions, wrongArg);
- if (idx > parameters.length - 1 && !parameters[parameters.length - 1].isVarArgs()) return null;
- PsiType paramType = candidateInfo.getSubstitutor().substitute(PsiTypesUtil.getParameterType(parameters, idx, candidateInfo.isVarargs()));
- String errorMessage = candidateInfo.getInferenceErrorMessage();
- HtmlChunk reason = getTypeMismatchErrorHtml(errorMessage);
- return HighlightUtil.createIncompatibleTypesTooltip(
- paramType, argType, (lRawType, lTypeArguments, rRawType, rTypeArguments) ->
- JavaErrorBundle.message("incompatible.types.html.tooltip",
- lRawType, lTypeArguments, rRawType, rTypeArguments, reason, ColorUtil.toHtmlColor(UIUtil.getContextHelpForeground())));
- }
- return null;
- }
-
static HighlightInfo.Builder createIncompatibleTypeHighlightInfo(@NotNull PsiCall methodCall,
@NotNull MethodCandidateInfo resolveResult,
@NotNull PsiElement elementToHighlight) {
@@ -380,20 +288,6 @@ public final class HighlightMethodUtil {
return JavaErrorBundle.message("static.interface.method.call.qualifier");
}
- private static @NotNull List mismatchedArgs(PsiExpression @NotNull [] expressions,
- PsiSubstitutor substitutor,
- PsiParameter @NotNull [] parameters,
- boolean varargs) {
- List result = new ArrayList<>();
- for (int i = 0; i < Math.max(parameters.length, expressions.length); i++) {
- if (parameters.length == 0 || !assignmentCompatible(i, parameters, expressions, substitutor, varargs)) {
- result.add(i < expressions.length ? expressions[i] : null);
- }
- }
-
- return result;
- }
-
static boolean isDummyConstructorCall(@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiResolveHelper resolveHelper,
@NotNull PsiExpressionList list,
@@ -641,132 +535,6 @@ public final class HighlightMethodUtil {
return ms.toString();
}
- private static @NotNull @NlsContexts.Tooltip String createMismatchedArgumentsHtmlTooltip(@NotNull MethodCandidateInfo info, @NotNull PsiExpressionList list) {
- PsiMethod method = info.getElement();
- PsiSubstitutor substitutor = info.getSubstitutor();
- PsiParameter[] parameters = method.getParameterList().getParameters();
- return createMismatchedArgumentsHtmlTooltip(list, info, parameters, substitutor);
- }
-
- @Language("HTML")
- private static @NotNull @NlsContexts.Tooltip String createMismatchedArgumentsHtmlTooltip(@NotNull PsiExpressionList list,
- @Nullable MethodCandidateInfo info,
- PsiParameter @NotNull [] parameters,
- @NotNull PsiSubstitutor substitutor) {
- PsiExpression[] expressions = list.getExpressions();
- if ((parameters.length == 0 || !parameters[parameters.length - 1].isVarArgs()) &&
- parameters.length != expressions.length) {
- return createMismatchedArgumentCountTooltip(parameters.length, expressions.length);
- }
-
- HtmlBuilder message = new HtmlBuilder();
- message.append(getTypeMismatchTable(info, substitutor, parameters, expressions));
-
- String errorMessage = info != null ? info.getInferenceErrorMessage() : null;
- message.append(getTypeMismatchErrorHtml(errorMessage));
- return message.wrapWithHtmlBody().toString();
- }
-
- private static @NotNull @NlsContexts.Tooltip String createMismatchedArgumentCountTooltip(int expected, int actual) {
- return HtmlChunk.text(JavaAnalysisBundle.message("arguments.count.mismatch", expected, actual)).wrapWith("html").toString();
- }
-
- private static @NotNull HtmlChunk getTypeMismatchErrorHtml(@Nls String errorMessage) {
- if (errorMessage == null) {
- return HtmlChunk.empty();
- }
- return HtmlChunk.tag("td").style("padding-left: 4px; padding-top: 10;")
- .addText(JavaAnalysisBundle.message("type.mismatch.reason", errorMessage))
- .wrapWith("tr").wrapWith("table");
- }
-
- private static @NotNull HtmlChunk getTypeMismatchTable(@Nullable MethodCandidateInfo info,
- @NotNull PsiSubstitutor substitutor,
- PsiParameter @NotNull [] parameters,
- PsiExpression[] expressions) {
- String greyedColor = ColorUtil.toHtmlColor(UIUtil.getContextHelpForeground());
- HtmlBuilder table = new HtmlBuilder();
- HtmlChunk.Element td = HtmlChunk.tag("td");
- HtmlChunk requiredHeader = td.style("color: " + greyedColor + "; padding-left: 16px; padding-right: 24px;")
- .addText(JavaAnalysisBundle.message("required.type"));
- HtmlChunk providedHeader = td.style("color: " + greyedColor + "; padding-right: 28px;")
- .addText(JavaAnalysisBundle.message("provided.type"));
- table.append(HtmlChunk.tag("tr").children(td, requiredHeader, providedHeader));
-
- String parameterNameStyle = String.format("color: %s; font-size:%dpt; padding:1px 4px 1px 4px;",
- greyedColor,
- StartupUiUtil.getLabelFont().getSize() - (SystemInfo.isWindows ? 0 : 1));
-
- Color paramBgColor = EditorColorsUtil.getGlobalOrDefaultColorScheme()
- .getAttributes(DefaultLanguageHighlighterColors.INLINE_PARAMETER_HINT)
- .getBackgroundColor();
- if (paramBgColor != null) {
- parameterNameStyle += "background-color: " + ColorUtil.toHtmlColor(paramBgColor) + ";";
- }
-
- boolean varargAdded = false;
- for (int i = 0; i < Math.max(parameters.length, expressions.length); i++) {
- boolean varargs = info != null && info.isVarargs();
- if (assignmentCompatible(i, parameters, expressions, substitutor, varargs)) continue;
- PsiParameter parameter = null;
- if (i < parameters.length) {
- parameter = parameters[i];
- varargAdded = parameter.isVarArgs();
- }
- else if (!varargAdded) {
- parameter = parameters[parameters.length - 1];
- varargAdded = true;
- }
- PsiType parameterType = substitutor.substitute(PsiTypesUtil.getParameterType(parameters, i, varargs));
- PsiExpression expression = i < expressions.length ? expressions[i] : null;
- boolean showShortType = HighlightUtil.showShortType(parameterType,
- expression != null ? expression.getType() : null);
- HtmlChunk.Element nameCell = td;
- HtmlChunk.Element typeCell = td.style("padding-left: 16px; padding-right: 24px;");
- if (parameter != null) {
- nameCell = nameCell.child(td.style(parameterNameStyle).addText(parameter.getName() + ":")
- .wrapWith("tr").wrapWith("table"));
- typeCell = typeCell.child(HighlightUtil.redIfNotMatch(substitutor.substitute(parameter.getType()), true, showShortType));
- }
-
- HtmlChunk.Element mismatchedCell = td.style("padding-right: 28px;");
- if (expression != null) {
- mismatchedCell = mismatchedCell.child(mismatchedExpressionType(parameterType, expression));
- }
- table.append(HtmlChunk.tag("tr").children(nameCell, typeCell, mismatchedCell));
- }
- return table.wrapWith("table");
- }
-
- private static @NotNull @Nls HtmlChunk mismatchedExpressionType(PsiType parameterType, @NotNull PsiExpression expression) {
- return HtmlChunk.raw(HighlightUtil.createIncompatibleTypesTooltip(parameterType, expression.getType(), new HighlightUtil.IncompatibleTypesTooltipComposer() {
- @Override
- public @NotNull String consume(@NotNull @NlsSafe String lRawType,
- @NotNull @NlsSafe String lTypeArguments,
- @NotNull @NlsSafe String rRawType,
- @NotNull @NlsSafe String rTypeArguments) {
- return rRawType + rTypeArguments;
- }
-
- @Override
- public boolean skipTypeArgsColumns() {
- return true;
- }
- }));
- }
-
- private static boolean assignmentCompatible(int i,
- PsiParameter @NotNull [] parameters,
- PsiExpression @NotNull [] expressions,
- @NotNull PsiSubstitutor substitutor,
- boolean varargs) {
- PsiExpression expression = i < expressions.length ? expressions[i] : null;
- if (expression == null) return true;
- PsiType paramType = substitutor.substitute(PsiTypesUtil.getParameterType(parameters, i, varargs));
- return paramType != null && TypeConversionUtil.areTypesAssignmentCompatible(paramType, expression) ||
- IncompleteModelUtil.isIncompleteModel(expression) && IncompleteModelUtil.isPotentiallyConvertible(paramType, expression);
- }
-
static HighlightInfo.Builder checkAbstractMethodInConcreteClass(@NotNull PsiMethod method, @NotNull PsiElement elementToHighlight) {
HighlightInfo.Builder errorResult = null;
PsiClass aClass = method.getContainingClass();
@@ -905,234 +673,6 @@ public final class HighlightMethodUtil {
return range;
}
- static void checkNewExpression(@NotNull Project project, @NotNull PsiNewExpression expression,
- @Nullable PsiType type,
- @NotNull JavaSdkVersion javaSdkVersion, @NotNull Consumer super HighlightInfo.Builder> errorSink) {
- if (!(type instanceof PsiClassType classType)) return;
- PsiClassType.ClassResolveResult typeResult = classType.resolveGenerics();
- PsiClass aClass = typeResult.getElement();
- if (aClass == null) return;
- if (aClass instanceof PsiAnonymousClass anonymousClass) {
- classType = anonymousClass.getBaseClassType();
- typeResult = classType.resolveGenerics();
- aClass = typeResult.getElement();
- if (aClass == null) return;
- }
-
- PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
- checkConstructorCall(project, typeResult, expression, classType, classReference, javaSdkVersion, expression.getArgumentList(), errorSink);
- }
-
- static void checkAmbiguousConstructorCall(@NotNull Project project, PsiJavaCodeReferenceElement ref,
- PsiElement resolved,
- PsiElement parent,
- JavaSdkVersion version, @NotNull Consumer super HighlightInfo.Builder> errorSink) {
- if (resolved instanceof PsiClass psiClass &&
- parent instanceof PsiNewExpression newExpression && psiClass.getConstructors().length > 0) {
- if (newExpression.resolveMethod() == null && !PsiTreeUtil.findChildrenOfType(newExpression.getArgumentList(), PsiFunctionalExpression.class).isEmpty()) {
- PsiType type = newExpression.getType();
- if (type instanceof PsiClassType classType) {
- checkConstructorCall(project, classType.resolveGenerics(), newExpression, type, newExpression.getClassReference(), version, ref,
- errorSink);
- }
- }
- }
- }
-
- static void checkConstructorCall(@NotNull Project project, @NotNull PsiClassType.ClassResolveResult typeResolveResult,
- @NotNull PsiConstructorCall constructorCall,
- @NotNull PsiType type,
- @Nullable PsiJavaCodeReferenceElement classReference,
- @NotNull JavaSdkVersion javaSdkVersion,
- @Nullable PsiElement elementToHighlight,
- @NotNull Consumer super HighlightInfo.Builder> errorSink) {
- if (elementToHighlight == null) return;
- PsiExpressionList list = constructorCall.getArgumentList();
- if (list == null) return;
- PsiClass aClass = typeResolveResult.getElement();
- if (aClass == null) return;
- PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
- PsiClass accessObjectClass = null;
- if (constructorCall instanceof PsiNewExpression newExpression) {
- PsiExpression qualifier = newExpression.getQualifier();
- if (qualifier != null) {
- accessObjectClass = (PsiClass)PsiUtil.getAccessObjectClass(qualifier).getElement();
- }
- }
- PsiMethod[] constructors = aClass.getConstructors();
-
- if (constructors.length == 0) {
- if (!list.isEmpty()) {
- String constructorName = aClass.getName();
- String argTypes = buildArgTypesList(list, false);
- String description = JavaErrorBundle.message("wrong.constructor.arguments", constructorName + "()", argTypes);
- String tooltip = createMismatchedArgumentsHtmlTooltip(list, null, PsiParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
- HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(list).description(description).escapedToolTip(tooltip).navigationShift(+1);
- if (classReference != null) {
- ConstructorParametersFixer.registerFixActions(classReference, constructorCall, asConsumer(info));
- }
- TextRange textRange = constructorCall.getTextRange();
- QuickFixAction.registerQuickFixActions(
- info, textRange, QuickFixFactory.getInstance().createCreateConstructorFromUsageFixes(constructorCall)
- );
- RemoveRedundantArgumentsFix.registerIntentions(list, asConsumer(info));
- errorSink.accept(info);
- return;
- }
- if (classReference != null && aClass.hasModifierProperty(PsiModifier.PROTECTED) && callingProtectedConstructorFromDerivedClass(constructorCall, aClass)) {
- HighlightInfo.Builder info = buildAccessProblem(classReference, aClass, typeResolveResult);
- errorSink.accept(info);
- }
- else if (aClass.isInterface() && constructorCall instanceof PsiNewExpression newExpression) {
- PsiReferenceParameterList typeArgumentList = newExpression.getTypeArgumentList();
- if (typeArgumentList.getTypeArguments().length > 0) {
- HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeArgumentList)
- .descriptionAndTooltip(JavaErrorBundle.message("anonymous.class.implements.interface.cannot.have.type.arguments"));
- errorSink.accept(info);
- }
- }
- return;
- }
-
- PsiElement place = list;
- if (constructorCall instanceof PsiNewExpression newExpression) {
- PsiAnonymousClass anonymousClass = newExpression.getAnonymousClass();
- if (anonymousClass != null) place = anonymousClass;
- }
-
- JavaResolveResult[] results = resolveHelper.multiResolveConstructor((PsiClassType)type, list, place);
- MethodCandidateInfo result = null;
- if (results.length == 1) result = (MethodCandidateInfo)results[0];
-
- 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;
- }
- }
- else {
- applicable = result != null && result.isApplicable();
- }
- }
- catch (IndexNotReadyException ignored) {
- }
- boolean reported = false;
- if (constructor == null) {
- if (IncompleteModelUtil.isIncompleteModel(list) &&
- ContainerUtil.exists(results, r -> r instanceof MethodCandidateInfo info && info.isPotentiallyCompatible() == ThreeState.YES) &&
- ContainerUtil.exists(list.getExpressions(), e -> IncompleteModelUtil.mayHaveUnknownTypeDueToPendingReference(e))) {
- return;
- }
- String name = aClass.getName();
- name += buildArgTypesList(list, true);
- String description = JavaErrorBundle.message("cannot.resolve.constructor", name);
- HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
- .range(elementToHighlight).descriptionAndTooltip(description);
- WrapExpressionFix.registerWrapAction(results, list.getExpressions(), asConsumer(info));
- HighlightFixUtil.registerFixesOnInvalidConstructorCall(asConsumer(info), constructorCall, classReference, list, aClass, constructors, results);
- errorSink.accept(info);
- reported = true;
- }
- else if (classReference != null &&
- (!result.isAccessible() ||
- constructor.hasModifierProperty(PsiModifier.PROTECTED) && callingProtectedConstructorFromDerivedClass(constructorCall, aClass))) {
- HighlightInfo.Builder info = buildAccessProblem(classReference, constructor, result);
- errorSink.accept(info);
- reported = true;
- }
- else if (!applicable) {
- List infos = createIncompatibleCallHighlightInfo(list, result);
- if (infos != null) {
- JavaResolveResult[] methodCandidates = results;
- if (constructorCall instanceof PsiNewExpression newExpression) {
- methodCandidates = resolveHelper.getReferencedMethodCandidates(newExpression, true);
- }
- for (HighlightInfo.Builder info : infos) {
- HighlightFixUtil.registerFixesOnInvalidConstructorCall(asConsumer(info), constructorCall, classReference, list, aClass, constructors,
- methodCandidates);
- HighlightFixUtil.registerMethodReturnFixAction(asConsumer(info), result, constructorCall);
- errorSink.accept(info);
- }
- reported = true;
- }
- }
- else if (constructorCall instanceof PsiNewExpression newExpression) {
- PsiReferenceParameterList typeArgumentList = newExpression.getTypeArgumentList();
- HighlightInfo.Builder info = GenericsHighlightUtil.checkReferenceTypeArgumentList(constructor, typeArgumentList, result.getSubstitutor(), false, javaSdkVersion);
- if (info != null) {
- errorSink.accept(info);
- reported = true;
- }
- }
-
- HighlightInfo.Builder info = result == null || reported ? null : checkVarargParameterErasureToBeAccessible(result, constructorCall);
- if (result != null && info == null && !reported) {
- info = createIncompatibleTypeHighlightInfo(constructorCall, result, constructorCall);
- }
- errorSink.accept(info);
- }
-
- /**
- * If the compile-time declaration is applicable by variable arity invocation,
- * then where the last formal parameter type of the invocation type of the method is Fn[],
- * it is a compile-time error if the type which is the erasure of Fn is not accessible at the point of invocation.
- */
- private static HighlightInfo.Builder checkVarargParameterErasureToBeAccessible(@NotNull MethodCandidateInfo info, @NotNull PsiCall place) {
- PsiMethod method = info.getElement();
- if (info.isVarargs() || method.isVarArgs() && !PsiUtil.isLanguageLevel8OrHigher(place)) {
- PsiParameter[] parameters = method.getParameterList().getParameters();
- PsiType componentType = ((PsiEllipsisType)parameters[parameters.length - 1].getType()).getComponentType();
- PsiType substitutedTypeErasure = TypeConversionUtil.erasure(info.getSubstitutor().substitute(componentType));
- PsiClass targetClass = PsiUtil.resolveClassInClassTypeOnly(substitutedTypeErasure);
- if (targetClass != null && !PsiUtil.isAccessible(targetClass, place, null)) {
- PsiExpressionList argumentList = place.getArgumentList();
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
- .descriptionAndTooltip(JavaErrorBundle.message("formal.varargs.element.type.inaccessible.here",
- PsiFormatUtil.formatClass(targetClass, PsiFormatUtilBase.SHOW_FQ_NAME)))
- .range(argumentList != null ? argumentList : place);
- }
- }
- return null;
- }
-
- private static @NotNull HighlightInfo.Builder buildAccessProblem(@NotNull PsiJavaCodeReferenceElement ref,
- @NotNull PsiJvmMember resolved,
- @NotNull JavaResolveResult result) {
- String description = HighlightUtil.accessProblemDescription(ref, resolved, result);
- HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(ref).descriptionAndTooltip(description).navigationShift(+1);
- if (result.isStaticsScopeCorrect()) {
- HighlightFixUtil.registerAccessQuickFixAction(asConsumer(info), resolved, ref, result.getCurrentFileResolveScope());
- }
- return info;
- }
-
- private static boolean callingProtectedConstructorFromDerivedClass(@NotNull PsiConstructorCall place, @NotNull PsiClass constructorClass) {
- // indirect instantiation via anonymous class is ok
- if (place instanceof PsiNewExpression newExpression && newExpression.getAnonymousClass() != null) return false;
- PsiElement curElement = place;
- PsiClass containingClass = constructorClass.getContainingClass();
- while (true) {
- PsiClass aClass = PsiTreeUtil.getParentOfType(curElement, PsiClass.class);
- if (aClass == null) return false;
- curElement = aClass;
- if ((aClass.isInheritor(constructorClass, true) || containingClass != null && aClass.isInheritor(containingClass, true))
- && !JavaPsiFacade.getInstance(aClass.getProject()).arePackagesTheSame(aClass, constructorClass)) {
- return true;
- }
- }
- }
-
private static @NotNull String buildArgTypesList(@NotNull PsiExpressionList list, boolean shortNames) {
StringBuilder builder = new StringBuilder();
builder.append("(");
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 0ef7ee667e88..116fd6b44fb6 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
@@ -503,17 +503,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
- @Override
- public void visitEnumConstant(@NotNull PsiEnumConstant enumConstant) {
- super.visitEnumConstant(enumConstant);
- if (!hasErrorResults()) {
- PsiClass containingClass = Objects.requireNonNull(enumConstant.getContainingClass());
- PsiClassType type = JavaPsiFacade.getElementFactory(getProject()).createType(containingClass);
- HighlightMethodUtil.checkConstructorCall(getProject(), type.resolveGenerics(), enumConstant, type, null, myJavaSdkVersion,
- enumConstant.getArgumentList(), myErrorSink);
- }
- }
-
@Override
public void visitExpression(@NotNull PsiExpression expression) {
ProgressManager.checkCanceled(); // visitLiteralExpression is invoked very often in array initializers
@@ -803,11 +792,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
PsiType type = expression.getType();
if (!hasErrorResults()) add(GenericsHighlightUtil.checkTypeParameterInstantiation(expression));
if (!hasErrorResults()) add(GenericsHighlightUtil.checkGenericArrayCreation(expression, type));
- try {
- if (!hasErrorResults()) HighlightMethodUtil.checkNewExpression(getProject(), expression, type, myJavaSdkVersion, myErrorSink);
- }
- catch (IndexNotReadyException ignored) {
- }
if (!hasErrorResults()) visitExpression(expression);
@@ -865,9 +849,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!hasErrorResults() && resolved instanceof PsiModifierListOwner) {
PreviewFeatureUtil.checkPreviewFeature(ref, myPreviewFeatureVisitor);
}
- if (!hasErrorResults()) {
- HighlightMethodUtil.checkAmbiguousConstructorCall(getProject(), ref, resolved, ref.getParent(), myJavaSdkVersion, myErrorSink);
- }
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaErrorFixProvider.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaErrorFixProvider.java
index cc452dd95b31..87283b784525 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaErrorFixProvider.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/JavaErrorFixProvider.java
@@ -22,6 +22,7 @@ import com.intellij.lang.jvm.actions.JvmElementActionFactories;
import com.intellij.lang.jvm.actions.MemberRequestsKt;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.Service;
+import com.intellij.openapi.project.Project;
import com.intellij.pom.java.JavaFeature;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -81,7 +82,8 @@ final class JavaErrorFixProvider {
CLASS_IMPLICIT_INITIALIZER, CLASS_IMPLICIT_PACKAGE,
RECORD_EXTENDS, ENUM_EXTENDS, RECORD_PERMITS, ENUM_PERMITS, ANNOTATION_PERMITS,
NEW_EXPRESSION_DIAMOND_NOT_ALLOWED, REFERENCE_TYPE_ARGUMENT_STATIC_CLASS,
- STATEMENT_CASE_OUTSIDE_SWITCH, NEW_EXPRESSION_DIAMOND_NOT_APPLICABLE)) {
+ STATEMENT_CASE_OUTSIDE_SWITCH, NEW_EXPRESSION_DIAMOND_NOT_APPLICABLE,
+ NEW_EXPRESSION_ANONYMOUS_IMPLEMENTS_INTERFACE_WITH_TYPE_ARGUMENTS)) {
fix(kind, genericRemover);
}
@@ -251,6 +253,29 @@ final class JavaErrorFixProvider {
}
return null;
});
+ multi(NEW_EXPRESSION_ARGUMENTS_TO_DEFAULT_CONSTRUCTOR_CALL, error -> {
+ PsiConstructorCall constructorCall = error.psi();
+ List registrar = new ArrayList<>();
+ PsiJavaCodeReferenceElement classReference =
+ constructorCall instanceof PsiNewExpression newExpression ? newExpression.getClassOrAnonymousClassReference() : null;
+ if (classReference != null) {
+ ConstructorParametersFixer.registerFixActions(constructorCall, registrar::add);
+ }
+ registrar.addAll(QuickFixFactory.getInstance().createCreateConstructorFromUsageFixes(constructorCall));
+ RemoveRedundantArgumentsFix.registerIntentions(requireNonNull(constructorCall.getArgumentList()), registrar::add);
+ return registrar;
+ });
+ multi(NEW_EXPRESSION_UNRESOLVED_CONSTRUCTOR, error -> {
+ PsiConstructorCall constructorCall = error.psi();
+ PsiExpressionList list = constructorCall.getArgumentList();
+ List registrar = new ArrayList<>();
+ if (list != null) {
+ JavaResolveResult[] results = error.context().results();
+ WrapExpressionFix.registerWrapAction(results, list.getExpressions(), registrar::add);
+ HighlightFixUtil.registerFixesOnInvalidConstructorCall(registrar::add, constructorCall, error.context().psiClass(), results);
+ }
+ return registrar;
+ });
fix(TYPE_PARAMETER_ABSENT_CLASS, error -> myFactory.createChangeClassSignatureFromUsageFix(error.context(), error.psi()));
fix(TYPE_PARAMETER_COUNT_MISMATCH,
error -> error.context() instanceof PsiClass cls ? myFactory.createChangeClassSignatureFromUsageFix(cls, error.psi()) : null);
@@ -323,7 +348,7 @@ final class JavaErrorFixProvider {
private void createAccessFixes() {
JavaFixesProvider accessFix = error -> {
List registrar = new ArrayList<>();
- if (error.context().getElement() instanceof PsiJvmMember member) {
+ if (error.context().isStaticsScopeCorrect() && error.context().getElement() instanceof PsiJvmMember member) {
HighlightFixUtil.registerAccessQuickFixAction(registrar::add, member, error.psi(), null);
}
return registrar;
@@ -397,21 +422,39 @@ final class JavaErrorFixProvider {
multi(CALL_WRONG_ARGUMENTS, error -> {
JavaMismatchedCallContext context = error.context();
List registrar = new ArrayList<>();
- if (context.list().getParent() instanceof PsiMethodCallExpression methodCall) {
+ PsiExpressionList list = context.list();
+ Project project = error.project();
+ PsiResolveHelper resolveHelper = PsiResolveHelper.getInstance(project);
+ MethodCandidateInfo candidate = context.candidate();
+ PsiElement parent = list.getParent();
+ if (parent instanceof PsiAnonymousClass) {
+ parent = parent.getParent();
+ }
+ if (parent instanceof PsiMethodCallExpression methodCall) {
PsiType expectedTypeByParent = InferenceSession.getTargetTypeByParent(methodCall);
PsiType actualType = ((PsiExpression)methodCall.copy()).getType();
if (expectedTypeByParent != null && actualType != null && !expectedTypeByParent.isAssignableFrom(actualType)) {
AdaptExpressionTypeFixUtil.registerExpectedTypeFixes(registrar::add, methodCall, expectedTypeByParent, actualType);
}
- PsiResolveHelper resolveHelper = PsiResolveHelper.getInstance(error.project());
HighlightFixUtil.registerQualifyMethodCallFix(
- resolveHelper.getReferencedMethodCandidates(methodCall, false), methodCall, context.list(), registrar::add);
- HighlightFixUtil.registerMethodCallIntentions(registrar::add, methodCall, context.list());
- MethodCandidateInfo candidate = context.candidate();
+ resolveHelper.getReferencedMethodCandidates(methodCall, false), methodCall, list, registrar::add);
+ HighlightFixUtil.registerMethodCallIntentions(registrar::add, methodCall, list);
HighlightFixUtil.registerMethodReturnFixAction(registrar::add, candidate, methodCall);
HighlightFixUtil.registerTargetTypeFixesBasedOnApplicabilityInference(methodCall, candidate, candidate.getElement(), registrar::add);
HighlightFixUtil.registerImplementsExtendsFix(registrar::add, methodCall, candidate.getElement());
}
+ if (parent instanceof PsiConstructorCall constructorCall) {
+ JavaResolveResult[] methodCandidates = JavaResolveResult.EMPTY_ARRAY;
+ PsiClass aClass = requireNonNull(candidate.getElement().getContainingClass());
+ if (constructorCall instanceof PsiNewExpression newExpression) {
+ methodCandidates = resolveHelper.getReferencedMethodCandidates(newExpression, true);
+ } else if (constructorCall instanceof PsiEnumConstant enumConstant) {
+ PsiClassType type = JavaPsiFacade.getElementFactory(project).createType(aClass);
+ methodCandidates = resolveHelper.multiResolveConstructor(type, list, enumConstant);
+ }
+ HighlightFixUtil.registerFixesOnInvalidConstructorCall(registrar::add, constructorCall, aClass, methodCandidates);
+ HighlightFixUtil.registerMethodReturnFixAction(registrar::add, candidate, constructorCall);
+ }
return registrar;
});
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeTypeArgumentsFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeTypeArgumentsFix.java
index 1bad969cf21e..d14631c75d64 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeTypeArgumentsFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeTypeArgumentsFix.java
@@ -14,7 +14,6 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
-import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -107,27 +106,20 @@ public class ChangeTypeArgumentsFix extends PsiUpdateModCommandAction info,
PsiClass psiClass) {
if (candidates.length == 0) return;
+ if (!(call instanceof PsiNewExpression newExpression)) return;
+ PsiExpressionList list = newExpression.getArgumentList();
+ if (list == null) return;
PsiExpression[] expressions = list.getExpressions();
for (JavaResolveResult candidate : candidates) {
- registerIntention(expressions, info, psiClass, candidate, list);
- }
- }
-
- private static void registerIntention(PsiExpression @NotNull [] expressions,
- @NotNull Consumer super CommonIntentionAction> info,
- PsiClass psiClass,
- @NotNull JavaResolveResult candidate,
- @NotNull PsiElement context) {
- if (!candidate.isStaticsScopeCorrect()) return;
- PsiMethod method = (PsiMethod)candidate.getElement();
- if (method != null && BaseIntentionAction.canModify(method)) {
- PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(context, PsiNewExpression.class);
- if (newExpression == null) return;
- info.accept(new ChangeTypeArgumentsFix(method, psiClass, expressions, newExpression));
+ if (!candidate.isStaticsScopeCorrect()) continue;
+ PsiMethod method = (PsiMethod)candidate.getElement();
+ if (method != null && BaseIntentionAction.canModify(method)) {
+ info.accept(new ChangeTypeArgumentsFix(method, psiClass, expressions, newExpression));
+ }
}
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConstructorParametersFixer.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConstructorParametersFixer.java
index 42b7d054d94b..a4ca4252aec2 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConstructorParametersFixer.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConstructorParametersFixer.java
@@ -18,20 +18,28 @@ import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
public final class ConstructorParametersFixer {
- public static void registerFixActions(@NotNull PsiJavaCodeReferenceElement ctrRef,
- @NotNull PsiConstructorCall constructorCall,
+ public static void registerFixActions(@NotNull PsiConstructorCall constructorCall,
@NotNull Consumer super CommonIntentionAction> info) {
- JavaResolveResult resolved = ctrRef.advancedResolve(false);
- PsiClass aClass = (PsiClass) resolved.getElement();
- PsiSubstitutor substitutor = resolved.getSubstitutor();
- if (aClass == null) return;
- registerFixActions(aClass, substitutor, constructorCall, info);
+ if (constructorCall instanceof PsiNewExpression newExpression) {
+ PsiJavaCodeReferenceElement ctrRef = newExpression.getClassOrAnonymousClassReference();
+ if (ctrRef == null) return;
+ JavaResolveResult resolved = ctrRef.advancedResolve(false);
+ PsiClass aClass = (PsiClass) resolved.getElement();
+ PsiSubstitutor substitutor = resolved.getSubstitutor();
+ if (aClass == null) return;
+ registerFixActions(aClass, substitutor, constructorCall, info);
+ } else if (constructorCall instanceof PsiEnumConstant enumConstant) {
+ PsiClass containingClass = enumConstant.getContainingClass();
+ if (containingClass != null) {
+ registerFixActions(containingClass, PsiSubstitutor.EMPTY, constructorCall, info);
+ }
+ }
}
- public static void registerFixActions(@NotNull PsiClass aClass,
- @NotNull PsiSubstitutor substitutor,
- @NotNull PsiConstructorCall constructorCall,
- @NotNull Consumer super CommonIntentionAction> info) {
+ private static void registerFixActions(@NotNull PsiClass aClass,
+ @NotNull PsiSubstitutor substitutor,
+ @NotNull PsiConstructorCall constructorCall,
+ @NotNull Consumer super CommonIntentionAction> info) {
PsiMethod[] methods = aClass.getConstructors();
CandidateInfo[] candidates = new CandidateInfo[methods.length];
for (int i = 0; i < candidates.length; i++) {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/TooltipNotEnoughArguments.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/TooltipNotEnoughArguments.java
index 751cb9e33ade..f71de2c5b3fd 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/TooltipNotEnoughArguments.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/TooltipNotEnoughArguments.java
@@ -3,6 +3,6 @@ class MyTest {
}
{
- new MyTest(1, "");
+ new MyTest(1, "");
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/ConstructorAccessibility.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/ConstructorAccessibility.java
index 39ed1dc812c6..0d94bb701e53 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/ConstructorAccessibility.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/ConstructorAccessibility.java
@@ -10,6 +10,6 @@ interface Either {
class Main {
{
- new Either.Left<>("");
+ new Either.Left<>("");
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/EraseTypeForNewExpressionWithDiamondsIfUncheckedConversionWasPerformedDuringApplicabilityCheck.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/EraseTypeForNewExpressionWithDiamondsIfUncheckedConversionWasPerformedDuringApplicabilityCheck.java
index da28c46de7d3..900b5c4c83e0 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/EraseTypeForNewExpressionWithDiamondsIfUncheckedConversionWasPerformedDuringApplicabilityCheck.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/diamond/EraseTypeForNewExpressionWithDiamondsIfUncheckedConversionWasPerformedDuringApplicabilityCheck.java
@@ -1,14 +1,14 @@
class Test {
{
Holder h = null;
- Result r1 = new Result<>(h);
+ Result r1 = new Result<>(h);
Result r2 = Result.create(h);
Holder dataHolder = null;
- Result r3 = new Result<>(new Holder<>(dataHolder));
+ Result r3 = new Result<>(new Holder<>(dataHolder));
Result r4 = Result.create(new Holder<>(dataHolder));
- Result r5 = new Result<>(Holder.create(dataHolder));
+ Result r5 = new Result<>(Holder.create(dataHolder));
Result r6 = Result.create(Holder.create(dataHolder));
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AmbiguousConstructorCallWithLambdaInside.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AmbiguousConstructorCallWithLambdaInside.java
index 619b622c3035..0c447b9b0a76 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AmbiguousConstructorCallWithLambdaInside.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AmbiguousConstructorCallWithLambdaInside.java
@@ -4,7 +4,7 @@ import java.util.function.Supplier;
class OverloadCast {
public void runMe() {
- new OverloadCast(WhitespaceTokenizer::new, src -> new LowerCaseFilter(src));
+ new OverloadCast(WhitespaceTokenizer::new, src -> new LowerCaseFilter(src));
overloadCast(WhitespaceTokenizer::new, src -> new LowerCaseFilter(src));
}
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 b2a1fc8622df..89de2062572d 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
@@ -1059,10 +1059,10 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
String red = ColorUtil.toHtmlColor(NamedColorUtil.getErrorForeground());
String expected = "" +
"" +
- "| Required type: | " +
- "int |
" +
- "| Provided: | " +
- "String |
" +
+ "Required type: | " +
+ "int | " +
+ "| Provided: | " +
+ "String |
" +
"
" +
"";
@@ -1079,11 +1079,11 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
String red = ColorUtil.toHtmlColor(NamedColorUtil.getErrorForeground());
String expected = "" +
"" +
- "| Required type: | " +
+ "Required type: | " +
"String | " +
"
" +
"" +
- "| Provided: | " +
+ "Provided: | " +
"int | " +
"
" +
"
";
@@ -1103,8 +1103,8 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
.getAttributes(DefaultLanguageHighlighterColors.INLINE_PARAMETER_HINT)
.getBackgroundColor());
String expected = "" +
- " | Required type | " +
- "Provided |
" +
+ " | Required type: | " +
+ "Provided: |
" +
" | " +
"String... | " +
"int |
" +
@@ -1124,10 +1124,10 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
String red = ColorUtil.toHtmlColor(NamedColorUtil.getErrorForeground());
String expected = "" +
"" +
- "| Required type: | " +
+ "Required type: | " +
"CharSequence | " +
"
" +
- "| Provided: | " +
+ "
| Provided: | " +
"int |
" +
"
";
@@ -1144,12 +1144,12 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
String red = ColorUtil.toHtmlColor(NamedColorUtil.getErrorForeground());
String expected = "" +
"" +
- "| Required type: | " +
+ "Required type: | " +
"Class | " +
"<capture of ?> | " +
"
" +
"" +
- "| Provided: | " +
+ "Provided: | " +
"Class | " +
"<capture of ?> |
" +
"
";
@@ -1171,8 +1171,8 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
String expected = "" +
"" +
" | " +
- "Required type | " +
- "Provided |
" +
+ "Required type: | " +
+ "Provided: | " +
"" +
" | " +
"List<Integer> | " +