[java-highlighting] more method call errors -> ExpressionChecker; drop ranges on fixes

Part of IDEA-365344 Create a new Java error highlighter with minimal dependencies (PSI only)

GitOrigin-RevId: e8ba3ee967f6d8b3534549b1a115b66fde3f57e5
This commit is contained in:
Tagir Valeev
2025-01-22 10:33:39 +00:00
committed by intellij-monorepo-bot
parent c28f1d89cc
commit 072f53c464
32 changed files with 599 additions and 493 deletions
@@ -129,6 +129,7 @@ type.parameter.on.enum=Enum may not have type parameters
type.parameter.on.annotation.member=@interface members may not have type parameters
type.parameter.on.annotation=@interface may not have type parameters
type.parameter.duplicate=Duplicate type parameter: ''{0}''
type.parameter.incompatible.upper.bounds=Type parameter {0} has incompatible upper bounds: {1}
method.duplicate=''{0}'' is already defined in ''{1}''
method.throws.class.name.expected=Class name expected
@@ -220,6 +221,9 @@ exception.never.thrown.try.multi=Exception ''{0}'' is never thrown in the corres
call.super.enum.constructor=Call to super is not allowed in enum constructor
call.super.qualifier.not.inner.class=Qualifier is not allowed because superclass ''{0}'' is not a non-static inner class
call.expected=Method call expected
call.static.interface.method.qualifier=Static method may only be called on its containing interface
call.formal.varargs.element.type.inaccessible.here=Formal varargs element type {0} is inaccessible here
call.type.inference.error={0}
array.illegal.initializer=Illegal initializer for ''{0}''
array.initializer.not.allowed=Array initializer is not allowed here
@@ -2,20 +2,25 @@
package com.intellij.java.codeserver.highlighting;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.core.JavaPsiBundle;
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds;
import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.impl.IncompleteModelUtil;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
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.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.intellij.util.ObjectUtils.tryCast;
@@ -316,7 +321,20 @@ final class ExpressionChecker {
if (resolved instanceof PsiMethod psiMethod && resolveResult.isValidResult()) {
checkUnhandledExceptions(methodCall);
if (myVisitor.hasErrorResults()) return;
if (psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
PsiClass containingClass = psiMethod.getContainingClass();
if (containingClass != null && containingClass.isInterface()) {
PsiElement element = ObjectUtils.notNull(referenceToMethod.getReferenceNameElement(), referenceToMethod);
myVisitor.checkFeature(element, JavaFeature.STATIC_INTERFACE_CALLS);
if (myVisitor.hasErrorResults()) return;
checkStaticInterfaceCallQualifier(referenceToMethod, resolveResult, containingClass);
}
}
myVisitor.myGenericsChecker.checkInferredIntersections(substitutor, methodCall);
if (myVisitor.hasErrorResults()) return;
checkVarargParameterErasureToBeAccessible((MethodCandidateInfo)resolveResult, methodCall);
if (myVisitor.hasErrorResults()) return;
checkIncompatibleType(methodCall, (MethodCandidateInfo)resolveResult, methodCall);
}
else {
MethodCandidateInfo candidateInfo = resolveResult instanceof MethodCandidateInfo ? (MethodCandidateInfo)resolveResult : null;
@@ -371,6 +389,97 @@ final class ExpressionChecker {
}
}
private static boolean favorParentReport(@NotNull PsiCall methodCall, @NotNull String errorMessage) {
// Parent resolve failed as well, and it's likely more informative.
// Suppress this error to allow reporting from parent
return (errorMessage.equals(JavaPsiBundle.message("error.incompatible.type.failed.to.resolve.argument")) ||
errorMessage.equals(JavaPsiBundle.message("error.incompatible.type.declaration.for.the.method.reference.not.found"))) &&
hasSurroundingInferenceError(methodCall);
}
static boolean hasSurroundingInferenceError(@NotNull PsiElement context) {
PsiCall topCall = LambdaUtil.treeWalkUp(context);
if (topCall == null) return false;
while (context != topCall) {
context = context.getParent();
if (context instanceof PsiMethodCallExpression call &&
call.resolveMethodGenerics() instanceof MethodCandidateInfo info &&
info.getInferenceErrorMessage() != null) {
// Possibly inapplicable method reference due to the surrounding call inference failure:
// suppress method reference error in order to display more relevant inference error.
return true;
}
}
return false;
}
private void checkIncompatibleType(@NotNull PsiCall methodCall,
@NotNull MethodCandidateInfo resolveResult,
@NotNull PsiElement elementToHighlight) {
String errorMessage = resolveResult.getInferenceErrorMessage();
if (errorMessage == null) return;
if (favorParentReport(methodCall, errorMessage)) return;
PsiMethod method = resolveResult.getElement();
PsiType expectedTypeByParent = InferenceSession.getTargetTypeByParent(methodCall);
PsiType actualType =
methodCall instanceof PsiExpression ? ((PsiExpression)methodCall.copy()).getType() :
resolveResult.getSubstitutor(false).substitute(method.getReturnType());
if (expectedTypeByParent != null && actualType != null && !expectedTypeByParent.isAssignableFrom(actualType)) {
myVisitor.report(JavaErrorKinds.TYPE_INCOMPATIBLE.create(
elementToHighlight, new JavaIncompatibleTypeErrorContext(expectedTypeByParent, actualType, errorMessage)));
}
else {
myVisitor.report(JavaErrorKinds.CALL_TYPE_INFERENCE_ERROR.create(methodCall, errorMessage));
}
}
/**
* 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 void 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)) {
myVisitor.report(JavaErrorKinds.CALL_FORMAL_VARARGS_ELEMENT_TYPE_INACCESSIBLE_HERE.create(place, targetClass));
}
}
}
private void checkStaticInterfaceCallQualifier(@NotNull PsiReferenceExpression referenceToMethod,
@NotNull JavaResolveResult resolveResult,
@NotNull PsiClass containingClass) {
PsiElement scope = resolveResult.getCurrentFileResolveScope();
PsiElement qualifierExpression = referenceToMethod.getQualifier();
if (qualifierExpression == null && PsiTreeUtil.isAncestor(containingClass, referenceToMethod, true)) return;
PsiElement resolve = null;
if (qualifierExpression == null && scope instanceof PsiImportStaticStatement statement) {
resolve = statement.resolveTargetClass();
}
else if (qualifierExpression instanceof PsiJavaCodeReferenceElement element) {
resolve = element.resolve();
}
if (containingClass.getManager().areElementsEquivalent(resolve, containingClass)) return;
if (resolve instanceof PsiTypeParameter typeParameter) {
Set<PsiClass> classes = new HashSet<>();
for (PsiClassType type : typeParameter.getExtendsListTypes()) {
PsiClass aClass = type.resolve();
if (aClass != null) {
classes.add(aClass);
}
}
if (classes.size() == 1 && classes.contains(containingClass)) return;
}
myVisitor.report(JavaErrorKinds.CALL_STATIC_INTERFACE_METHOD_QUALIFIER.create(referenceToMethod));
}
private static boolean shouldHighlightUnhandledException(@NotNull PsiElement element) {
// JSP top-level errors are handled by UnhandledExceptionInJSP inspection
if (FileTypeUtils.isInServerPageFile(element)) {
@@ -238,4 +238,16 @@ final class GenericsChecker {
}
}
}
void checkInferredIntersections(@NotNull PsiSubstitutor substitutor, @NotNull PsiMethodCallExpression call) {
for (Map.Entry<PsiTypeParameter, PsiType> typeEntry : substitutor.getSubstitutionMap().entrySet()) {
if (typeEntry.getValue() instanceof PsiIntersectionType intersectionType) {
String conflictingConjunctsMessage = intersectionType.getConflictingConjunctsMessage();
if (conflictingConjunctsMessage != null) {
myVisitor.report(JavaErrorKinds.TYPE_PARAMETER_INCOMPATIBLE_UPPER_BOUNDS.create(
call, new JavaErrorKinds.IncompatibleIntersectionContext(typeEntry.getKey(), conflictingConjunctsMessage)));
}
}
}
}
}
@@ -42,7 +42,7 @@ final class JavaErrorVisitor extends JavaElementVisitor {
private final @NotNull AnnotationChecker myAnnotationChecker = new AnnotationChecker(this);
final @NotNull ClassChecker myClassChecker = new ClassChecker(this);
private final @NotNull RecordChecker myRecordChecker = new RecordChecker(this);
private final @NotNull GenericsChecker myGenericsChecker = new GenericsChecker(this);
final @NotNull GenericsChecker myGenericsChecker = new GenericsChecker(this);
final @NotNull MethodChecker myMethodChecker = new MethodChecker(this);
private final @NotNull ReceiverChecker myReceiverChecker = new ReceiverChecker(this);
private final @NotNull ModifierChecker myModifierChecker = new ModifierChecker(this);
@@ -68,6 +68,12 @@ final class JavaErrorFormatUtil {
return nameElement.getTextRangeInParent();
}
}
if (element instanceof PsiReferenceExpression refExpression) {
PsiElement nameElement = refExpression.getReferenceNameElement();
if (nameElement != null) {
return nameElement.getTextRangeInParent();
}
}
PsiElement nextSibling = element.getNextSibling();
if (PsiUtil.isJavaToken(nextSibling, JavaTokenType.SEMICOLON)) {
return TextRange.create(0, element.getTextLength() + 1);
@@ -381,6 +381,10 @@ public final class JavaErrorKinds {
public static final Simple<PsiTypeParameter> TYPE_PARAMETER_DUPLICATE =
error(PsiTypeParameter.class, "type.parameter.on.annotation.member")
.withRawDescription(typeParameter -> message("type.parameter.duplicate", typeParameter.getName()));
public static final Parameterized<PsiMethodCallExpression, IncompatibleIntersectionContext> TYPE_PARAMETER_INCOMPATIBLE_UPPER_BOUNDS =
parameterized(PsiMethodCallExpression.class, IncompatibleIntersectionContext.class, "type.parameter.incompatible.upper.bounds")
.withRange((call, ctx) -> getRange(call))
.withRawDescription((call, ctx) -> message("type.parameter.incompatible.upper.bounds", ctx.parameter().getName(), ctx.message()));
public static final Simple<PsiMethod> METHOD_DUPLICATE =
error(PsiMethod.class, "method.duplicate")
@@ -525,6 +529,7 @@ public final class JavaErrorKinds {
public static final Parameterized<PsiElement, JavaIncompatibleTypeErrorContext> TYPE_INCOMPATIBLE =
parameterized(PsiElement.class, JavaIncompatibleTypeErrorContext.class, "type.incompatible")
.withRange((psi, context) -> getRange(psi))
.withDescription((psi, context) -> context.createDescription())
.withTooltip((psi, context) -> context.createTooltip());
public static final Simple<PsiKeyword> TYPE_VOID_ILLEGAL = error("type.void.illegal");
@@ -634,7 +639,18 @@ public final class JavaErrorKinds {
parameterized(PsiExpression.class, PsiClass.class, "call.super.qualifier.not.inner.class")
.withRawDescription((psi, cls) -> message("call.super.qualifier.not.inner.class", formatClass(cls)));
public static final Simple<PsiMethodCallExpression> CALL_EXPECTED = error("call.expected");
public static final Simple<PsiReferenceExpression> CALL_STATIC_INTERFACE_METHOD_QUALIFIER =
error(PsiReferenceExpression.class, "call.static.interface.method.qualifier")
.withAnchor(ref -> requireNonNullElse(ref.getReferenceNameElement(), ref))
.withRange(JavaErrorFormatUtil::getRange);
public static final Parameterized<PsiCall, PsiClass> CALL_FORMAL_VARARGS_ELEMENT_TYPE_INACCESSIBLE_HERE =
parameterized(PsiCall.class, PsiClass.class, "call.formal.varargs.element.type.inaccessible.here")
.withAnchor((call, cls) -> requireNonNullElse(call.getArgumentList(), call))
.withRawDescription((call, cls) -> message("call.formal.varargs.element.type.inaccessible.here", formatClass(cls)));
public static final Parameterized<PsiCall, String> CALL_TYPE_INFERENCE_ERROR =
parameterized(PsiCall.class, String.class, "call.type.inference.error")
.withRange((psi, context) -> getRange(psi))
.withRawDescription((psi, context) -> message("call.type.inference.error", context));
public static final Simple<PsiExpression> STRING_TEMPLATE_VOID_NOT_ALLOWED_IN_EMBEDDED =
error("string.template.void.not.allowed.in.embedded");
public static final Simple<PsiTemplateExpression> STRING_TEMPLATE_PROCESSOR_MISSING =
@@ -739,5 +755,6 @@ public final class JavaErrorKinds {
public record InvalidDisjointTypeContext(@NotNull PsiClass superClass, @NotNull PsiClass subClass) {
}
public record IncompatibleIntersectionContext(@NotNull PsiTypeParameter parameter, @NotNull @Nls String message) {}
}
@@ -9,13 +9,19 @@ import com.intellij.openapi.util.text.HtmlChunk;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public record JavaIncompatibleTypeErrorContext(@NotNull PsiType lType, @Nullable PsiType rType) {
public record JavaIncompatibleTypeErrorContext(@NotNull PsiType lType, @Nullable PsiType rType,
@Nullable @Nls String reasonForIncompatibleTypes) {
private static final @NlsSafe String ANONYMOUS = "anonymous ";
public JavaIncompatibleTypeErrorContext(@NotNull PsiType lType, @Nullable PsiType rType) {
this(lType, rType, null);
}
private @Nls @NotNull String getReasonForIncompatibleTypes() {
if (rType instanceof PsiMethodReferenceType referenceType) {
JavaResolveResult[] results = referenceType.getExpression().multiResolve(false);
@@ -33,10 +39,11 @@ public record JavaIncompatibleTypeErrorContext(@NotNull PsiType lType, @Nullable
}
@NotNull HtmlChunk createTooltip() {
return createTooltip(getReasonForIncompatibleTypes());
return createTooltip(
reasonForIncompatibleTypes == null ? getReasonForIncompatibleTypes() : XmlStringUtil.escapeString(reasonForIncompatibleTypes));
}
@NotNull HtmlChunk createTooltip(@NotNull @Nls String reason) {
private @NotNull HtmlChunk createTooltip(@NotNull @Nls String reason) {
String styledReason = reason.isEmpty() ? "" :
String.format("<table><tr><td style=''padding-top: 10px; padding-left: 4px;''>%s</td></tr></table>", reason);
IncompatibleTypesTooltipComposer tooltipComposer = (lTypeString, lTypeArguments, rTypeString, rTypeArguments) ->
@@ -1112,23 +1112,6 @@ public final class GenericsHighlightUtil {
}
}
static HighlightInfo.Builder checkInferredIntersections(@NotNull PsiSubstitutor substitutor, @NotNull PsiMethodCallExpression call) {
for (Map.Entry<PsiTypeParameter, PsiType> typeEntry : substitutor.getSubstitutionMap().entrySet()) {
String parameterName = typeEntry.getKey().getName();
PsiType type = typeEntry.getValue();
if (type instanceof PsiIntersectionType intersectionType) {
String conflictingConjunctsMessage = intersectionType.getConflictingConjunctsMessage();
if (conflictingConjunctsMessage != null) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.descriptionAndTooltip(
JavaErrorBundle.message("type.parameter.has.incompatible.upper.bounds", parameterName, conflictingConjunctsMessage))
.range(HighlightMethodUtil.getFixRange(call));
}
}
}
return null;
}
static HighlightInfo.Builder checkMemberSignatureTypesAccessibility(@NotNull PsiReferenceExpression ref) {
String message = null;
@@ -3,10 +3,7 @@ package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.quickfix.QualifyMethodCallFix;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.daemon.impl.quickfix.ReplaceAssignmentFromVoidWithStatementIntentionAction;
import com.intellij.codeInsight.daemon.impl.quickfix.ReplaceGetClassWithClassLiteralFix;
import com.intellij.codeInsight.daemon.impl.quickfix.*;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
@@ -22,6 +19,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
@@ -36,6 +34,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
public final class HighlightFixUtil {
@@ -70,22 +69,19 @@ public final class HighlightFixUtil {
}
/**
* Make element protected/package-private/public suggestion.
* Make an element protected/package-private/public suggestion.
* For private method in the interface it should add default modifier as well.
*/
static void registerAccessQuickFixAction(@Nullable HighlightInfo.Builder info,
@NotNull TextRange fixRange,
static void registerAccessQuickFixAction(@NotNull Consumer<? super CommonIntentionAction> info,
@NotNull PsiJvmMember refElement,
@NotNull PsiJavaCodeReferenceElement place,
@Nullable PsiElement fileResolveScope,
@Nullable TextRange parentFixRange) {
if (info == null) return;
@Nullable PsiElement fileResolveScope) {
PsiClass accessObjectClass = null;
PsiElement qualifier = place.getQualifier();
if (qualifier instanceof PsiExpression) {
accessObjectClass = (PsiClass)PsiUtil.getAccessObjectClass((PsiExpression)qualifier).getElement();
}
registerReplaceInaccessibleFieldWithGetterSetterFix(info, refElement, place, accessObjectClass, parentFixRange);
registerReplaceInaccessibleFieldWithGetterSetterFix(info, refElement, place, accessObjectClass);
if (refElement instanceof PsiCompiledElement) return;
PsiModifierList modifierList = refElement.getModifierList();
@@ -95,7 +91,7 @@ public final class HighlightFixUtil {
if (packageLocalClassInTheMiddle != null) {
List<IntentionAction> fixes =
JvmElementActionFactories.createModifierActions(packageLocalClassInTheMiddle, MemberRequestsKt.modifierRequest(JvmModifier.PUBLIC, true));
QuickFixAction.registerQuickFixActions(info, parentFixRange, fixes);
fixes.forEach(info);
return;
}
@@ -118,14 +114,13 @@ public final class HighlightFixUtil {
}
int[] accessLevels = {PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL, PsiUtil.ACCESS_LEVEL_PROTECTED, PsiUtil.ACCESS_LEVEL_PUBLIC,};
for (int i = ArrayUtil.indexOf(accessLevels, minAccessLevel); i < accessLevels.length; i++) {
@PsiUtil.AccessLevel
@SuppressWarnings("MagicConstant") @PsiUtil.AccessLevel
int level = accessLevels[i];
modifierListCopy.setModifierProperty(PsiUtil.getAccessModifier(level), true);
if (facade.getResolveHelper().isAccessible(refElement, modifierListCopy, place, accessObjectClass, fileResolveScope)) {
List<IntentionAction> fixes = JvmElementActionFactories
.createModifierActions(refElement, MemberRequestsKt.modifierRequest(JvmUtil.getAccessModifier(level), true));
PsiElement ref = place.getReferenceNameElement();
QuickFixAction.registerQuickFixActions(info, ref == null ? fixRange : fixRange.union(ref.getTextRange()), fixes);
fixes.forEach(info);
}
}
}
@@ -296,11 +291,10 @@ public final class HighlightFixUtil {
return QuickFixFactory.getInstance().createChangeParameterClassFix(rClass, (PsiClassType)lType);
}
private static void registerReplaceInaccessibleFieldWithGetterSetterFix(@NotNull HighlightInfo.Builder builder,
private static void registerReplaceInaccessibleFieldWithGetterSetterFix(@NotNull Consumer<? super CommonIntentionAction> info,
@NotNull PsiMember refElement,
@NotNull PsiJavaCodeReferenceElement place,
@Nullable PsiClass accessObjectClass,
@Nullable TextRange parentFixRange) {
@Nullable PsiClass accessObjectClass) {
if (refElement instanceof PsiField psiField && place instanceof PsiReferenceExpression ref) {
if (PsiTypes.nullType().equals(psiField.getType())) return;
PsiClass containingClass = psiField.getContainingClass();
@@ -312,7 +306,7 @@ public final class HighlightFixUtil {
PsiElement element = PsiTreeUtil.skipParentsOfType(ref, PsiParenthesizedExpression.class);
if (element instanceof PsiAssignmentExpression && ((PsiAssignmentExpression)element).getOperationTokenType() == JavaTokenType.EQ) {
IntentionAction action = QuickFixFactory.getInstance().createReplaceInaccessibleFieldWithGetterSetterFix(ref, setter, true);
builder.registerFix(action, null, null, parentFixRange, null);
info.accept(action);
}
}
}
@@ -321,7 +315,7 @@ public final class HighlightFixUtil {
PsiMethod getter = containingClass.findMethodBySignature(getterPrototype, true);
if (getter != null && PsiUtil.isAccessible(getter, ref, accessObjectClass)) {
IntentionAction action = QuickFixFactory.getInstance().createReplaceInaccessibleFieldWithGetterSetterFix(ref, getter, false);
builder.registerFix(action, null, null, parentFixRange, null);
info.accept(action);
}
}
}
@@ -335,10 +329,12 @@ public final class HighlightFixUtil {
}
}
static void registerChangeParameterClassFix(@NotNull PsiType lType, @NotNull PsiType rType, @Nullable HighlightInfo.Builder info) {
static void registerChangeParameterClassFix(@NotNull PsiType lType,
@NotNull PsiType rType,
@NotNull Consumer<? super CommonIntentionAction> info) {
IntentionAction action = getChangeParameterClassFix(lType, rType);
if (info != null && action != null) {
info.registerFix(action, null, null, null, null);
if (action != null) {
info.accept(action);
}
}
@@ -485,4 +481,250 @@ public final class HighlightFixUtil {
}
}
}
private static void registerStaticMethodQualifierFixes(@NotNull PsiMethodCallExpression methodCall,
@NotNull Consumer<? super CommonIntentionAction> info) {
info.accept(QuickFixFactory.getInstance().createStaticImportMethodFix(methodCall));
info.accept(QuickFixFactory.getInstance().createQualifyStaticMethodCallFix(methodCall));
info.accept(QuickFixFactory.getInstance().addMethodQualifierFix(methodCall));
}
private static void registerUsageFixes(@NotNull PsiMethodCallExpression methodCall,
@NotNull Consumer<? super CommonIntentionAction> info) {
QuickFixFactory.getInstance().createCreateMethodFromUsageFixes(methodCall).forEach(info);
}
private static void registerThisSuperFixes(@NotNull PsiMethodCallExpression methodCall,
@NotNull Consumer<? super CommonIntentionAction> info) {
QuickFixFactory.getInstance().createCreateConstructorFromCallExpressionFixes(methodCall).forEach(info);
}
static void registerMethodCallIntentions(@NotNull Consumer<? super CommonIntentionAction> info,
@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiExpressionList list) {
PsiExpression qualifierExpression = methodCall.getMethodExpression().getQualifierExpression();
if (qualifierExpression instanceof PsiReferenceExpression referenceExpression) {
PsiElement resolve = referenceExpression.resolve();
if (resolve instanceof PsiClass psiClass &&
psiClass.getContainingClass() != null &&
!psiClass.hasModifierProperty(PsiModifier.STATIC)) {
List<IntentionAction> actions = JvmElementActionFactories.createModifierActions(
psiClass, MemberRequestsKt.modifierRequest(JvmModifier.STATIC, true));
actions.forEach(info);
}
}
else if (qualifierExpression instanceof PsiSuperExpression superExpression && superExpression.getQualifier() == null) {
QualifySuperArgumentFix.registerQuickFixAction(superExpression, info);
}
PsiResolveHelper resolveHelper = PsiResolveHelper.getInstance(methodCall.getProject());
CandidateInfo[] methodCandidates = resolveHelper.getReferencedMethodCandidates(methodCall, false);
IntentionAction action2 = QuickFixFactory.getInstance().createSurroundWithArrayFix(methodCall, null);
info.accept(action2);
CastMethodArgumentFix.REGISTRAR.registerCastActions(methodCandidates, methodCall, info);
AddTypeArgumentsFix.REGISTRAR.registerCastActions(methodCandidates, methodCall, info);
CandidateInfo[] candidates = resolveHelper.getReferencedMethodCandidates(methodCall, true);
ChangeStringLiteralToCharInMethodCallFix.registerFixes(candidates, methodCall, info);
WrapWithAdapterMethodCallFix.registerCastActions(methodCandidates, methodCall, info);
IntentionAction action1 = QuickFixFactory.getInstance().createReplaceAddAllArrayToCollectionFix(methodCall);
info.accept(action1);
WrapObjectWithOptionalOfNullableFix.REGISTAR.registerCastActions(methodCandidates, methodCall, info);
MethodReturnFixFactory.INSTANCE.registerCastActions(methodCandidates, methodCall, info);
WrapExpressionFix.registerWrapAction(methodCandidates, list.getExpressions(), info);
QualifyThisArgumentFix.registerQuickFixAction(methodCandidates, methodCall, info);
registerMethodAccessLevelIntentions(methodCandidates, methodCall, list, info);
if (!PermuteArgumentsFix.registerFix(info, methodCall, methodCandidates) &&
!MoveParenthesisFix.registerFix(info, methodCall, methodCandidates)) {
registerChangeMethodSignatureFromUsageIntentions(methodCandidates, list, info);
}
QuickFixFactory.getInstance().getVariableTypeFromCallFixes(methodCall, list).forEach(info);
if (methodCandidates.length == 0) {
registerStaticMethodQualifierFixes(methodCall, info);
}
registerThisSuperFixes(methodCall, info);
registerUsageFixes(methodCall, info);
RemoveRedundantArgumentsFix.registerIntentions(methodCandidates, list, info);
registerChangeParameterClassFix(methodCall, list, info);
}
private static void registerMethodAccessLevelIntentions(CandidateInfo @NotNull [] methodCandidates,
@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiExpressionList exprList,
@NotNull Consumer<? super CommonIntentionAction> info) {
for (CandidateInfo methodCandidate : methodCandidates) {
PsiMethod method = (PsiMethod)methodCandidate.getElement();
if (!methodCandidate.isAccessible() && PsiUtil.isApplicable(method, methodCandidate.getSubstitutor(), exprList)) {
registerAccessQuickFixAction(info, method, methodCall.getMethodExpression(), methodCandidate.getCurrentFileResolveScope());
}
}
}
static void registerChangeParameterClassFix(@NotNull PsiCall methodCall,
@NotNull PsiExpressionList list,
@NotNull Consumer<? super CommonIntentionAction> info) {
JavaResolveResult result = methodCall.resolveMethodGenerics();
PsiMethod method = (PsiMethod)result.getElement();
PsiSubstitutor substitutor = result.getSubstitutor();
PsiExpression[] expressions = list.getExpressions();
if (method == null) return;
PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length != expressions.length) return;
for (int i = 0; i < expressions.length; i++) {
PsiExpression expression = expressions[i];
PsiParameter parameter = parameters[i];
PsiType expressionType = expression.getType();
PsiType parameterType = substitutor.substitute(parameter.getType());
if (expressionType == null ||
expressionType instanceof PsiPrimitiveType ||
TypeConversionUtil.isNullType(expressionType) ||
expressionType instanceof PsiArrayType) {
continue;
}
if (parameterType instanceof PsiPrimitiveType ||
TypeConversionUtil.isNullType(parameterType) ||
parameterType instanceof PsiArrayType) {
continue;
}
if (parameterType.isAssignableFrom(expressionType)) continue;
PsiClass parameterClass = PsiUtil.resolveClassInType(parameterType);
PsiClass expressionClass = PsiUtil.resolveClassInType(expressionType);
if (parameterClass == null || expressionClass == null) continue;
if (expressionClass instanceof PsiAnonymousClass) continue;
if (expressionClass.isInheritor(parameterClass, true)) continue;
IntentionAction action = QuickFixFactory.getInstance().createChangeParameterClassFix(expressionClass, (PsiClassType)parameterType);
info.accept(action);
}
}
static void registerChangeMethodSignatureFromUsageIntentions(JavaResolveResult @NotNull [] candidates,
@NotNull PsiExpressionList list,
@NotNull Consumer<? super CommonIntentionAction> info) {
if (candidates.length == 0) return;
PsiExpression[] expressions = list.getExpressions();
for (JavaResolveResult candidate : candidates) {
registerChangeMethodSignatureFromUsageIntention(expressions, info, candidate, list);
}
}
private static void registerChangeMethodSignatureFromUsageIntention(PsiExpression @NotNull [] expressions,
@NotNull Consumer<? super CommonIntentionAction> info,
@NotNull JavaResolveResult candidate,
@NotNull PsiElement context) {
if (!candidate.isStaticsScopeCorrect()) return;
PsiMethod method = (PsiMethod)candidate.getElement();
PsiSubstitutor substitutor = candidate.getSubstitutor();
if (method != null && context.getManager().isInProject(method)) {
IntentionAction fix = QuickFixFactory.getInstance()
.createChangeMethodSignatureFromUsageFix(method, expressions, substitutor, context, false, 2);
info.accept(fix);
IntentionAction f2 =
QuickFixFactory.getInstance()
.createChangeMethodSignatureFromUsageReverseOrderFix(method, expressions, substitutor, context, false, 2);
info.accept(f2);
}
}
static void registerMethodReturnFixAction(@NotNull Consumer<? super CommonIntentionAction> info,
@NotNull MethodCandidateInfo candidate,
@NotNull PsiCall methodCall) {
if (candidate.getInferenceErrorMessage() != null && methodCall.getParent() instanceof PsiReturnStatement) {
PsiMethod containerMethod = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class, true, PsiLambdaExpression.class);
if (containerMethod != null) {
PsiMethod method = candidate.getElement();
PsiExpression methodCallCopy =
JavaPsiFacade.getElementFactory(method.getProject()).createExpressionFromText(methodCall.getText(), methodCall);
PsiType methodCallTypeByArgs = methodCallCopy.getType();
//ensure type params are not included
methodCallTypeByArgs = JavaPsiFacade.getElementFactory(method.getProject())
.createRawSubstitutor(method).substitute(methodCallTypeByArgs);
if (methodCallTypeByArgs != null) {
info.accept(QuickFixFactory.getInstance().createMethodReturnFix(containerMethod, methodCallTypeByArgs, true));
}
}
}
}
static MethodCandidateInfo @NotNull [] toMethodCandidates(JavaResolveResult @NotNull [] resolveResults) {
List<MethodCandidateInfo> candidateList = new ArrayList<>(resolveResults.length);
for (JavaResolveResult result : resolveResults) {
if (!(result instanceof MethodCandidateInfo candidate)) continue;
if (candidate.isAccessible()) candidateList.add(candidate);
}
return candidateList.toArray(new MethodCandidateInfo[0]);
}
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);
}
ChangeStringLiteralToCharInMethodCallFix.registerFixes(constructors, constructorCall, info);
IntentionAction action = QuickFixFactory.getInstance().createSurroundWithArrayFix(constructorCall, null);
info.accept(action);
if (!PermuteArgumentsFix.registerFix(info, constructorCall, toMethodCandidates(results))) {
registerChangeMethodSignatureFromUsageIntentions(results, list, info);
}
QuickFixFactory.getInstance().createCreateConstructorFromUsageFixes(constructorCall).forEach(info);
registerChangeParameterClassFix(constructorCall, list, info);
RemoveRedundantArgumentsFix.registerIntentions(results, list, info);
}
static void registerTargetTypeFixesBasedOnApplicabilityInference(@NotNull PsiMethodCallExpression methodCall,
@NotNull MethodCandidateInfo resolveResult,
@NotNull PsiMethod resolved,
@NotNull Consumer<? super CommonIntentionAction> info) {
PsiElement parent = PsiUtil.skipParenthesizedExprUp(methodCall.getParent());
PsiVariable variable = null;
if (parent instanceof PsiVariable) {
variable = (PsiVariable)parent;
}
else if (parent instanceof PsiAssignmentExpression assignmentExpression) {
PsiExpression lExpression = assignmentExpression.getLExpression();
if (lExpression instanceof PsiReferenceExpression referenceExpression) {
PsiElement resolve = referenceExpression.resolve();
if (resolve instanceof PsiVariable) {
variable = (PsiVariable)resolve;
}
}
}
if (variable != null) {
PsiType rType = methodCall.getType();
if (rType != null && !variable.getType().isAssignableFrom(rType)) {
PsiType expectedTypeByApplicabilityConstraints = resolveResult.getSubstitutor(false).substitute(resolved.getReturnType());
if (expectedTypeByApplicabilityConstraints != null && !variable.getType().isAssignableFrom(expectedTypeByApplicabilityConstraints) &&
PsiTypesUtil.allTypeParametersResolved(variable, expectedTypeByApplicabilityConstraints)) {
registerChangeVariableTypeFixes(variable, expectedTypeByApplicabilityConstraints, methodCall, info);
}
}
}
}
static void registerCallInferenceFixes(@NotNull PsiMethodCallExpression callExpression, @NotNull Consumer<CommonIntentionAction> info) {
MethodCandidateInfo resolveResult = (MethodCandidateInfo)callExpression.getMethodExpression().advancedResolve(true);
PsiMethod method = resolveResult.getElement();
registerMethodCallIntentions(info, callExpression, callExpression.getArgumentList());
PsiType actualType = ((PsiExpression)callExpression.copy()).getType();
if (!PsiTypesUtil.mentionsTypeParameters(actualType, Set.of(method.getTypeParameters()))) {
registerMethodReturnFixAction(info, resolveResult, callExpression);
}
registerTargetTypeFixesBasedOnApplicabilityInference(callExpression, resolveResult, method, info);
}
}
@@ -13,9 +13,6 @@ 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.lang.jvm.JvmModifier;
import com.intellij.lang.jvm.actions.JvmElementActionFactories;
import com.intellij.lang.jvm.actions.MemberRequestsKt;
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
import com.intellij.openapi.editor.colors.EditorColorsUtil;
import com.intellij.openapi.project.IndexNotReadyException;
@@ -55,6 +52,8 @@ import java.util.*;
import java.util.List;
import java.util.function.Consumer;
import static com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil.asConsumer;
public final class HighlightMethodUtil {
private HighlightMethodUtil() { }
@@ -197,9 +196,7 @@ public final class HighlightMethodUtil {
static void checkMethodCall(@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiResolveHelper resolveHelper,
@NotNull LanguageLevel languageLevel,
@NotNull JavaSdkVersion javaSdkVersion,
@NotNull PsiFile file,
@NotNull Consumer<? super HighlightInfo.Builder> errorSink) {
PsiExpressionList list = methodCall.getArgumentList();
PsiReferenceExpression referenceToMethod = methodCall.getMethodExpression();
@@ -212,33 +209,8 @@ public final class HighlightMethodUtil {
HighlightInfo.Builder builder = null;
PsiSubstitutor substitutor = resolveResult.getSubstitutor();
if (resolved instanceof PsiMethod psiMethod && resolveResult.isValidResult()) {
if (psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
PsiClass containingClass = psiMethod.getContainingClass();
if (containingClass != null && containingClass.isInterface()) {
PsiElement element = ObjectUtils.notNull(referenceToMethod.getReferenceNameElement(), referenceToMethod);
builder = HighlightUtil.checkFeature(element, JavaFeature.STATIC_INTERFACE_CALLS, languageLevel, file);
if (builder == null) {
builder = checkStaticInterfaceCallQualifier(referenceToMethod, resolveResult, methodCall, containingClass);
}
}
}
if (builder == null) {
builder = GenericsHighlightUtil.checkInferredIntersections(substitutor, methodCall);
}
if (builder == null) {
builder = checkVarargParameterErasureToBeAccessible((MethodCandidateInfo)resolveResult, methodCall);
}
if (builder == null) {
builder = createIncompatibleTypeHighlightInfo(methodCall, resolveHelper, (MethodCandidateInfo)resolveResult, methodCall);
}
if (builder == null) {
builder = checkInferredReturnTypeAccessible((MethodCandidateInfo)resolveResult, methodCall);
}
if (resolved instanceof PsiMethod && resolveResult.isValidResult()) {
builder = checkInferredReturnTypeAccessible((MethodCandidateInfo)resolveResult, methodCall);
}
else {
MethodCandidateInfo candidateInfo = resolveResult instanceof MethodCandidateInfo ? (MethodCandidateInfo)resolveResult : null;
@@ -254,13 +226,13 @@ public final class HighlightMethodUtil {
PsiType actualType = ((PsiExpression)methodCall.copy()).getType();
if (expectedTypeByParent != null && actualType != null && !expectedTypeByParent.isAssignableFrom(actualType)) {
AdaptExpressionTypeFixUtil.registerExpectedTypeFixes(
HighlightUtil.asConsumer(builder), methodCall, expectedTypeByParent, actualType);
asConsumer(builder), methodCall, expectedTypeByParent, actualType);
}
HighlightFixUtil.registerQualifyMethodCallFix(resolveHelper.getReferencedMethodCandidates(methodCall, false), methodCall,
list, builder);
registerMethodCallIntentions(builder, methodCall, list, resolveHelper);
registerMethodReturnFixAction(builder, candidateInfo, methodCall);
registerTargetTypeFixesBasedOnApplicabilityInference(methodCall, candidateInfo, resolvedMethod, builder);
HighlightFixUtil.registerMethodCallIntentions(asConsumer(builder), methodCall, list);
HighlightFixUtil.registerMethodReturnFixAction(asConsumer(builder), candidateInfo, methodCall);
HighlightFixUtil.registerTargetTypeFixesBasedOnApplicabilityInference(methodCall, candidateInfo, resolvedMethod, asConsumer(builder));
registerImplementsExtendsFix(builder, methodCall, resolvedMethod);
errorSink.accept(builder);
return;
@@ -310,13 +282,6 @@ public final class HighlightMethodUtil {
}
}
private static void registerStaticMethodQualifierFixes(@NotNull PsiMethodCallExpression methodCall, @NotNull HighlightInfo.Builder info) {
TextRange methodExpressionRange = methodCall.getMethodExpression().getTextRange();
info.registerFix(QuickFixFactory.getInstance().createStaticImportMethodFix(methodCall), null, null, methodExpressionRange, null);
info.registerFix(QuickFixFactory.getInstance().createQualifyStaticMethodCallFix(methodCall), null, null, methodExpressionRange, null);
info.registerFix(QuickFixFactory.getInstance().addMethodQualifierFix(methodCall), null, null, methodExpressionRange, null);
}
/**
* 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
@@ -408,8 +373,7 @@ public final class HighlightMethodUtil {
}
static HighlightInfo.Builder createIncompatibleTypeHighlightInfo(@NotNull PsiCall methodCall,
@NotNull PsiResolveHelper resolveHelper,
@NotNull MethodCandidateInfo resolveResult,
@NotNull MethodCandidateInfo resolveResult,
@NotNull PsiElement elementToHighlight) {
String errorMessage = resolveResult.getInferenceErrorMessage();
if (errorMessage == null) return null;
@@ -425,7 +389,7 @@ public final class HighlightMethodUtil {
builder = HighlightUtil.createIncompatibleTypeHighlightInfo(
expectedTypeByParent, actualType, fixRange, 0, XmlStringUtil.escapeString(errorMessage));
if (methodCall instanceof PsiExpression) {
AdaptExpressionTypeFixUtil.registerExpectedTypeFixes(HighlightUtil.asConsumer(builder),
AdaptExpressionTypeFixUtil.registerExpectedTypeFixes(asConsumer(builder),
(PsiExpression)methodCall, expectedTypeByParent, actualType);
}
PsiElement parent = PsiUtil.skipParenthesizedExprUp(methodCall.getParent());
@@ -442,11 +406,11 @@ public final class HighlightMethodUtil {
builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(errorMessage).range(fixRange);
}
if (methodCall instanceof PsiMethodCallExpression callExpression) {
registerMethodCallIntentions(builder, callExpression, callExpression.getArgumentList(), resolveHelper);
HighlightFixUtil.registerMethodCallIntentions(asConsumer(builder), callExpression, callExpression.getArgumentList());
if (!PsiTypesUtil.mentionsTypeParameters(actualType, Set.of(method.getTypeParameters()))) {
registerMethodReturnFixAction(builder, resolveResult, methodCall);
HighlightFixUtil.registerMethodReturnFixAction(asConsumer(builder), resolveResult, methodCall);
}
registerTargetTypeFixesBasedOnApplicabilityInference(callExpression, resolveResult, method, builder);
HighlightFixUtil.registerTargetTypeFixesBasedOnApplicabilityInference(callExpression, resolveResult, method, asConsumer(builder));
}
return builder;
}
@@ -459,61 +423,10 @@ public final class HighlightMethodUtil {
hasSurroundingInferenceError(methodCall);
}
private static void registerUsageFixes(@NotNull PsiMethodCallExpression methodCall,
@Nullable HighlightInfo.Builder highlightInfo,
@NotNull TextRange range) {
for (IntentionAction action : QuickFixFactory.getInstance().createCreateMethodFromUsageFixes(methodCall)) {
if (highlightInfo != null) {
highlightInfo.registerFix(action, null, null, range, null);
}
}
}
private static void registerThisSuperFixes(@NotNull PsiMethodCallExpression methodCall,
@Nullable HighlightInfo.Builder highlightInfo,
@NotNull TextRange range) {
for (IntentionAction action : QuickFixFactory.getInstance().createCreateConstructorFromCallExpressionFixes(methodCall)) {
if (highlightInfo != null) {
highlightInfo.registerFix(action, null, null, range, null);
}
}
}
private static void registerTargetTypeFixesBasedOnApplicabilityInference(@NotNull PsiMethodCallExpression methodCall,
@NotNull MethodCandidateInfo resolveResult,
@NotNull PsiMethod resolved,
HighlightInfo.Builder highlightInfo) {
PsiElement parent = PsiUtil.skipParenthesizedExprUp(methodCall.getParent());
PsiVariable variable = null;
if (parent instanceof PsiVariable) {
variable = (PsiVariable)parent;
}
else if (parent instanceof PsiAssignmentExpression assignmentExpression) {
PsiExpression lExpression = assignmentExpression.getLExpression();
if (lExpression instanceof PsiReferenceExpression referenceExpression) {
PsiElement resolve = referenceExpression.resolve();
if (resolve instanceof PsiVariable) {
variable = (PsiVariable)resolve;
}
}
}
if (variable != null) {
PsiType rType = methodCall.getType();
if (rType != null && !variable.getType().isAssignableFrom(rType)) {
PsiType expectedTypeByApplicabilityConstraints = resolveResult.getSubstitutor(false).substitute(resolved.getReturnType());
if (expectedTypeByApplicabilityConstraints != null && !variable.getType().isAssignableFrom(expectedTypeByApplicabilityConstraints) &&
PsiTypesUtil.allTypeParametersResolved(variable, expectedTypeByApplicabilityConstraints)) {
HighlightFixUtil.registerChangeVariableTypeFixes(variable, expectedTypeByApplicabilityConstraints, methodCall, highlightInfo);
}
}
}
}
static HighlightInfo.Builder checkStaticInterfaceCallQualifier(@NotNull PsiJavaCodeReferenceElement referenceToMethod,
@NotNull JavaResolveResult resolveResult,
@NotNull PsiElement elementToHighlight,
@NotNull PsiClass containingClass) {
@NotNull JavaResolveResult resolveResult,
@NotNull PsiElement elementToHighlight,
@NotNull PsiClass containingClass) {
String message = checkStaticInterfaceMethodCallQualifier(referenceToMethod, resolveResult.getCurrentFileResolveScope(), containingClass);
if (message != null) {
HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(message)
@@ -566,28 +479,6 @@ public final class HighlightMethodUtil {
return JavaErrorBundle.message("static.interface.method.call.qualifier");
}
private static void registerMethodReturnFixAction(@NotNull HighlightInfo.Builder highlightInfo,
@NotNull MethodCandidateInfo candidate,
@NotNull PsiCall methodCall) {
if (candidate.getInferenceErrorMessage() != null && methodCall.getParent() instanceof PsiReturnStatement) {
PsiMethod containerMethod = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class, true, PsiLambdaExpression.class);
if (containerMethod != null) {
PsiMethod method = candidate.getElement();
PsiExpression methodCallCopy =
JavaPsiFacade.getElementFactory(method.getProject()).createExpressionFromText(methodCall.getText(), methodCall);
PsiType methodCallTypeByArgs = methodCallCopy.getType();
//ensure type params are not included
methodCallTypeByArgs = JavaPsiFacade.getElementFactory(method.getProject())
.createRawSubstitutor(method).substitute(methodCallTypeByArgs);
if (methodCallTypeByArgs != null) {
@Nullable TextRange fixRange = getFixRange(methodCall);
IntentionAction action = QuickFixFactory.getInstance().createMethodReturnFix(containerMethod, methodCallTypeByArgs, true);
highlightInfo.registerFix(action, null, null, fixRange, null);
}
}
}
}
private static @NotNull List<PsiExpression> mismatchedArgs(PsiExpression @NotNull [] expressions,
PsiSubstitutor substitutor,
PsiParameter @NotNull [] parameters,
@@ -621,17 +512,16 @@ public final class HighlightMethodUtil {
}
static HighlightInfo.Builder checkAmbiguousMethodCallIdentifier(@NotNull PsiReferenceExpression referenceToMethod,
JavaResolveResult @NotNull [] resolveResults,
@NotNull PsiExpressionList list,
@Nullable PsiElement element,
@NotNull JavaResolveResult resolveResult,
@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiResolveHelper resolveHelper,
@NotNull LanguageLevel languageLevel,
@NotNull PsiFile file) {
JavaResolveResult @NotNull [] resolveResults,
@NotNull PsiExpressionList list,
@Nullable PsiElement element,
@NotNull JavaResolveResult resolveResult,
@NotNull PsiMethodCallExpression methodCall,
@NotNull LanguageLevel languageLevel,
@NotNull PsiFile file) {
MethodCandidateInfo methodCandidate2 = findCandidates(resolveResults).second;
if (methodCandidate2 != null) return null;
MethodCandidateInfo[] candidates = toMethodCandidates(resolveResults);
MethodCandidateInfo[] candidates = HighlightFixUtil.toMethodCandidates(resolveResults);
HighlightInfoType highlightInfoType = HighlightInfoType.ERROR;
String description;
@@ -698,19 +588,19 @@ public final class HighlightMethodUtil {
if (element != null && !resolveResult.isStaticsScopeCorrect()) {
HighlightFixUtil.registerStaticProblemQuickFixAction(builder, element, referenceToMethod);
}
registerMethodCallIntentions(builder, methodCall, list, resolveHelper);
HighlightFixUtil.registerMethodCallIntentions(asConsumer(builder), methodCall, list);
TextRange fixRange = getFixRange(elementToHighlight);
CastMethodArgumentFix.REGISTRAR.registerCastActions(candidates, methodCall, builder, fixRange);
WrapWithAdapterMethodCallFix.registerCastActions(candidates, methodCall, builder, fixRange);
WrapObjectWithOptionalOfNullableFix.REGISTAR.registerCastActions(candidates, methodCall, builder, fixRange);
WrapExpressionFix.registerWrapAction(candidates, list.getExpressions(), builder, fixRange);
PermuteArgumentsFix.registerFix(builder, methodCall, candidates, fixRange);
CastMethodArgumentFix.REGISTRAR.registerCastActions(candidates, methodCall, asConsumer(builder));
WrapWithAdapterMethodCallFix.registerCastActions(candidates, methodCall, asConsumer(builder));
WrapObjectWithOptionalOfNullableFix.REGISTAR.registerCastActions(candidates, methodCall, asConsumer(builder));
WrapExpressionFix.registerWrapAction(candidates, list.getExpressions(), asConsumer(builder));
PermuteArgumentsFix.registerFix(asConsumer(builder), methodCall, candidates);
var action = RemoveRepeatingCallFix.createFix(methodCall);
if (action != null) {
builder.registerFix(action, null, null, fixRange, null);
}
registerChangeParameterClassFix(methodCall, list, builder, fixRange);
HighlightFixUtil.registerChangeParameterClassFix(methodCall, list, asConsumer(builder));
if (candidates.length == 0) {
UnresolvedReferenceQuickFixUpdater.getInstance(file.getProject()).registerQuickFixesLater(methodCall.getMethodExpression(), builder);
}
@@ -723,12 +613,11 @@ public final class HighlightMethodUtil {
PsiElement element,
@NotNull JavaResolveResult resolveResult,
@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiResolveHelper resolveHelper,
@NotNull PsiElement elementToHighlight) {
Pair<MethodCandidateInfo, MethodCandidateInfo> pair = findCandidates(resolveResults);
MethodCandidateInfo methodCandidate1 = pair.first;
MethodCandidateInfo methodCandidate2 = pair.second;
MethodCandidateInfo[] candidates = toMethodCandidates(resolveResults);
MethodCandidateInfo[] candidates = HighlightFixUtil.toMethodCandidates(resolveResults);
String description;
String toolTip;
@@ -780,23 +669,23 @@ public final class HighlightMethodUtil {
if (PsiTreeUtil.hasErrorElements(list)) {
return null;
}
TextRange fixRange = getFixRange(elementToHighlight);
HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(elementToHighlight).description(description).escapedToolTip(toolTip);
if (!resolveResult.isAccessible() && resolveResult.isStaticsScopeCorrect() && methodCandidate2 != null) {
HighlightFixUtil.registerAccessQuickFixAction(builder, fixRange, (PsiJvmMember)element, referenceToMethod, resolveResult.getCurrentFileResolveScope(), fixRange);
HighlightFixUtil.registerAccessQuickFixAction(asConsumer(builder), (PsiJvmMember)element, referenceToMethod,
resolveResult.getCurrentFileResolveScope());
}
if (methodCandidate2 == null) {
registerMethodCallIntentions(builder, methodCall, list, resolveHelper);
HighlightFixUtil.registerMethodCallIntentions(asConsumer(builder), methodCall, list);
}
if (element != null && !resolveResult.isStaticsScopeCorrect()) {
HighlightFixUtil.registerStaticProblemQuickFixAction(builder, element, referenceToMethod);
}
CastMethodArgumentFix.REGISTRAR.registerCastActions(candidates, methodCall, builder, fixRange);
WrapWithAdapterMethodCallFix.registerCastActions(candidates, methodCall, builder, fixRange);
WrapObjectWithOptionalOfNullableFix.REGISTAR.registerCastActions(candidates, methodCall, builder, fixRange);
WrapExpressionFix.registerWrapAction(candidates, expressions, builder, fixRange);
PermuteArgumentsFix.registerFix(builder, methodCall, candidates, fixRange);
registerChangeParameterClassFix(methodCall, list, builder, fixRange);
CastMethodArgumentFix.REGISTRAR.registerCastActions(candidates, methodCall, asConsumer(builder));
WrapWithAdapterMethodCallFix.registerCastActions(candidates, methodCall, asConsumer(builder));
WrapObjectWithOptionalOfNullableFix.REGISTAR.registerCastActions(candidates, methodCall, asConsumer(builder));
WrapExpressionFix.registerWrapAction(candidates, expressions, asConsumer(builder));
PermuteArgumentsFix.registerFix(asConsumer(builder), methodCall, candidates);
HighlightFixUtil.registerChangeParameterClassFix(methodCall, list, asConsumer(builder));
return builder;
}
@@ -818,89 +707,6 @@ public final class HighlightMethodUtil {
return Pair.pair(methodCandidate1, methodCandidate2);
}
private static MethodCandidateInfo @NotNull [] toMethodCandidates(JavaResolveResult @NotNull [] resolveResults) {
List<MethodCandidateInfo> candidateList = new ArrayList<>(resolveResults.length);
for (JavaResolveResult result : resolveResults) {
if (!(result instanceof MethodCandidateInfo candidate)) continue;
if (candidate.isAccessible()) candidateList.add(candidate);
}
return candidateList.toArray(new MethodCandidateInfo[0]);
}
private static void registerMethodCallIntentions(@NotNull HighlightInfo.Builder builder,
@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiExpressionList list,
@NotNull PsiResolveHelper resolveHelper) {
TextRange fixRange = getFixRange(methodCall);
PsiExpression qualifierExpression = methodCall.getMethodExpression().getQualifierExpression();
if (qualifierExpression instanceof PsiReferenceExpression referenceExpression) {
PsiElement resolve = referenceExpression.resolve();
if (resolve instanceof PsiClass psiClass &&
psiClass.getContainingClass() != null &&
!psiClass.hasModifierProperty(PsiModifier.STATIC)) {
QuickFixAction.registerQuickFixActions(builder, fixRange, JvmElementActionFactories.createModifierActions(psiClass,
MemberRequestsKt.modifierRequest(
JvmModifier.STATIC,
true)));
}
}
else if (qualifierExpression instanceof PsiSuperExpression superExpression && superExpression.getQualifier() == null) {
QualifySuperArgumentFix.registerQuickFixAction(superExpression, builder);
}
CandidateInfo[] methodCandidates = resolveHelper.getReferencedMethodCandidates(methodCall, false);
IntentionAction action2 = QuickFixFactory.getInstance().createSurroundWithArrayFix(methodCall, null);
builder.registerFix(action2, null, null, fixRange, null);
CastMethodArgumentFix.REGISTRAR.registerCastActions(methodCandidates, methodCall, builder, fixRange);
AddTypeArgumentsFix.REGISTRAR.registerCastActions(methodCandidates, methodCall, builder, fixRange);
CandidateInfo[] candidates = resolveHelper.getReferencedMethodCandidates(methodCall, true);
ChangeStringLiteralToCharInMethodCallFix.registerFixes(candidates, methodCall, builder, fixRange);
WrapWithAdapterMethodCallFix.registerCastActions(methodCandidates, methodCall, builder, fixRange);
IntentionAction action1 = QuickFixFactory.getInstance().createReplaceAddAllArrayToCollectionFix(methodCall);
builder.registerFix(action1, null, null, fixRange, null);
WrapObjectWithOptionalOfNullableFix.REGISTAR.registerCastActions(methodCandidates, methodCall, builder, fixRange);
MethodReturnFixFactory.INSTANCE.registerCastActions(methodCandidates, methodCall, builder, fixRange);
WrapExpressionFix.registerWrapAction(methodCandidates, list.getExpressions(), builder, fixRange);
QualifyThisArgumentFix.registerQuickFixAction(methodCandidates, methodCall, builder, fixRange);
registerMethodAccessLevelIntentions(methodCandidates, methodCall, list, builder, fixRange);
if (!PermuteArgumentsFix.registerFix(builder, methodCall, methodCandidates, fixRange) &&
!MoveParenthesisFix.registerFix(builder, methodCall, methodCandidates, fixRange)) {
registerChangeMethodSignatureFromUsageIntentions(methodCandidates, list, builder, fixRange);
}
for (IntentionAction action : QuickFixFactory.getInstance().getVariableTypeFromCallFixes(methodCall, list)) {
builder.registerFix(action, null, null, fixRange, null);
}
if (methodCandidates.length == 0) {
registerStaticMethodQualifierFixes(methodCall, builder);
}
registerThisSuperFixes(methodCall, builder, fixRange);
registerUsageFixes(methodCall, builder, fixRange);
RemoveRedundantArgumentsFix.registerIntentions(methodCandidates, list, builder, fixRange);
registerChangeParameterClassFix(methodCall, list, builder, fixRange);
}
private static void registerMethodAccessLevelIntentions(CandidateInfo @NotNull [] methodCandidates,
@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiExpressionList exprList,
@Nullable HighlightInfo.Builder info,
@NotNull TextRange fixRange) {
for (CandidateInfo methodCandidate : methodCandidates) {
PsiMethod method = (PsiMethod)methodCandidate.getElement();
if (!methodCandidate.isAccessible() && PsiUtil.isApplicable(method, methodCandidate.getSubstitutor(), exprList)) {
HighlightFixUtil.registerAccessQuickFixAction(info, fixRange, method, methodCall.getMethodExpression(), methodCandidate.getCurrentFileResolveScope(),
fixRange);
}
}
}
private static @NotNull @NlsContexts.Tooltip String createAmbiguousMethodHtmlTooltip(MethodCandidateInfo @NotNull [] methodCandidates) {
return JavaErrorBundle.message("ambiguous.method.html.tooltip",
methodCandidates[0].getElement().getParameterList().getParametersCount() + 2,
@@ -1070,7 +876,7 @@ public final class HighlightMethodUtil {
if (aClass.isEnum()) {
for (PsiField field : aClass.getFields()) {
if (field instanceof PsiEnumConstant) {
// only report abstract method in enum when there are no enum constants to implement it
// only report an abstract method in enum when there are no enum constants to implement it
return null;
}
}
@@ -1174,7 +980,7 @@ public final class HighlightMethodUtil {
PsiStatement[] statements = body == null ? null : body.getStatements();
if (statements == null) return null;
// if we have unhandled exception inside method body, we could not have been called here,
// if we have unhandled exception inside the method body, we could not have been called here,
// so the only problem it can catch here is with super ctr only
Collection<PsiClassType> unhandled = ExceptionUtil.collectUnhandledExceptions(method, method.getContainingClass());
if (unhandled.isEmpty()) return null;
@@ -1256,7 +1062,7 @@ public final class HighlightMethodUtil {
String description = HighlightUtil.accessProblemDescription(classReference, aClass, typeResolveResult);
PsiElement element = ObjectUtils.notNull(classReference.getReferenceNameElement(), classReference);
HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description);
HighlightFixUtil.registerAccessQuickFixAction(info, element.getTextRange(), aClass, classReference, null, null);
HighlightFixUtil.registerAccessQuickFixAction(asConsumer(info), aClass, classReference, null);
errorSink.accept(info);
return;
}
@@ -1270,13 +1076,13 @@ public final class HighlightMethodUtil {
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, info, getFixRange(list));
ConstructorParametersFixer.registerFixActions(classReference, constructorCall, asConsumer(info));
}
TextRange textRange = constructorCall.getTextRange();
QuickFixAction.registerQuickFixActions(
info, textRange, QuickFixFactory.getInstance().createCreateConstructorFromUsageFixes(constructorCall)
);
RemoveRedundantArgumentsFix.registerIntentions(list, info, getFixRange(list));
RemoveRedundantArgumentsFix.registerIntentions(list, asConsumer(info));
errorSink.accept(info);
return;
}
@@ -1340,9 +1146,8 @@ public final class HighlightMethodUtil {
String description = JavaErrorBundle.message("cannot.resolve.constructor", name);
HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.range(elementToHighlight).descriptionAndTooltip(description);
TextRange fixRange = getFixRange(elementToHighlight);
WrapExpressionFix.registerWrapAction(results, list.getExpressions(), info, fixRange);
registerFixesOnInvalidConstructorCall(info, constructorCall, classReference, list, aClass, constructors, results, fixRange);
WrapExpressionFix.registerWrapAction(results, list.getExpressions(), asConsumer(info));
HighlightFixUtil.registerFixesOnInvalidConstructorCall(asConsumer(info), constructorCall, classReference, list, aClass, constructors, results);
errorSink.accept(info);
reported = true;
}
@@ -1360,8 +1165,9 @@ public final class HighlightMethodUtil {
if (constructorCall instanceof PsiNewExpression newExpression) {
methodCandidates = resolveHelper.getReferencedMethodCandidates(newExpression, true);
}
registerFixesOnInvalidConstructorCall(info, constructorCall, classReference, list, aClass, constructors, methodCandidates, getFixRange(list));
registerMethodReturnFixAction(info, result, constructorCall);
HighlightFixUtil.registerFixesOnInvalidConstructorCall(asConsumer(info), constructorCall, classReference, list, aClass, constructors,
methodCandidates);
HighlightFixUtil.registerMethodReturnFixAction(asConsumer(info), result, constructorCall);
errorSink.accept(info);
reported = true;
}
@@ -1377,7 +1183,7 @@ public final class HighlightMethodUtil {
HighlightInfo.Builder info = result == null || reported ? null : checkVarargParameterErasureToBeAccessible(result, constructorCall);
if (result != null && info == null && !reported) {
info = createIncompatibleTypeHighlightInfo(constructorCall, resolveHelper, result, constructorCall);
info = createIncompatibleTypeHighlightInfo(constructorCall, result, constructorCall);
}
errorSink.accept(info);
}
@@ -1420,40 +1226,13 @@ public final class HighlightMethodUtil {
return null;
}
private static void registerFixesOnInvalidConstructorCall(@NotNull HighlightInfo.Builder builder, @NotNull PsiConstructorCall constructorCall,
@Nullable PsiJavaCodeReferenceElement classReference,
@NotNull PsiExpressionList list,
@NotNull PsiClass aClass,
PsiMethod @NotNull [] constructors,
JavaResolveResult @NotNull [] results,
TextRange fixRange) {
if (classReference != null) {
ConstructorParametersFixer.registerFixActions(classReference, constructorCall, builder, fixRange);
ChangeTypeArgumentsFix.registerIntentions(results, list, builder, aClass, fixRange);
}
else if (aClass.isEnum()) {
ConstructorParametersFixer.registerFixActions(aClass, PsiSubstitutor.EMPTY, constructorCall, builder, fixRange);
}
ChangeStringLiteralToCharInMethodCallFix.registerFixes(constructors, constructorCall, builder, fixRange);
IntentionAction action = QuickFixFactory.getInstance().createSurroundWithArrayFix(constructorCall, null);
builder.registerFix(action, null, null, fixRange, null);
if (!PermuteArgumentsFix.registerFix(builder, constructorCall, toMethodCandidates(results), fixRange)) {
registerChangeMethodSignatureFromUsageIntentions(results, list, builder, fixRange);
}
QuickFixAction.registerQuickFixActions(
builder, constructorCall.getTextRange(), QuickFixFactory.getInstance().createCreateConstructorFromUsageFixes(constructorCall)
);
registerChangeParameterClassFix(constructorCall, list, builder, fixRange);
RemoveRedundantArgumentsFix.registerIntentions(results, list, builder, fixRange);
}
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(info, ref.getTextRange(), resolved, ref, result.getCurrentFileResolveScope(), null);
HighlightFixUtil.registerAccessQuickFixAction(asConsumer(info), resolved, ref, result.getCurrentFileResolveScope());
}
return info;
}
@@ -1487,66 +1266,6 @@ public final class HighlightMethodUtil {
return builder.toString();
}
private static void registerChangeParameterClassFix(@NotNull PsiCall methodCall,
@NotNull PsiExpressionList list,
@Nullable HighlightInfo.Builder highlightInfo, TextRange fixRange) {
JavaResolveResult result = methodCall.resolveMethodGenerics();
PsiMethod method = (PsiMethod)result.getElement();
PsiSubstitutor substitutor = result.getSubstitutor();
PsiExpression[] expressions = list.getExpressions();
if (method == null) return;
PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length != expressions.length) return;
for (int i = 0; i < expressions.length; i++) {
PsiExpression expression = expressions[i];
PsiParameter parameter = parameters[i];
PsiType expressionType = expression.getType();
PsiType parameterType = substitutor.substitute(parameter.getType());
if (expressionType == null || expressionType instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(expressionType) || expressionType instanceof PsiArrayType) continue;
if (parameterType instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(parameterType) || parameterType instanceof PsiArrayType) continue;
if (parameterType.isAssignableFrom(expressionType)) continue;
PsiClass parameterClass = PsiUtil.resolveClassInType(parameterType);
PsiClass expressionClass = PsiUtil.resolveClassInType(expressionType);
if (parameterClass == null || expressionClass == null) continue;
if (expressionClass instanceof PsiAnonymousClass) continue;
if (expressionClass.isInheritor(parameterClass, true)) continue;
IntentionAction action = QuickFixFactory.getInstance().createChangeParameterClassFix(expressionClass, (PsiClassType)parameterType);
if (highlightInfo != null) {
highlightInfo.registerFix(action, null, null, fixRange, null);
}
}
}
private static void registerChangeMethodSignatureFromUsageIntentions(JavaResolveResult @NotNull [] candidates,
@NotNull PsiExpressionList list,
@NotNull HighlightInfo.Builder builder,
@Nullable TextRange fixRange) {
if (candidates.length == 0) return;
PsiExpression[] expressions = list.getExpressions();
for (JavaResolveResult candidate : candidates) {
registerChangeMethodSignatureFromUsageIntention(expressions, builder, fixRange, candidate, list);
}
}
private static void registerChangeMethodSignatureFromUsageIntention(PsiExpression @NotNull [] expressions,
@NotNull HighlightInfo.Builder builder,
@Nullable TextRange fixRange,
@NotNull JavaResolveResult candidate,
@NotNull PsiElement context) {
if (!candidate.isStaticsScopeCorrect()) return;
PsiMethod method = (PsiMethod)candidate.getElement();
PsiSubstitutor substitutor = candidate.getSubstitutor();
if (method != null && context.getManager().isInProject(method)) {
IntentionAction fix = QuickFixFactory.getInstance()
.createChangeMethodSignatureFromUsageFix(method, expressions, substitutor, context, false, 2);
builder.registerFix(fix, null, null, fixRange, null);
IntentionAction f2 =
QuickFixFactory.getInstance()
.createChangeMethodSignatureFromUsageReverseOrderFix(method, expressions, substitutor, context, false, 2);
builder.registerFix(f2, null, null, fixRange, null);
}
}
static PsiType determineReturnType(@NotNull PsiMethod method) {
PsiManager manager = method.getManager();
PsiReturnStatement[] returnStatements = PsiUtil.findReturnStatements(method);
@@ -594,7 +594,7 @@ public final class HighlightUtil {
IntentionAction action = getFixFactory().createMethodReturnFix(method, valueType, true);
errorResult.registerFix(action, null, null, null, null);
}
HighlightFixUtil.registerChangeParameterClassFix(returnType, valueType, errorResult);
HighlightFixUtil.registerChangeParameterClassFix(returnType, valueType, asConsumer(errorResult));
}
}
}
@@ -1275,7 +1275,7 @@ public final class HighlightUtil {
String description = JavaErrorBundle.message("unqualified.super.disallowed");
HighlightInfo.Builder builder =
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expr).descriptionAndTooltip(description);
QualifySuperArgumentFix.registerQuickFixAction(superExpression, builder);
QualifySuperArgumentFix.registerQuickFixAction(superExpression, asConsumer(builder));
return builder;
}
}
@@ -2172,7 +2172,7 @@ public final class HighlightUtil {
HighlightInfo.Builder info =
HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(refName).descriptionAndTooltip(description);
if (result.isStaticsScopeCorrect() && resolved instanceof PsiJvmMember) {
HighlightFixUtil.registerAccessQuickFixAction(info, refName.getTextRange(), (PsiJvmMember)resolved, ref, result.getCurrentFileResolveScope(), null);
HighlightFixUtil.registerAccessQuickFixAction(asConsumer(info), (PsiJvmMember)resolved, ref, result.getCurrentFileResolveScope());
if (ref instanceof PsiReferenceExpression expression) {
IntentionAction action = getFixFactory().createRenameWrongRefFix(expression);
info.registerFix(action, null, null, null, null);
@@ -105,6 +105,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
private final Map<PsiElement, PsiMethod> myInsideConstructorOfClassCache = new HashMap<>(); // null value means "cached but no corresponding ctr found"
private boolean myHasError; // true if myHolder.add() was called with HighlightInfo of >=ERROR severity. On each .visit(PsiElement) call this flag is reset. Useful to determine whether the error was already reported while visiting this PsiElement.
@Contract(pure = true)
private @NotNull PsiResolveHelper getResolveHelper() {
return PsiResolveHelper.getInstance(getProject());
}
@@ -380,7 +381,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (parentInferenceErrorMessage != null && (returnErrors == null || !returnErrors.containsValue(parentInferenceErrorMessage))) {
if (returnErrors == null) return;
HighlightInfo.Builder info =
HighlightMethodUtil.createIncompatibleTypeHighlightInfo(callExpression, getResolveHelper(),
HighlightMethodUtil.createIncompatibleTypeHighlightInfo(callExpression,
parentCallResolveResult, expression);
if (info != null) {
for (PsiElement errorElement : returnErrors.keySet()) {
@@ -578,16 +579,15 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (results == null) return;
JavaResolveResult result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
PsiResolveHelper resolveHelper;
if ((!result.isAccessible() || !result.isStaticsScopeCorrect()) &&
!HighlightMethodUtil.isDummyConstructorCall(expression, resolveHelper = getResolveHelper(), list, referenceExpression) &&
!HighlightMethodUtil.isDummyConstructorCall(expression, getResolveHelper(), list, referenceExpression) &&
// this check is for fake expression from JspMethodCallImpl
referenceExpression.getParent() == expression) {
try {
if (PsiTreeUtil.findChildrenOfType(expression.getArgumentList(), PsiLambdaExpression.class).isEmpty()) {
PsiElement resolved = result.getElement();
add(HighlightMethodUtil.checkAmbiguousMethodCallArguments(referenceExpression, results, list, resolved, result, expression,
resolveHelper, list));
list));
}
}
catch (IndexNotReadyException ignored) {
@@ -788,7 +788,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
visitElement(expression);
if (!hasErrorResults()) {
try {
HighlightMethodUtil.checkMethodCall(expression, getResolveHelper(), myLanguageLevel, myJavaSdkVersion, myFile,
HighlightMethodUtil.checkMethodCall(expression, getResolveHelper(), myJavaSdkVersion,
myErrorSink);
}
catch (IndexNotReadyException ignored) {
@@ -1076,13 +1076,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!HighlightMethodUtil.isDummyConstructorCall(methodCallExpression, resolveHelper, list, expression)) {
try {
add(HighlightMethodUtil.checkAmbiguousMethodCallIdentifier(
expression, results, list, resolved, result, methodCallExpression, resolveHelper, myLanguageLevel, myFile));
expression, results, list, resolved, result, methodCallExpression, myLanguageLevel, myFile));
if (!PsiTreeUtil.findChildrenOfType(methodCallExpression.getArgumentList(), PsiLambdaExpression.class).isEmpty()) {
PsiElement nameElement = expression.getReferenceNameElement();
if (nameElement != null) {
add(HighlightMethodUtil.checkAmbiguousMethodCallArguments(
expression, results, list, resolved, result, methodCallExpression, resolveHelper, nameElement));
expression, results, list, resolved, result, methodCallExpression, nameElement));
}
}
}
@@ -1125,8 +1125,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
String accessProblem = HighlightUtil.accessProblemDescription(expression, method, result);
HighlightInfo.Builder info =
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(accessProblem);
HighlightFixUtil.registerAccessQuickFixAction(info, expression.getTextRange(), (PsiJvmMember)method, expression,
result.getCurrentFileResolveScope(), null);
HighlightFixUtil.registerAccessQuickFixAction(HighlightUtil.asConsumer(info), (PsiJvmMember)method, expression, result.getCurrentFileResolveScope());
add(info);
}
@@ -286,7 +286,7 @@ final class JavaErrorFixProvider {
multi(TYPE_INCOMPATIBLE, error -> {
JavaIncompatibleTypeErrorContext context = error.context();
PsiElement anchor = error.psi();
PsiElement parent = anchor.getParent();
PsiElement parent = PsiUtil.skipParenthesizedExprUp(anchor.getParent());
PsiType lType = context.lType();
PsiType rType = context.rType();
if (anchor instanceof PsiJavaCodeReferenceElement && parent instanceof PsiReferenceList &&
@@ -312,10 +312,21 @@ final class JavaErrorFixProvider {
assignment.getOperationTokenType() == JavaTokenType.EQ) {
registrar.add(myFactory.createAssignmentToComparisonFix(assignment));
}
if (expression.getParent() instanceof PsiArrayInitializerExpression initializerList) {
if (parent instanceof PsiArrayInitializerExpression initializerList) {
PsiType sameType = JavaHighlightUtil.sameType(initializerList.getInitializers());
ContainerUtil.addIfNotNull(registrar, sameType == null ? null : VariableArrayTypeFix.createFix(initializerList, sameType));
}
else if (parent instanceof PsiReturnStatement && rType != null) {
if (PsiTreeUtil.getParentOfType(parent, PsiMethod.class, PsiLambdaExpression.class) instanceof PsiMethod containingMethod) {
registrar.add(myFactory.createMethodReturnFix(containingMethod, rType, true, true));
}
}
else if (parent instanceof PsiLocalVariable var && rType != null) {
HighlightFixUtil.registerChangeVariableTypeFixes(var, rType, var.getInitializer(), registrar::add);
}
if (expression instanceof PsiMethodCallExpression callExpression) {
HighlightFixUtil.registerCallInferenceFixes(callExpression, registrar::add);
}
return registrar;
}
if (anchor instanceof PsiParameter parameter && parent instanceof PsiForeachStatement forEach) {
@@ -325,7 +336,15 @@ final class JavaErrorFixProvider {
}
return List.of();
});
multi(CALL_TYPE_INFERENCE_ERROR, error -> {
PsiCall methodCall = error.psi();
if (methodCall instanceof PsiMethodCallExpression callExpression) {
List<CommonIntentionAction> registrar = new ArrayList<>();
HighlightFixUtil.registerCallInferenceFixes(callExpression, registrar::add);
return registrar;
}
return List.of();
});
}
private void createGenericFixes() {
@@ -337,6 +356,8 @@ final class JavaErrorFixProvider {
PsiClassType type = JavaPsiFacade.getElementFactory(error.project()).createType(error.psi());
return myFactory.createExtendsListFix(error.context(), type, false);
});
fix(CALL_STATIC_INTERFACE_METHOD_QUALIFIER, error -> myFactory.createAccessStaticViaInstanceFix(
error.psi(), error.psi().advancedResolve(true)));
}
private void createClassFixes() {
@@ -1,11 +1,10 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.util.PsiTypesUtil;
@@ -15,13 +14,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Consumer;
public abstract class ArgumentFixerActionFactory {
private static final Logger LOG = Logger.getInstance(ArgumentFixerActionFactory.class);
protected abstract @Nullable PsiExpression getModifiedArgument(PsiExpression expression, final PsiType toType) throws IncorrectOperationException;
public void registerCastActions(CandidateInfo @NotNull [] candidates, @NotNull PsiCall call, @NotNull HighlightInfo.Builder highlightInfo, final TextRange fixRange) {
public void registerCastActions(CandidateInfo @NotNull [] candidates, @NotNull PsiCall call, @NotNull Consumer<? super CommonIntentionAction> info) {
if (candidates.length == 0) return;
List<CandidateInfo> methodCandidates = new ArrayList<>(Arrays.asList(candidates));
PsiExpressionList list = call.getArgumentList();
@@ -94,7 +94,7 @@ public abstract class ArgumentFixerActionFactory {
if (newCall != null) {
doCheckNewCall(expectedTypeByParent, newCall, () -> {
for (Map.Entry<Integer, PsiType> entry : potentialCasts.entrySet()) {
registerCastIntention(highlightInfo, fixRange, list, suggestedCasts, entry);
registerCastIntention(info, list, suggestedCasts, entry);
}
potentialCasts.clear();
});
@@ -103,7 +103,7 @@ public abstract class ArgumentFixerActionFactory {
for (Map.Entry<Integer, PsiType> entry : potentialCasts.entrySet()) {
PsiCall callWithSingleCast = replaceWithCast(expressions, call, entry, true);
if (callWithSingleCast == null) continue;
doCheckNewCall(expectedTypeByParent, callWithSingleCast, () -> registerCastIntention(highlightInfo, fixRange, list, suggestedCasts, entry));
doCheckNewCall(expectedTypeByParent, callWithSingleCast, () -> registerCastIntention(info, list, suggestedCasts, entry));
}
}
}
@@ -124,15 +124,14 @@ public abstract class ArgumentFixerActionFactory {
}
}
private void registerCastIntention(@NotNull HighlightInfo.Builder builder,
TextRange fixRange,
private void registerCastIntention(@NotNull Consumer<? super CommonIntentionAction> info,
PsiExpressionList list,
Map<Integer, Set<String>> suggestedCasts,
Map.Entry<Integer, PsiType> entry) {
suggestedCasts.get(entry.getKey()).add(entry.getValue().getCanonicalText());
IntentionAction action = createFix(list, entry.getKey(), entry.getValue());
if (action != null) {
builder.registerFix(action, null, null, fixRange, null);
info.accept(action);
}
}
@@ -2,14 +2,13 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.codeInsight.intention.PriorityAction;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.Presentation;
import com.intellij.modcommand.PsiUpdateModCommandAction;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
@@ -17,10 +16,10 @@ import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
@@ -67,7 +66,7 @@ public final class ChangeStringLiteralToCharInMethodCallFix extends PsiUpdateMod
}
public static void registerFixes(final PsiMethod @NotNull [] candidates, final @NotNull PsiConstructorCall call,
final @NotNull HighlightInfo.Builder out, TextRange fixRange) {
@NotNull Consumer<? super CommonIntentionAction> info) {
final Set<PsiLiteralExpression> literals = new HashSet<>();
if (call.getArgumentList() == null) {
return;
@@ -77,15 +76,13 @@ public final class ChangeStringLiteralToCharInMethodCallFix extends PsiUpdateMod
exactMatch |= findMatchingExpressions(call.getArgumentList().getExpressions(), method, literals);
}
if (! exactMatch) {
processLiterals(literals, out, fixRange);
processLiterals(literals, info);
}
}
public static void registerFixes(final CandidateInfo @NotNull [] candidates,
final @NotNull PsiMethodCallExpression methodCall,
final @Nullable HighlightInfo.Builder info,
@Nullable TextRange fixRange) {
if (info == null) return;
@NotNull Consumer<? super CommonIntentionAction> info) {
final Set<PsiLiteralExpression> literals = new HashSet<>();
boolean exactMatch = false;
for (CandidateInfo candidate : candidates) {
@@ -95,15 +92,15 @@ public final class ChangeStringLiteralToCharInMethodCallFix extends PsiUpdateMod
}
}
if (!exactMatch) {
processLiterals(literals, info, fixRange);
processLiterals(literals, info);
}
}
private static void processLiterals(final @NotNull Set<? extends PsiLiteralExpression> literals,
final @NotNull HighlightInfo.Builder info, TextRange fixRange) {
@NotNull Consumer<? super CommonIntentionAction> info) {
for (PsiLiteralExpression literal : literals) {
final ChangeStringLiteralToCharInMethodCallFix fix = new ChangeStringLiteralToCharInMethodCallFix(literal);
info.registerFix(fix, null, null, fixRange, null);
info.accept(fix);
}
}
@@ -1,7 +1,7 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.codeInsight.intention.PriorityAction;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.java.analysis.JavaAnalysisBundle;
@@ -10,7 +10,6 @@ import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.Presentation;
import com.intellij.modcommand.PsiUpdateModCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -21,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import java.util.function.Consumer;
public class ChangeTypeArgumentsFix extends PsiUpdateModCommandAction<PsiNewExpression> {
private static final Logger LOG = Logger.getInstance(ChangeTypeArgumentsFix.class);
@@ -108,28 +108,26 @@ public class ChangeTypeArgumentsFix extends PsiUpdateModCommandAction<PsiNewExpr
public static void registerIntentions(JavaResolveResult @NotNull [] candidates,
@NotNull PsiExpressionList list,
@NotNull HighlightInfo.Builder highlightInfo,
PsiClass psiClass, TextRange fixRange) {
@NotNull Consumer<? super CommonIntentionAction> info,
PsiClass psiClass) {
if (candidates.length == 0) return;
PsiExpression[] expressions = list.getExpressions();
for (JavaResolveResult candidate : candidates) {
registerIntention(expressions, highlightInfo, psiClass, candidate, list, fixRange);
registerIntention(expressions, info, psiClass, candidate, list);
}
}
private static void registerIntention(PsiExpression @NotNull [] expressions,
@NotNull HighlightInfo.Builder builder,
@NotNull Consumer<? super CommonIntentionAction> info,
PsiClass psiClass,
@NotNull JavaResolveResult candidate,
@NotNull PsiElement context,
TextRange fixRange) {
@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;
final ChangeTypeArgumentsFix fix = new ChangeTypeArgumentsFix(method, psiClass, expressions, newExpression);
builder.registerFix(fix, null, null, fixRange, null);
info.accept(new ChangeTypeArgumentsFix(method, psiClass, expressions, newExpression));
}
}
}
@@ -10,37 +10,36 @@
*/
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.openapi.util.TextRange;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
public final class ConstructorParametersFixer {
public static void registerFixActions(@NotNull PsiJavaCodeReferenceElement ctrRef,
@NotNull PsiConstructorCall constructorCall,
@NotNull HighlightInfo.Builder builder,
@NotNull TextRange fixRange) {
@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, builder, fixRange);
registerFixActions(aClass, substitutor, constructorCall, info);
}
public static void registerFixActions(@NotNull PsiClass aClass,
@NotNull PsiSubstitutor substitutor,
@NotNull PsiConstructorCall constructorCall,
@NotNull HighlightInfo.Builder builder,
@NotNull TextRange fixRange) {
@NotNull Consumer<? super CommonIntentionAction> info) {
PsiMethod[] methods = aClass.getConstructors();
CandidateInfo[] candidates = new CandidateInfo[methods.length];
for (int i = 0; i < candidates.length; i++) {
candidates[i] = new CandidateInfo(methods[i], substitutor);
}
CastMethodArgumentFix.REGISTRAR.registerCastActions(candidates, constructorCall, builder, fixRange);
AddTypeArgumentsFix.REGISTRAR.registerCastActions(candidates, constructorCall, builder, fixRange);
WrapObjectWithOptionalOfNullableFix.REGISTAR.registerCastActions(candidates, constructorCall, builder, fixRange);
WrapWithAdapterMethodCallFix.registerCastActions(candidates, constructorCall, builder, fixRange);
CastMethodArgumentFix.REGISTRAR.registerCastActions(candidates, constructorCall, info);
AddTypeArgumentsFix.REGISTRAR.registerCastActions(candidates, constructorCall, info);
WrapObjectWithOptionalOfNullableFix.REGISTAR.registerCastActions(candidates, constructorCall, info);
WrapWithAdapterMethodCallFix.registerCastActions(candidates, constructorCall, info);
}
}
@@ -2,14 +2,13 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.codeInsight.intention.PriorityAction;
import com.intellij.codeInspection.util.IntentionFamilyName;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.Presentation;
import com.intellij.modcommand.PsiUpdateModCommandAction;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.util.ArrayUtil;
@@ -20,6 +19,7 @@ import it.unimi.dsi.fastutil.ints.IntSet;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import java.util.function.Consumer;
public final class MoveParenthesisFix extends PsiUpdateModCommandAction<PsiCallExpression> {
private final int myPos;
@@ -78,7 +78,7 @@ public final class MoveParenthesisFix extends PsiUpdateModCommandAction<PsiCallE
return parentCopy;
}
public static boolean registerFix(@NotNull HighlightInfo.Builder info, PsiCallExpression callExpression, final CandidateInfo[] candidates, TextRange fixRange) {
public static boolean registerFix(@NotNull Consumer<? super CommonIntentionAction> info, PsiCallExpression callExpression, final CandidateInfo[] candidates) {
PsiExpressionList parent = ObjectUtils.tryCast(callExpression.getParent(), PsiExpressionList.class);
if (parent == null) return false;
PsiCallExpression parentCall = ObjectUtils.tryCast(parent.getParent(), PsiCallExpression.class);
@@ -112,7 +112,7 @@ public final class MoveParenthesisFix extends PsiUpdateModCommandAction<PsiCallE
fix = new MoveParenthesisFix(parentCall, pos, shift);
}
if (fix == null) return false;
info.registerFix(fix, null, null, fixRange, null);
info.accept(fix);
return true;
}
}
@@ -2,14 +2,13 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.codeInsight.intention.PriorityAction;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.Presentation;
import com.intellij.modcommand.PsiUpdateModCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
@@ -22,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
public final class PermuteArgumentsFix extends PsiUpdateModCommandAction<PsiCall> {
private static final Logger LOG = Logger.getInstance(PermuteArgumentsFix.class);
@@ -47,7 +47,7 @@ public final class PermuteArgumentsFix extends PsiUpdateModCommandAction<PsiCall
Objects.requireNonNull(call.getArgumentList()).replace(Objects.requireNonNull(myPermutation.getArgumentList()));
}
public static boolean registerFix(@NotNull HighlightInfo.Builder info, PsiCall callExpression, final CandidateInfo[] candidates, final TextRange fixRange) {
public static boolean registerFix(@NotNull Consumer<? super CommonIntentionAction> info, PsiCall callExpression, final CandidateInfo[] candidates) {
PsiExpression[] expressions = Objects.requireNonNull(callExpression.getArgumentList()).getExpressions();
if (expressions.length < 2) return false;
List<PsiCall> permutations = new ArrayList<>();
@@ -83,7 +83,7 @@ public final class PermuteArgumentsFix extends PsiUpdateModCommandAction<PsiCall
}
if (permutations.size() == 1) {
PermuteArgumentsFix fix = new PermuteArgumentsFix(callExpression, permutations.get(0));
info.registerFix(fix, null, null, fixRange, null);
info.accept(fix);
return true;
}
@@ -2,13 +2,15 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
public class QualifySuperArgumentFix extends QualifyThisOrSuperArgumentFix {
private QualifySuperArgumentFix(@NotNull PsiExpression expression, @NotNull PsiClass psiClass) {
super(expression, psiClass);
@@ -24,7 +26,7 @@ public class QualifySuperArgumentFix extends QualifyThisOrSuperArgumentFix {
return RefactoringChangeUtil.createSuperExpression(manager, myPsiClass);
}
public static void registerQuickFixAction(@NotNull PsiSuperExpression expr, @NotNull HighlightInfo.Builder highlightInfo) {
public static void registerQuickFixAction(@NotNull PsiSuperExpression expr, @NotNull Consumer<? super CommonIntentionAction> info) {
LOG.assertTrue(expr.getQualifier() == null);
final PsiClass containingClass = PsiTreeUtil.getParentOfType(expr, PsiClass.class);
if (containingClass != null) {
@@ -47,7 +49,7 @@ public class QualifySuperArgumentFix extends QualifyThisOrSuperArgumentFix {
}
if (method != null && !method.hasModifierProperty(PsiModifier.ABSTRACT)) {
var action = new QualifySuperArgumentFix(expr, superClass);
highlightInfo.registerFix(action, null, null, null, null);
info.accept(action);
}
}
}
@@ -2,8 +2,7 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.openapi.util.TextRange;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.util.PsiTreeUtil;
@@ -14,6 +13,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
public class QualifyThisArgumentFix extends QualifyThisOrSuperArgumentFix{
public QualifyThisArgumentFix(@NotNull PsiExpression expression, @NotNull PsiClass psiClass) {
@@ -30,7 +30,7 @@ public class QualifyThisArgumentFix extends QualifyThisOrSuperArgumentFix{
return RefactoringChangeUtil.createThisExpression(manager, myPsiClass);
}
public static void registerQuickFixAction(CandidateInfo[] candidates, PsiCall call, @NotNull HighlightInfo.Builder builder, final TextRange fixRange) {
public static void registerQuickFixAction(CandidateInfo[] candidates, PsiCall call, @NotNull Consumer<? super CommonIntentionAction> info) {
if (candidates.length == 0) return;
final Set<PsiClass> containingClasses = new HashSet<>();
@@ -70,8 +70,7 @@ public class QualifyThisArgumentFix extends QualifyThisOrSuperArgumentFix{
if (!TypeConversionUtil.isAssignable(parameterType, exprType)) {
final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(parameterType);
if (psiClass != null && containingClasses.contains(psiClass)) {
var action = new QualifyThisArgumentFix(expression, psiClass);
builder.registerFix(action, null, null, fixRange, null);
info.accept(new QualifyThisArgumentFix(expression, psiClass));
}
}
}
@@ -2,14 +2,13 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.Presentation;
import com.intellij.modcommand.PsiUpdateModCommandAction;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
@@ -17,6 +16,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.function.Consumer;
public final class RemoveRedundantArgumentsFix extends PsiUpdateModCommandAction<PsiExpressionList> {
private final PsiMethod myTargetMethod;
@@ -79,24 +79,21 @@ public final class RemoveRedundantArgumentsFix extends PsiUpdateModCommandAction
public static void registerIntentions(JavaResolveResult @NotNull [] candidates,
@NotNull PsiExpressionList arguments,
@NotNull HighlightInfo.Builder highlightInfo,
TextRange fixRange) {
@NotNull Consumer<? super CommonIntentionAction> info) {
for (JavaResolveResult candidate : candidates) {
registerIntention(arguments, highlightInfo, fixRange, candidate);
registerIntention(arguments, info, candidate);
}
}
public static void registerIntentions(@NotNull PsiExpressionList arguments,
@NotNull HighlightInfo.Builder highlightInfo,
TextRange fixRange) {
@NotNull Consumer<? super CommonIntentionAction> info) {
if (!arguments.isEmpty()) {
highlightInfo.registerFix(new ForImplicitConstructorAction(arguments), null, null, fixRange, null);
info.accept(new ForImplicitConstructorAction(arguments));
}
}
private static void registerIntention(@NotNull PsiExpressionList arguments,
@NotNull HighlightInfo.Builder builder,
TextRange fixRange,
@NotNull Consumer<? super CommonIntentionAction> info,
@NotNull JavaResolveResult candidate) {
if (!candidate.isStaticsScopeCorrect()) return;
PsiMethod method = (PsiMethod)candidate.getElement();
@@ -108,8 +105,7 @@ public final class RemoveRedundantArgumentsFix extends PsiUpdateModCommandAction
// Avoid creating recursive constructor call
return;
}
var action = new RemoveRedundantArgumentsFix(method, arguments, substitutor);
builder.registerFix(action, null, null, fixRange, null);
info.accept(new RemoveRedundantArgumentsFix(method, arguments, substitutor));
}
private static class ForImplicitConstructorAction extends PsiUpdateModCommandAction<PsiExpressionList> {
@@ -2,13 +2,12 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.Presentation;
import com.intellij.modcommand.PsiUpdateModCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.search.GlobalSearchScope;
@@ -19,6 +18,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
public class WrapExpressionFix extends PsiUpdateModCommandAction<PsiExpression> {
private static final Logger LOG = Logger.getInstance(WrapExpressionFix.class);
@@ -139,8 +139,7 @@ public class WrapExpressionFix extends PsiUpdateModCommandAction<PsiExpression>
public static void registerWrapAction(JavaResolveResult[] candidates,
PsiExpression[] expressions,
@NotNull HighlightInfo.Builder highlightInfo,
TextRange fixRange) {
@NotNull Consumer<? super CommonIntentionAction> info) {
PsiType expectedType = null;
PsiExpression expr = null;
@@ -179,8 +178,7 @@ public class WrapExpressionFix extends PsiUpdateModCommandAction<PsiExpression>
}
if (expectedType != null) {
var action = new WrapExpressionFix(expectedType, expr, null);
highlightInfo.registerFix(action, null, null, fixRange, null);
info.accept(new WrapExpressionFix(expectedType, expr, null));
}
}
}
@@ -2,7 +2,7 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.CommonIntentionAction;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.PriorityAction;
@@ -13,7 +13,6 @@ import com.intellij.modcommand.Presentation;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Predicates;
import com.intellij.openapi.util.TextRange;
import com.intellij.pom.java.JavaFeature;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -36,6 +35,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
import static com.intellij.pom.java.LanguageLevel.JDK_11;
@@ -346,10 +346,9 @@ public final class WrapWithAdapterMethodCallFix extends LocalQuickFixAndIntentio
public static void registerCastActions(CandidateInfo @NotNull [] candidates,
@NotNull PsiCall call,
@NotNull HighlightInfo.Builder highlightInfo,
final TextRange fixRange) {
@NotNull Consumer<? super CommonIntentionAction> info) {
for (AbstractWrapper wrapper : WRAPPERS) {
wrapper.registerCastActions(candidates, call, highlightInfo, fixRange);
wrapper.registerCastActions(candidates, call, info);
}
}
}
@@ -4,9 +4,9 @@ class a {
void f() {
assert false : <error descr="'void' type is not allowed here">System.out.println()</error>;
assert <error descr="Incompatible types. Found: 'int', required: 'boolean'">0</error>;
assert <error descr="Incompatible types. Found: 'char', required: 'boolean'">'a'</error>;
assert <error descr="Incompatible types. Found: 'java.lang.String', required: 'boolean'">""</error>;
assert <error descr="Incompatible types. Found: 'void', required: 'boolean'">f()</error>;
assert <error descr="Incompatible types. Found: 'int', required: 'boolean'">0;</error>
assert <error descr="Incompatible types. Found: 'char', required: 'boolean'">'a';</error>
assert <error descr="Incompatible types. Found: 'java.lang.String', required: 'boolean'">"";</error>
assert <error descr="Incompatible types. Found: 'void', required: 'boolean'">f</error>();
}
}
@@ -1,6 +1,6 @@
class YouAreNotMyType {
String[][] oldLady() {
return new String[][]{<error descr="Incompatible types. Found: 'java.lang.Integer[]', required: 'java.lang.String[]'">new Integer[]{}</error>};
return new String[][]{new <error descr="Incompatible types. Found: 'java.lang.Integer[]', required: 'java.lang.String[]'">Integer</error>[]{}};
}
}
@@ -12,9 +12,9 @@ class c {
int i8 = <error descr="Incompatible types. Found: 'java.lang.String', required: 'boolean'">"ff" + true</error> ? 1 : 2;
assert <error descr="Incompatible types. Found: 'int', required: 'boolean'">0</error>;
assert <error descr="Incompatible types. Found: 'char', required: 'boolean'">'a'</error>;
assert <error descr="Incompatible types. Found: 'java.lang.String', required: 'boolean'">""</error>;
assert <error descr="Incompatible types. Found: 'void', required: 'boolean'">f()</error>;
assert <error descr="Incompatible types. Found: 'int', required: 'boolean'">0;</error>
assert <error descr="Incompatible types. Found: 'char', required: 'boolean'">'a';</error>
assert <error descr="Incompatible types. Found: 'java.lang.String', required: 'boolean'">"";</error>
assert <error descr="Incompatible types. Found: 'void', required: 'boolean'">f</error>();
}
}
@@ -11,7 +11,7 @@ class a {
}
synchronized (<error descr="Incompatible types. Found: 'boolean', required: 'java.lang.Object'">true</error>) {
}
synchronized (<error descr="Incompatible types. Found: 'void', required: 'java.lang.Object'">System.out.println()</error> ) {
synchronized (System.out.<error descr="Incompatible types. Found: 'void', required: 'java.lang.Object'">println</error>() ) {
}
@@ -7,13 +7,13 @@ import java.util.stream.Stream;
public class Demo {
Map<Path, Long> fileSizes(List<File> files) {
return <error descr="Incompatible types. Found: 'java.util.Map<java.io.File,java.lang.Long>', required: 'java.util.Map<java.nio.file.Path,java.lang.Long>'">files.stream().collect(Collectors.toMap(f -> f, f -> f.length()));</error>
return files.stream().<error descr="Incompatible types. Found: 'java.util.Map<java.io.File,java.lang.Long>', required: 'java.util.Map<java.nio.file.Path,java.lang.Long>'">collect</error>(Collectors.toMap(f -> f, f -> f.length()));
}
void test() {
Map<Long, List<String>> collect = <error descr="Incompatible types. Found: 'java.util.Map<java.lang.Integer,java.util.List<java.lang.String>>', required: 'java.util.Map<java.lang.Long,java.util.List<java.lang.String>>'">Stream.of("xyz", "asfdasdfdasf", "dasfafasdfdf")
.collect(Collectors.groupingBy(s -> s.length()));</error>
Map<Long, List<String>> collect = Stream.of("xyz", "asfdasdfdasf", "dasfafasdfdf")
.<error descr="Incompatible types. Found: 'java.util.Map<java.lang.Integer,java.util.List<java.lang.String>>', required: 'java.util.Map<java.lang.Long,java.util.List<java.lang.String>>'">collect</error>(Collectors.groupingBy(s -> s.length()));
Map<String, Long> map = <error descr="Incompatible types. Found: 'java.util.Map<java.lang.String,java.lang.Integer>', required: 'java.util.Map<java.lang.String,java.lang.Long>'">Stream.of("a", "b", "c").collect(Collectors.toMap(s -> s, s -> s.length()));</error>
Map<String, Long> map = Stream.of("a", "b", "c").<error descr="Incompatible types. Found: 'java.util.Map<java.lang.String,java.lang.Integer>', required: 'java.util.Map<java.lang.String,java.lang.Long>'">collect</error>(Collectors.toMap(s -> s, s -> s.length()));
}
}
@@ -4,7 +4,7 @@ class FooClass {
{
Set[][] a = null;
a[0] = new Set[]{ <error descr="Incompatible types. Found: 'java.util.List', required: 'java.util.Set'">fooBar()</error>, <error descr="Incompatible types. Found: 'java.util.List', required: 'java.util.Set'">fooBar()</error>};
a[0] = new Set[]{ <error descr="Incompatible types. Found: 'java.util.List', required: 'java.util.Set'">fooBar</error>(), <error descr="Incompatible types. Found: 'java.util.List', required: 'java.util.Set'">fooBar</error>()};
}
private List fooBar() {
@@ -2,7 +2,7 @@ import java.util.Arrays;
class Test {
{
Arrays.asList<error descr="Formal varargs element type is inaccessible here">(new Outer.B(), new Outer.C())</error>;
Arrays.asList<error descr="Formal varargs element type Outer.A is inaccessible here">(new Outer.B(), new Outer.C())</error>;
}
}
@@ -19,6 +19,6 @@ class An {
class C {
{
An.foo<error descr="Formal varargs element type is inaccessible here">()</error>;
An.foo<error descr="Formal varargs element type An.B is inaccessible here">()</error>;
}
}
@@ -11,7 +11,7 @@ class Test {
}
switch (o) {
case Integer i when <error descr="Incompatible types. Found: 'int', required: 'boolean'">isInt()</error>:
case Integer i when <error descr="Incompatible types. Found: 'int', required: 'boolean'">isInt</error>():
break;
default:
break;