[java-highlighting] checkCreateInnerClassFromStaticContext -> JavaInheritorsGetter.isInnerClassFromStaticContext

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

GitOrigin-RevId: 449d1d80f89480b3d13f8f0d299d2c309da0f0c6
This commit is contained in:
Tagir Valeev
2025-02-06 10:35:32 +00:00
committed by intellij-monorepo-bot
parent 631e06c624
commit 31f950b501
2 changed files with 16 additions and 76 deletions
@@ -11,7 +11,10 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
import com.intellij.psi.util.*;
import com.intellij.psi.util.JavaElementKind;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,75 +35,6 @@ public final class HighlightClassUtil {
return PsiTypesUtil.isRestrictedIdentifier(typeName, level);
}
private static void registerMakeInnerClassStatic(@Nullable PsiClass aClass, @Nullable HighlightInfo.Builder result) {
if (result == null || aClass == null) return;
if (aClass.getContainingClass() != null) {
PsiModifierList modifierList = aClass.getModifierList();
if (modifierList != null && JavaPsiModifierUtil.getIncompatibleModifier(PsiModifier.STATIC, modifierList) == null) {
IntentionAction action = QuickFixFactory.getInstance().createModifierListFix(aClass, PsiModifier.STATIC, true, false);
result.registerFix(action, null, null, null, null);
}
}
}
public static HighlightInfo.Builder checkCreateInnerClassFromStaticContext(@NotNull PsiElement element,
@Nullable PsiExpression qualifier,
@NotNull PsiClass aClass) {
PsiElement placeToSearchEnclosingFrom;
if (qualifier != null) {
PsiType qType = qualifier.getType();
placeToSearchEnclosingFrom = PsiUtil.resolveClassInType(qType);
}
else {
placeToSearchEnclosingFrom = element;
}
if (placeToSearchEnclosingFrom == null) {
return null;
}
return checkCreateInnerClassFromStaticContext(element, placeToSearchEnclosingFrom, aClass);
}
static HighlightInfo.Builder checkCreateInnerClassFromStaticContext(@NotNull PsiElement element,
@NotNull PsiElement placeToSearchEnclosingFrom,
@NotNull PsiClass aClass) {
if (!PsiUtil.isInnerClass(aClass)) return null;
PsiClass outerClass = aClass.getContainingClass();
if (outerClass == null) return null;
if (outerClass instanceof PsiSyntheticClass ||
InheritanceUtil.hasEnclosingInstanceInScope(outerClass, placeToSearchEnclosingFrom, true, false)) {
return null;
}
return checkIllegalEnclosingUsage(placeToSearchEnclosingFrom, aClass, outerClass, element);
}
static HighlightInfo.Builder checkIllegalEnclosingUsage(@NotNull PsiElement place,
@Nullable PsiClass aClass,
@NotNull PsiClass outerClass,
@NotNull PsiElement elementToHighlight) {
if (!PsiTreeUtil.isContextAncestor(outerClass, place, false)) {
String description = JavaErrorBundle.message("is.not.an.enclosing.class", HighlightUtil.formatClass(outerClass));
HighlightInfo.Builder highlightInfo =
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(elementToHighlight).descriptionAndTooltip(description);
registerMakeInnerClassStatic(aClass, highlightInfo);
return highlightInfo;
}
PsiModifierListOwner staticParent = PsiUtil.getEnclosingStaticElement(place, outerClass);
if (staticParent != null) {
String element = HighlightUtil.formatClass(outerClass) + "." +
(place instanceof PsiSuperExpression ? PsiKeyword.SUPER : PsiKeyword.THIS);
String description = JavaErrorBundle.message("cannot.be.referenced.from.static.context", element);
HighlightInfo.Builder builder =
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(elementToHighlight).descriptionAndTooltip(description);
// make context not static or referenced class static
IntentionAction action1 = QuickFixFactory.getInstance().createModifierListFix(staticParent, PsiModifier.STATIC, false, false);
builder.registerFix(action1, null, null, null, null);
registerMakeInnerClassStatic(aClass, builder);
return builder;
}
return null;
}
public static HighlightInfo.Builder checkExtendsSealedClass(@NotNull PsiClass aClass,
@NotNull PsiClass superClass,
@NotNull PsiJavaCodeReferenceElement elementToHighlight) {
@@ -3,7 +3,6 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightClassUtil;
import com.intellij.codeInsight.lookup.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.pom.java.JavaFeature;
@@ -15,10 +14,7 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.statistics.JavaStatisticsManager;
import com.intellij.psi.statistics.StatisticsInfo;
import com.intellij.psi.statistics.StatisticsManager;
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.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
@@ -110,7 +106,7 @@ public class JavaInheritorsGetter {
PsiElement position = parameters.getPosition();
if ((parameters.getInvocationCount() < 2 || psiClass instanceof PsiCompiledElement) &&
HighlightClassUtil.checkCreateInnerClassFromStaticContext(position, null, psiClass) != null &&
isInnerClassFromStaticContext(position, psiClass) &&
!psiElement().afterLeaf(psiElement().withText(PsiKeyword.NEW).afterLeaf(".")).accepts(position)) {
return null;
}
@@ -251,4 +247,14 @@ public class JavaInheritorsGetter {
}
return true;
}
private static boolean isInnerClassFromStaticContext(@NotNull PsiElement element, @NotNull PsiClass aClass) {
if (aClass.hasModifierProperty(PsiModifier.STATIC)) return false;
PsiClass outerClass = aClass.getContainingClass();
if (outerClass == null) return false;
return !InheritanceUtil.hasEnclosingInstanceInScope(outerClass, element, true, false) &&
(!PsiTreeUtil.isContextAncestor(outerClass, element, false) ||
PsiUtil.getEnclosingStaticElement(element, outerClass) != null);
}
}