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=\ - \ - {1}\ - {3}\ -
Required type:{0}
Provided:{2}
{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("
%s
", 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 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 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 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 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 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 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 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 info) { + private static void registerFixActions(@NotNull PsiClass aClass, + @NotNull PsiSubstitutor substitutor, + @NotNull PsiConstructorCall constructorCall, + @NotNull Consumer 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 = "" + - "" + - "" + + "" + + "" + "" + "" + "" + @@ -1124,10 +1124,10 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase { String red = ColorUtil.toHtmlColor(NamedColorUtil.getErrorForeground()); String expected = "
Required typeProvided
Required type:Provided:
list:
String...int
" + "" + - "" + + "" + "" + "" + - "" + + "" + "" + "
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 typeProvided
Required type:Provided:
integerList:
List<Integer>