[java-highlighting] Inner class and type parameter reference errors migrated

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

GitOrigin-RevId: 48755f4faf20e9fab83eed660ad49d47fd2420b6
This commit is contained in:
Tagir Valeev
2025-01-31 15:31:12 +00:00
committed by intellij-monorepo-bot
parent 3de978db6f
commit 75f1ac4fed
5 changed files with 55 additions and 43 deletions
@@ -251,6 +251,7 @@ 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
reference.outer.type.parameter.from.static.context=''{0}'' cannot be referenced from a static context
statement.case.outside.switch=Case statement outside switch
statement.invalid=Invalid statement
@@ -505,6 +505,24 @@ final class GenericsChecker {
}
}
void checkTypeParameterReference(@NotNull PsiJavaCodeReferenceElement ref, @NotNull PsiTypeParameter typeParameter) {
PsiTypeParameterListOwner owner = typeParameter.getOwner();
if (owner instanceof PsiClass outerClass) {
if (!InheritanceUtil.hasEnclosingInstanceInScope(outerClass, ref, false, false)) {
myVisitor.myExpressionChecker.checkIllegalEnclosingUsage(ref, null, outerClass, ref);
}
}
else if (owner instanceof PsiMethod) {
PsiModifierListOwner staticElement = PsiUtil.getEnclosingStaticElement(ref, null);
if (staticElement != null && PsiTreeUtil.isAncestor(owner, staticElement, true)) {
PsiClass ownerContainingClass = owner.getContainingClass();
if (ownerContainingClass != null) {
myVisitor.report(JavaErrorKinds.REFERENCE_OUTER_TYPE_PARAMETER_FROM_STATIC_CONTEXT.create(ref, typeParameter));
}
}
}
}
private void checkUnsafeCastInInstanceOf(@NotNull PsiTypeElement checkTypeElement, @NotNull PsiType checkType, @Nullable PsiType expressionType) {
if (expressionType != null && JavaGenericsUtil.isUncheckedCast(checkType, expressionType)) {
myVisitor.report(JavaErrorKinds.INSTANCEOF_UNSAFE_CAST.create(
@@ -760,6 +760,34 @@ final class JavaErrorVisitor extends JavaElementVisitor {
if (!hasErrorResults() && (!(parent instanceof PsiNewExpression newExpression) || !newExpression.isArrayCreation())) {
myGenericsChecker.checkParameterizedReferenceTypeArguments(resolved, ref, result.getSubstitutor());
}
if (!hasErrorResults() && resolved instanceof PsiClass psiClass) {
PsiClass aClass = psiClass.getContainingClass();
if (aClass != null) {
PsiElement qualifier = ref.getQualifier();
PsiElement place;
if (qualifier instanceof PsiJavaCodeReferenceElement element) {
place = element.resolve();
}
else {
if (parent instanceof PsiNewExpression newExpression) {
PsiExpression newQualifier = newExpression.getQualifier();
place = newQualifier == null ? ref : PsiUtil.resolveClassInType(newQualifier.getType());
}
else {
place = ref;
}
}
if (place != null &&
PsiTreeUtil.isAncestor(aClass, place, false) &&
aClass.hasTypeParameters() &&
!PsiUtil.isInsideJavadocComment(place)) {
myExpressionChecker.checkCreateInnerClassFromStaticContext(ref, place, psiClass);
}
}
else if (resolved instanceof PsiTypeParameter typeParameter) {
myGenericsChecker.checkTypeParameterReference(ref, typeParameter);
}
}
if (parent instanceof PsiAnonymousClass psiAnonymousClass && ref.equals(psiAnonymousClass.getBaseClassReference())) {
if (!hasErrorResults()) myGenericsChecker.checkGenericCannotExtendException(psiAnonymousClass);
}
@@ -906,6 +906,10 @@ public final class JavaErrorKinds {
String name = HighlightMessageUtil.getSymbolName(refElement, PsiSubstitutor.EMPTY);
return message("reference.non.static.from.static.context", type, name);
});
public static final Parameterized<PsiJavaCodeReferenceElement, PsiTypeParameter> REFERENCE_OUTER_TYPE_PARAMETER_FROM_STATIC_CONTEXT =
parameterized(PsiJavaCodeReferenceElement.class, PsiTypeParameter.class, "reference.outer.type.parameter.from.static.context")
.withHighlightType((ref, refElement) -> JavaErrorHighlightType.WRONG_REF)
.withRawDescription((ref, refElement) -> message("reference.outer.type.parameter.from.static.context", refElement.getName()));
public static final Simple<PsiSwitchLabelStatementBase> STATEMENT_CASE_OUTSIDE_SWITCH = error("statement.case.outside.switch");
public static final Simple<PsiStatement> STATEMENT_INVALID = error("statement.invalid");
@@ -43,14 +43,16 @@ import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.NewUI;
import com.intellij.util.ObjectUtils;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.NamedColorUtil;
import com.intellij.util.ui.UIUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -628,47 +630,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
add(info);
}
if (!hasErrorResults() && resolved instanceof PsiClass psiClass) {
PsiClass aClass = psiClass.getContainingClass();
if (aClass != null) {
PsiElement qualifier = ref.getQualifier();
PsiElement place;
if (qualifier instanceof PsiJavaCodeReferenceElement element) {
place = element.resolve();
}
else {
if (parent instanceof PsiNewExpression newExpression) {
PsiExpression newQualifier = newExpression.getQualifier();
place = newQualifier == null ? ref : PsiUtil.resolveClassInType(newQualifier.getType());
}
else {
place = ref;
}
}
if (place != null &&
PsiTreeUtil.isAncestor(aClass, place, false) &&
aClass.hasTypeParameters() &&
!PsiUtil.isInsideJavadocComment(place)) {
add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(ref, place, psiClass));
}
}
else if (resolved instanceof PsiTypeParameter typeParameter) {
PsiTypeParameterListOwner owner = typeParameter.getOwner();
if (owner instanceof PsiClass outerClass) {
if (!InheritanceUtil.hasEnclosingInstanceInScope(outerClass, ref, false, false)) {
add(HighlightClassUtil.checkIllegalEnclosingUsage(ref, null, outerClass, ref));
}
}
else if (owner instanceof PsiMethod) {
PsiClass cls = ClassUtils.getContainingStaticClass(ref);
if (cls != null && PsiTreeUtil.isAncestor(owner, cls, true)) {
String description = JavaErrorBundle.message("cannot.be.referenced.from.static.context", ref.getReferenceName());
add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(ref).descriptionAndTooltip(description));
}
}
}
}
if (!hasErrorResults()) {
add(HighlightUtil.checkPackageAndClassConflict(ref, myFile));
}