[java-highlighting] checkAmbiguousMethodCallIdentifier -> ExpressionChecker

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

GitOrigin-RevId: 0edb80ae452250e0d12ff987aa5701b048dc91cb
This commit is contained in:
Tagir Valeev
2025-01-30 17:21:02 +00:00
committed by intellij-monorepo-bot
parent c16bd2b684
commit 01bc97b6cc
10 changed files with 117 additions and 199 deletions
@@ -242,6 +242,7 @@ reference.qualifier.primitive=Cannot access fields on ''{0}'' type
reference.unresolved=Cannot resolve symbol ''{0}''
reference.ambiguous=Reference to ''{0}'' is ambiguous, both ''{1}'' and ''{2}'' match
reference.implicit.class=Implicitly declared class ''{0}'' cannot be referenced
reference.non.static.from.static.context=Non-static {0} ''{1}'' cannot be referenced from a static context
statement.case.outside.switch=Case statement outside switch
statement.invalid=Invalid statement
@@ -296,6 +297,9 @@ call.constructor.duplicate=Only one explicit constructor call allowed in constru
call.constructor.record.in.canonical=Canonical constructor cannot delegate to another constructor
call.constructor.recursive=Recursive constructor call
call.unresolved=Cannot resolve method ''{0}''
call.unresolved.name=Cannot resolve method ''{0}''
call.qualifier.primitive=Cannot call methods on ''{0}'' type
call.ambiguous.no.match=Cannot resolve method ''{0}'' in ''{1}''
call.ambiguous=Ambiguous method call: both ''{0}'' and ''{1}'' match
# {0} - colspan, {1} - method1, {2} - class1, {3} - method2, {4} - class2
call.ambiguous.tooltip=\
@@ -16,6 +16,7 @@ import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.search.searches.ImplicitClassSearch;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.util.JavaPsiConstructorUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.ThreeState;
@@ -26,6 +27,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import static com.intellij.util.ObjectUtils.tryCast;
import static java.util.Objects.*;
final class ExpressionChecker {
private final @NotNull JavaErrorVisitor myVisitor;
@@ -1150,6 +1152,67 @@ final class ExpressionChecker {
}
}
void checkAmbiguousMethodCallIdentifier(JavaResolveResult @NotNull [] resolveResults,
@NotNull JavaResolveResult resolveResult,
@NotNull PsiMethodCallExpression methodCall) {
PsiReferenceExpression referenceToMethod = methodCall.getMethodExpression();
PsiElement element = resolveResult.getElement();
MethodCandidateInfo methodCandidate2 = findCandidates(resolveResults).second;
if (methodCandidate2 != null) return;
PsiElement anchor = requireNonNullElse(referenceToMethod.getReferenceNameElement(), referenceToMethod);
if (element instanceof PsiModifierListOwner owner && !resolveResult.isAccessible()) {
myVisitor.myModifierChecker.reportAccessProblem(referenceToMethod, owner, resolveResult);
}
else if (element != null && !resolveResult.isStaticsScopeCorrect()) {
if (element instanceof PsiMethod psiMethod && psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
PsiClass containingClass = psiMethod.getContainingClass();
if (containingClass != null && containingClass.isInterface()) {
myVisitor.checkFeature(anchor, JavaFeature.STATIC_INTERFACE_CALLS);
if (myVisitor.hasErrorResults()) return;
checkStaticInterfaceCallQualifier(referenceToMethod, resolveResult, containingClass);
if (myVisitor.hasErrorResults()) return;
}
}
myVisitor.report(JavaErrorKinds.REFERENCE_NON_STATIC_FROM_STATIC_CONTEXT.create(referenceToMethod, element));
}
else if (!ContainerUtil.exists(resolveResults, result -> result instanceof MethodCandidateInfo && result.isAccessible())) {
PsiClass qualifierClass = RefactoringChangeUtil.getQualifierClass(referenceToMethod);
String className = qualifierClass != null ? qualifierClass.getName() : null;
PsiExpression qualifierExpression = referenceToMethod.getQualifierExpression();
if (className != null) {
if (IncompleteModelUtil.isIncompleteModel(myVisitor.file()) &&
IncompleteModelUtil.canBePendingReference(referenceToMethod)) {
myVisitor.report(JavaErrorKinds.REFERENCE_PENDING.create(anchor));
return;
}
myVisitor.report(JavaErrorKinds.CALL_AMBIGUOUS_NO_MATCH.create(methodCall, resolveResults));
}
else if (qualifierExpression != null &&
qualifierExpression.getType() instanceof PsiPrimitiveType primitiveType &&
!primitiveType.equals(PsiTypes.nullType())) {
if (PsiTypes.voidType().equals(primitiveType) &&
PsiUtil.deparenthesizeExpression(qualifierExpression) instanceof PsiReferenceExpression) {
return;
}
myVisitor.report(JavaErrorKinds.CALL_QUALIFIER_PRIMITIVE.create(methodCall, primitiveType));
}
else {
if (qualifierExpression != null) {
PsiType type = qualifierExpression.getType();
if (type instanceof PsiClassType t && t.resolve() == null || PsiTypes.nullType().equals(type)) return;
}
if (IncompleteModelUtil.isIncompleteModel(myVisitor.file()) && IncompleteModelUtil.canBePendingReference(referenceToMethod)) {
myVisitor.report(JavaErrorKinds.REFERENCE_PENDING.create(anchor));
return;
}
myVisitor.report(JavaErrorKinds.CALL_UNRESOLVED_NAME.create(methodCall, resolveResults));
}
}
}
void checkRestrictedIdentifierReference(@NotNull PsiJavaCodeReferenceElement ref, @NotNull PsiClass resolved) {
String name = resolved.getName();
if (PsiTypesUtil.isRestrictedIdentifier(name, myVisitor.languageLevel())) {
@@ -619,6 +619,7 @@ final class JavaErrorVisitor extends JavaElementVisitor {
(!result.isAccessible() || !result.isStaticsScopeCorrect())) {
PsiExpressionList list = methodCallExpression.getArgumentList();
if (!myExpressionChecker.isDummyConstructorCall(methodCallExpression, list, expression)) {
myExpressionChecker.checkAmbiguousMethodCallIdentifier(results, result, methodCallExpression);
if (!PsiTreeUtil.findChildrenOfType(methodCallExpression.getArgumentList(), PsiLambdaExpression.class).isEmpty()) {
PsiElement nameElement = expression.getReferenceNameElement();
if (nameElement != null) {
@@ -2,6 +2,7 @@
package com.intellij.java.codeserver.highlighting.errors;
import com.intellij.codeInsight.AnnotationTargetUtil;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightMessageUtil;
import com.intellij.core.JavaPsiBundle;
import com.intellij.java.codeserver.highlighting.JavaCompilationErrorBundle;
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKind.Parameterized;
@@ -13,6 +14,7 @@ import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.*;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.util.VisibilityUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -811,6 +813,15 @@ public final class JavaErrorKinds {
.withRawDescription((ref, results) -> message("reference.ambiguous", ref.getReferenceName(),
format(requireNonNull(results.get(0).getElement())),
format(requireNonNull(results.get(1).getElement()))));
public static final Parameterized<PsiJavaCodeReferenceElement, PsiElement> REFERENCE_NON_STATIC_FROM_STATIC_CONTEXT =
parameterized(PsiJavaCodeReferenceElement.class, PsiElement.class, "reference.non.static.from.static.context")
.withHighlightType((ref, refElement) -> JavaErrorHighlightType.WRONG_REF)
.withAnchor((ref, refElement) -> requireNonNullElse(ref.getReferenceNameElement(), ref))
.withRawDescription((ref, refElement) -> {
String type = JavaElementKind.fromElement(refElement).lessDescriptive().subject();
String name = HighlightMessageUtil.getSymbolName(refElement, PsiSubstitutor.EMPTY);
return message("reference.non.static.from.static.context", type, name);
});
public static final Simple<PsiSwitchLabelStatementBase> STATEMENT_CASE_OUTSIDE_SWITCH = error("statement.case.outside.switch");
public static final Simple<PsiStatement> STATEMENT_INVALID = error("statement.invalid");
@@ -886,12 +897,27 @@ public final class JavaErrorKinds {
.withAnchor((call, results) -> call.getArgumentList())
.withRawDescription((call, results) -> message(
"call.unresolved", call.getMethodExpression().getReferenceName() + formatArgumentTypes(call.getArgumentList(), true)));
public static final Parameterized<PsiMethodCallExpression, JavaResolveResult[]> CALL_UNRESOLVED_NAME =
parameterized(PsiMethodCallExpression.class, JavaResolveResult[].class, "call.unresolved.name")
.withRange((call, cls) -> getRange(call))
.withRawDescription((call, results) -> message(
"call.unresolved.name", call.getMethodExpression().getReferenceName() + formatArgumentTypes(call.getArgumentList(), true)));
public static final Parameterized<PsiMethodCallExpression, JavaAmbiguousCallContext> CALL_AMBIGUOUS =
parameterized(PsiMethodCallExpression.class, JavaAmbiguousCallContext.class, "call.ambiguous")
.withAnchor((call, ctx) -> call.getArgumentList())
.withRawDescription((call, ctx) -> ctx.description())
.withTooltip((call, ctx) -> ctx.tooltip());
public static final Parameterized<PsiMethodCallExpression, JavaResolveResult[]> CALL_AMBIGUOUS_NO_MATCH =
parameterized(PsiMethodCallExpression.class, JavaResolveResult[].class, "call.ambiguous.no.match")
.withRange((call, cls) -> getRange(call))
.withRawDescription(
(call, cls) -> message("call.ambiguous.no.match", call.getMethodExpression().getReferenceName(),
requireNonNull(RefactoringChangeUtil.getQualifierClass(call.getMethodExpression())).getName()));
public static final Parameterized<PsiMethodCallExpression, PsiPrimitiveType> CALL_QUALIFIER_PRIMITIVE =
parameterized(PsiMethodCallExpression.class, PsiPrimitiveType.class, "call.qualifier.primitive")
.withHighlightType((ref, type) -> JavaErrorHighlightType.WRONG_REF)
.withRange((call, type) -> getRange(call))
.withRawDescription((call, type) -> message("call.qualifier.primitive", type.getPresentableText()));
public static final Parameterized<PsiMethodCallExpression, PsiMethod> CALL_DIRECT_ABSTRACT_METHOD_ACCESS =
parameterized(PsiMethodCallExpression.class, PsiMethod.class, "call.direct.abstract.method.access")
@@ -510,6 +510,7 @@ public final class HighlightFixUtil {
registerUsageFixes(methodCall, info);
RemoveRedundantArgumentsFix.registerIntentions(methodCandidates, list, info);
info.accept(RemoveRepeatingCallFix.createFix(methodCall));
registerChangeParameterClassFix(methodCall, list, info);
}
@@ -797,6 +798,7 @@ public final class HighlightFixUtil {
WrapExpressionFix.registerWrapAction(candidates, list.getExpressions(), sink);
PermuteArgumentsFix.registerFix(sink, methodCall, candidates);
registerChangeParameterClassFix(methodCall, list, sink);
registerMethodCallIntentions(sink, methodCall, list);
}
private static final class ReturnModel {
@@ -5,27 +5,19 @@ import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.daemon.JavaErrorBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.quickfix.*;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInsight.quickfix.LazyQuickFixUpdater;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.codeInspection.LocalQuickFixOnPsiElementAsIntentionAdapter;
import com.intellij.core.JavaPsiBundle;
import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.pom.java.JavaFeature;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.IncompleteModelUtil;
import com.intellij.psi.impl.light.LightRecordMethod;
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.refactoring.util.RefactoringChangeUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -281,139 +273,6 @@ public final class HighlightMethodUtil {
return JavaErrorBundle.message("static.interface.method.call.qualifier");
}
static boolean isDummyConstructorCall(@NotNull PsiMethodCallExpression methodCall,
@NotNull PsiResolveHelper resolveHelper,
@NotNull PsiExpressionList list,
@NotNull PsiReferenceExpression referenceToMethod) {
boolean isDummy = false;
boolean isThisOrSuper = referenceToMethod.getReferenceNameElement() instanceof PsiKeyword;
if (isThisOrSuper) {
// super(..) or this(..)
if (list.isEmpty()) { // implicit ctr call
CandidateInfo[] candidates = resolveHelper.getReferencedMethodCandidates(methodCall, true);
if (candidates.length == 1 && !candidates[0].getElement().isPhysical()) {
isDummy = true;// dummy constructor
}
}
}
return isDummy;
}
static HighlightInfo.Builder checkAmbiguousMethodCallIdentifier(@NotNull PsiReferenceExpression referenceToMethod,
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 = HighlightFixUtil.toMethodCandidates(resolveResults);
HighlightInfoType highlightInfoType = HighlightInfoType.ERROR;
String description;
PsiElement elementToHighlight = ObjectUtils.notNull(referenceToMethod.getReferenceNameElement(), referenceToMethod);
if (element != null && !resolveResult.isAccessible()) {
description = HighlightUtil.accessProblemDescription(referenceToMethod, element, resolveResult);
}
else if (element != null && !resolveResult.isStaticsScopeCorrect()) {
if (element instanceof PsiMethod psiMethod && psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
PsiClass containingClass = psiMethod.getContainingClass();
if (containingClass != null && containingClass.isInterface()) {
HighlightInfo.Builder info = HighlightUtil.checkFeature(elementToHighlight, JavaFeature.STATIC_INTERFACE_CALLS, languageLevel, file);
if (info != null) return info;
info = checkStaticInterfaceCallQualifier(referenceToMethod, resolveResult, elementToHighlight, containingClass);
if (info != null) return info;
}
}
description = HighlightUtil.staticContextProblemDescription(element);
}
else if (candidates.length == 0) {
PsiClass qualifierClass = RefactoringChangeUtil.getQualifierClass(referenceToMethod);
String className = qualifierClass != null ? qualifierClass.getName() : null;
PsiExpression qualifierExpression = referenceToMethod.getQualifierExpression();
if (className != null) {
if (IncompleteModelUtil.isIncompleteModel(file) &&
IncompleteModelUtil.canBePendingReference(referenceToMethod)) {
return HighlightUtil.getPendingReferenceHighlightInfo(elementToHighlight);
}
description = JavaErrorBundle.message("ambiguous.method.call.no.match", referenceToMethod.getReferenceName(), className);
}
else if (qualifierExpression != null &&
qualifierExpression.getType() instanceof PsiPrimitiveType primitiveType &&
!primitiveType.equals(PsiTypes.nullType())) {
if (PsiTypes.voidType().equals(primitiveType) &&
PsiUtil.deparenthesizeExpression(qualifierExpression) instanceof PsiReferenceExpression) {
return null;
}
description = JavaErrorBundle.message("cannot.call.method.on.type", primitiveType.getPresentableText(false));
}
else {
if (qualifierExpression != null) {
PsiType type = qualifierExpression.getType();
if (type instanceof PsiClassType t && t.resolve() == null || PsiTypes.nullType().equals(type)) {
return null;
}
}
if (IncompleteModelUtil.isIncompleteModel(file) && IncompleteModelUtil.canBePendingReference(referenceToMethod)) {
return HighlightUtil.getPendingReferenceHighlightInfo(elementToHighlight);
}
description =
JavaErrorBundle.message("cannot.resolve.method", referenceToMethod.getReferenceName() + buildArgTypesList(list, true));
}
highlightInfoType = HighlightInfoType.WRONG_REF;
}
else {
return null;
}
String toolTip = XmlStringUtil.escapeString(description);
HighlightInfo.Builder builder =
HighlightInfo.newHighlightInfo(highlightInfoType).range(elementToHighlight).description(description).escapedToolTip(toolTip);
if (element != null && !resolveResult.isStaticsScopeCorrect()) {
HighlightFixUtil.registerStaticProblemQuickFixAction(asConsumer(builder), element, referenceToMethod);
}
HighlightFixUtil.registerMethodCallIntentions(asConsumer(builder), methodCall, list);
TextRange fixRange = getFixRange(elementToHighlight);
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);
}
HighlightFixUtil.registerChangeParameterClassFix(methodCall, list, asConsumer(builder));
if (candidates.length == 0) {
PsiReference ref = methodCall.getMethodExpression();
UnresolvedReferenceQuickFixProvider.registerUnresolvedReferenceLazyQuickFixes(ref, builder);
}
return builder;
}
private static @NotNull Pair<MethodCandidateInfo, MethodCandidateInfo> findCandidates(JavaResolveResult @NotNull [] resolveResults) {
MethodCandidateInfo methodCandidate1 = null;
MethodCandidateInfo methodCandidate2 = null;
for (JavaResolveResult result : resolveResults) {
if (!(result instanceof MethodCandidateInfo candidate)) continue;
if (candidate.isApplicable() && !candidate.getElement().isConstructor()) {
if (methodCandidate1 == null) {
methodCandidate1 = candidate;
}
else {
methodCandidate2 = candidate;
break;
}
}
}
return Pair.pair(methodCandidate1, methodCandidate2);
}
static HighlightInfo.Builder checkAbstractMethodInConcreteClass(@NotNull PsiMethod method, @NotNull PsiElement elementToHighlight) {
HighlightInfo.Builder errorResult = null;
PsiClass aClass = method.getContainingClass();
@@ -473,19 +332,6 @@ public final class HighlightMethodUtil {
return range;
}
private static @NotNull String buildArgTypesList(@NotNull PsiExpressionList list, boolean shortNames) {
StringBuilder builder = new StringBuilder();
builder.append("(");
PsiExpression[] args = list.getExpressions();
for (int i = 0; i < args.length; i++) {
if (i > 0) builder.append(", ");
PsiType argType = args[i].getType();
builder.append(argType != null ? (shortNames ? argType.getPresentableText() : JavaHighlightUtil.formatType(argType)) : "?");
}
builder.append(")");
return builder.toString();
}
static boolean hasSurroundingInferenceError(@NotNull PsiElement context) {
PsiCall topCall = LambdaUtil.treeWalkUp(context);
if (topCall == null) return false;
@@ -16,7 +16,6 @@ import com.intellij.core.JavaPsiBundle;
import com.intellij.java.codeserver.highlighting.JavaErrorCollector;
import com.intellij.java.codeserver.highlighting.errors.JavaCompilationError;
import com.intellij.java.codeserver.highlighting.errors.JavaErrorHighlightType;
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.lang.jvm.JvmModifier;
@@ -62,6 +61,7 @@ import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import static com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds.*;
import static com.intellij.psi.PsiModifier.SEALED;
import static com.intellij.util.ObjectUtils.tryCast;
import static java.util.Objects.*;
@@ -99,11 +99,6 @@ 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());
}
protected HighlightVisitorImpl() {
}
@@ -138,7 +133,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
/**
* @deprecated use {@link #HighlightVisitorImpl()} and {@link #getResolveHelper()}
* @deprecated use {@link #HighlightVisitorImpl()}
*/
@Deprecated(forRemoval = true)
protected HighlightVisitorImpl(@NotNull PsiResolveHelper psiResolveHelper) {
@@ -251,8 +246,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
info.range(anchor);
}
errorFixProvider.processFixes(error, fix -> info.registerFix(fix.asIntention(), null, null, null, null));
error.psiForKind(JavaErrorKinds.EXPRESSION_EXPECTED, JavaErrorKinds.REFERENCE_UNRESOLVED, JavaErrorKinds.REFERENCE_AMBIGUOUS)
.or(() -> error.psiForKind(JavaErrorKinds.TYPE_UNKNOWN_CLASS).map(PsiTypeElement::getInnermostComponentReferenceElement))
error.psiForKind(EXPRESSION_EXPECTED, REFERENCE_UNRESOLVED, REFERENCE_AMBIGUOUS)
.or(() -> error.psiForKind(TYPE_UNKNOWN_CLASS).map(PsiTypeElement::getInnermostComponentReferenceElement))
.or(() -> error.psiForKind(CALL_AMBIGUOUS_NO_MATCH, CALL_UNRESOLVED).map(PsiMethodCallExpression::getMethodExpression))
.ifPresent(ref -> UnresolvedReferenceQuickFixProvider.registerUnresolvedReferenceLazyQuickFixes(ref, info));
add(info);
}
@@ -752,7 +748,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
JavaResolveResult resultForIncompleteCode = doVisitReferenceElement(expression);
doVisitReferenceElement(expression);
if (!hasErrorResults()) {
visitExpression(expression);
@@ -780,22 +776,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
PsiElement parent = expression.getParent();
if (parent instanceof PsiMethodCallExpression methodCallExpression &&
methodCallExpression.getMethodExpression() == expression &&
(!result.isAccessible() || !result.isStaticsScopeCorrect())) {
PsiExpressionList list = methodCallExpression.getArgumentList();
PsiResolveHelper resolveHelper = getResolveHelper();
if (!HighlightMethodUtil.isDummyConstructorCall(methodCallExpression, resolveHelper, list, expression)) {
try {
add(HighlightMethodUtil.checkAmbiguousMethodCallIdentifier(
expression, results, list, resolved, result, methodCallExpression, myLanguageLevel, myFile));
}
catch (IndexNotReadyException ignored) {
}
}
}
if (!hasErrorResults()) add(GenericsHighlightUtil.checkAccessStaticFieldFromEnumConstructor(expression, result));
if (!hasErrorResults()) add(HighlightUtil.checkClassReferenceAfterQualifier(expression, resolved));
PsiExpression qualifierExpression = expression.getQualifierExpression();
@@ -1177,17 +1157,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
@Override
public void visitDefaultCaseLabelElement(@NotNull PsiDefaultCaseLabelElement element) {
super.visitDefaultCaseLabelElement(element);
// "case default:" will be highlighted as "The label for the default case must only use the 'default' keyword, without 'case'".
// see SwitchBlockHighlightingModel#checkSwitchLabelValues
// The "case default:" syntax was only allowed in outdated preview versions of Java (from Java 17 Preview to Java 19 Preview).
// And even if the "case default" syntax was allowed not only in outdated preview versions of Java, using "case default:"
// instead of "default:" looks weird. Therefore, for this case, we do not check the feature availability and do not
// suggest increasing the language level.
}
@Override
public void visitPatternVariable(@NotNull PsiPatternVariable variable) {
super.visitPatternVariable(variable);
@@ -405,14 +405,21 @@ final class JavaErrorFixProvider {
}
}
});
fixes(CALL_AMBIGUOUS, (error, sink) -> {
PsiMethodCallExpression methodCall = error.psi();
JavaResolveResult[] resolveResults = error.context().results();
HighlightFixUtil.registerAmbiguousCallFixes(sink, methodCall, resolveResults);
fixes(CALL_UNRESOLVED_NAME,
(error, sink) -> HighlightFixUtil.registerMethodCallIntentions(sink, error.psi(), error.psi().getArgumentList()));
fix(CALL_QUALIFIER_PRIMITIVE, error -> myFactory.createRenameWrongRefFix(error.psi().getMethodExpression()));
fixes(CALL_QUALIFIER_PRIMITIVE,
(error, sink) -> HighlightFixUtil.registerMethodCallIntentions(sink, error.psi(), error.psi().getArgumentList()));
fixes(CALL_AMBIGUOUS, (error, sink) -> HighlightFixUtil.registerAmbiguousCallFixes(sink, error.psi(), error.context().results()));
fixes(CALL_AMBIGUOUS_NO_MATCH, (error, sink) -> HighlightFixUtil.registerAmbiguousCallFixes(sink, error.psi(), error.context()));
fixes(REFERENCE_NON_STATIC_FROM_STATIC_CONTEXT, (error, sink) -> {
HighlightFixUtil.registerStaticProblemQuickFixAction(sink, error.context(), error.psi());
if (error.psi().getParent() instanceof PsiMethodCallExpression methodCall) {
HighlightFixUtil.registerMethodCallIntentions(sink, methodCall, methodCall.getArgumentList());
}
});
fixes(CALL_UNRESOLVED, (error, sink) -> {
PsiMethodCallExpression methodCall = error.psi();
HighlightFixUtil.registerMethodCallIntentions(sink, methodCall, methodCall.getArgumentList());
JavaResolveResult[] resolveResults = error.context();
if (resolveResults.length == 1) {
PsiElement element = resolveResults[0].getElement();
@@ -23,7 +23,7 @@ class C {
interface II extends I {
default void m() {
I.super.m();
<error descr="Unqualified super reference is not allowed in extension method">super.m</error>();
<error descr="Unqualified super reference is not allowed in extension method">super.<error descr="Cannot resolve method 'm' in 'Object'">m</error></error>();
System.out.println(<error descr="'C.I' is not an enclosing class">I.super</error>.i);
System.out.println(<error descr="Unqualified super reference is not allowed in extension method">super.<error descr="Cannot resolve symbol 'i'">i</error></error>);
@@ -4,7 +4,7 @@ import static p.<error descr="Cannot access p.BaseClass">ChildClass</error>.*;
class Sample {
public static void main(String[] args) {
<error descr="Cannot access p.BaseClass">ChildClass.foo</error>();
ChildClass.<error descr="Cannot resolve method 'foo' in 'ChildClass'">foo</error>();
foo();
ChildClass cc = ChildClass2.childClass();
}