mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
[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:
committed by
intellij-monorepo-bot
parent
c28f1d89cc
commit
072f53c464
@@ -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
|
||||
|
||||
+110
-1
@@ -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)) {
|
||||
|
||||
+12
@@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+6
@@ -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);
|
||||
|
||||
+19
-2
@@ -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) {}
|
||||
}
|
||||
|
||||
+10
-3
@@ -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) ->
|
||||
|
||||
-17
@@ -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;
|
||||
|
||||
|
||||
+265
-23
@@ -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);
|
||||
}
|
||||
}
|
||||
+53
-334
@@ -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);
|
||||
|
||||
+3
-3
@@ -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);
|
||||
|
||||
+8
-9
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+24
-3
@@ -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() {
|
||||
|
||||
+7
-8
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-11
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-10
@@ -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
-11
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-12
@@ -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> {
|
||||
|
||||
+4
-6
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -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
-4
@@ -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
-1
@@ -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>[]{}};
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -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>();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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>() ) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-4
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
-2
@@ -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>;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user