[java-highlighting] checkInterfaceMultipleInheritance, checkClassSupersAccessibility -> GenericsChecker

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

GitOrigin-RevId: d8c69e0cc3ce9f2e4525ce432013e3e0d729a36e
This commit is contained in:
Tagir Valeev
2025-01-17 19:30:16 +00:00
committed by intellij-monorepo-bot
parent e4d0585b15
commit 60ceb06e60
8 changed files with 189 additions and 121 deletions
@@ -86,6 +86,9 @@ class.anonymous.extends.sealed=Anonymous classes must not extend sealed classes
class.already.imported=''{0}'' is already defined in this compilation unit
class.not.enclosing=''{0}'' is not an enclosing class
class.cannot.be.referenced.from.static.context=''{0}'' cannot be referenced from a static context
class.inheritance.different.type.arguments=''{0}'' cannot be inherited with different type arguments: ''{1}'' and ''{2}''
class.inheritance.raw.and.generic=''{0}'' cannot be inherited as a raw type and with generic type arguments ''{1}''
class.not.accessible=Cannot access {0}
class.implicit.no.main.method=Implicitly declared class contains no 'main' method
class.implicit.invalid.file.name=Implicitly declared class's file name is not a valid identifier
@@ -4,14 +4,18 @@ package com.intellij.java.codeserver.highlighting;
import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
import com.intellij.java.codeserver.highlighting.errors.JavaErrorKinds;
import com.intellij.java.codeserver.highlighting.errors.JavaIncompatibleTypeErrorContext;
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.IncompleteModelUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import java.util.*;
final class GenericsChecker {
private final @NotNull JavaErrorVisitor myVisitor;
@@ -119,4 +123,119 @@ final class GenericsChecker {
myVisitor.report(JavaErrorKinds.REFERENCE_TYPE_NEEDS_TYPE_ARGUMENTS.create(parent));
}
}
void checkInterfaceMultipleInheritance(@NotNull PsiClass aClass) {
PsiClassType[] types = aClass.getSuperTypes();
if (types.length < 2) return;
checkInterfaceMultipleInheritance(aClass,
aClass,
PsiSubstitutor.EMPTY, new HashMap<>(),
new HashSet<>());
}
private void checkInterfaceMultipleInheritance(@NotNull PsiClass aClass,
@NotNull PsiClass place,
@NotNull PsiSubstitutor derivedSubstitutor,
@NotNull Map<PsiClass, PsiSubstitutor> inheritedClasses,
@NotNull Set<? super PsiClass> visited) {
List<PsiClassType.ClassResolveResult> superTypes = PsiClassImplUtil.getScopeCorrectedSuperTypes(aClass, place.getResolveScope());
for (PsiClassType.ClassResolveResult result : superTypes) {
PsiClass superClass = result.getElement();
if (superClass == null || visited.contains(superClass)) continue;
PsiSubstitutor superTypeSubstitutor = result.getSubstitutor();
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(aClass.getProject());
//JLS 4.8 The superclasses (respectively, superinterfaces) of a raw type are the erasures
// of the superclasses (superinterfaces) of any of the parameterizations of the generic type.
superTypeSubstitutor = PsiUtil.isRawSubstitutor(aClass, derivedSubstitutor)
? elementFactory.createRawSubstitutor(superClass)
: MethodSignatureUtil.combineSubstitutors(superTypeSubstitutor, derivedSubstitutor);
PsiSubstitutor inheritedSubstitutor = inheritedClasses.get(superClass);
if (inheritedSubstitutor != null) {
PsiTypeParameter[] typeParameters = superClass.getTypeParameters();
for (PsiTypeParameter typeParameter : typeParameters) {
PsiType type1 = inheritedSubstitutor.substitute(typeParameter);
PsiType type2 = superTypeSubstitutor.substitute(typeParameter);
if (!Comparing.equal(type1, type2)) {
var context = new JavaErrorKinds.InheritTypeClashContext(superClass, type1, type2);
if (type1 != null && type2 != null) {
myVisitor.report(JavaErrorKinds.CLASS_INHERITANCE_DIFFERENT_TYPE_ARGUMENTS.create(place, context));
}
else {
myVisitor.report(JavaErrorKinds.CLASS_INHERITANCE_RAW_AND_GENERIC.create(place, context));
}
return;
}
}
}
inheritedClasses.put(superClass, superTypeSubstitutor);
visited.add(superClass);
checkInterfaceMultipleInheritance(superClass, place, superTypeSubstitutor, inheritedClasses, visited);
visited.remove(superClass);
if (myVisitor.hasErrorResults()) return;
}
}
void checkClassSupersAccessibility(@NotNull PsiClass aClass) {
checkClassSupersAccessibility(aClass, aClass, aClass.getResolveScope(), true);
}
void checkClassSupersAccessibility(@NotNull PsiClass aClass, @NotNull PsiElement ref, @NotNull GlobalSearchScope scope) {
checkClassSupersAccessibility(ref, aClass, scope, false);
}
private void checkClassSupersAccessibility(@NotNull PsiElement anchor,
@NotNull PsiClass aClass,
@NotNull GlobalSearchScope resolveScope,
boolean checkParameters) {
JavaPsiFacade factory = JavaPsiFacade.getInstance(aClass.getProject());
for (PsiClassType superType : aClass.getSuperTypes()) {
HashSet<PsiClass> checked = new HashSet<>();
checked.add(aClass);
checkTypeAccessible(anchor, superType, checked, checkParameters, true, resolveScope, factory);
}
}
private void checkTypeAccessible(@NotNull PsiElement anchor,
@Nullable PsiType type,
@NotNull Set<? super PsiClass> classes,
boolean checkParameters,
boolean checkSuperTypes,
@NotNull GlobalSearchScope resolveScope,
@NotNull JavaPsiFacade factory) {
type = PsiClassImplUtil.correctType(type, resolveScope);
PsiClass aClass = PsiUtil.resolveClassInType(type);
if (aClass != null && classes.add(aClass)) {
VirtualFile vFile = PsiUtilCore.getVirtualFile(aClass);
if (vFile == null) return;
FileIndexFacade index = FileIndexFacade.getInstance(aClass.getProject());
if (!index.isInSource(vFile) && !index.isInLibraryClasses(vFile)) return;
PsiImplicitClass parentImplicitClass = PsiTreeUtil.getParentOfType(aClass, PsiImplicitClass.class);
String qualifiedName = aClass.getQualifiedName();
if (parentImplicitClass == null && qualifiedName != null && factory.findClass(qualifiedName, resolveScope) == null) {
myVisitor.report(JavaErrorKinds.CLASS_NOT_ACCESSIBLE.create(anchor, aClass));
return;
}
if (!checkParameters) return;
if (type instanceof PsiClassType classType) {
for (PsiType parameterType : classType.getParameters()) {
checkTypeAccessible(anchor, parameterType, classes, true, false, resolveScope, factory);
if (myVisitor.hasErrorResults()) return;
}
}
if (!checkSuperTypes) return;
boolean isInLibrary = !index.isInContent(vFile);
for (PsiClassType superType : aClass.getSuperTypes()) {
checkTypeAccessible(anchor, superType, classes, !isInLibrary, true, resolveScope, factory);
if (myVisitor.hasErrorResults()) return;
}
}
}
}
@@ -4,6 +4,7 @@ package com.intellij.java.codeserver.highlighting;
import com.intellij.java.codeserver.highlighting.errors.JavaCompilationError;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaModule;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -22,8 +23,13 @@ public final class JavaErrorCollector {
* @param file Java file to process
* @param consumer a consumer to get errors
*/
public JavaErrorCollector(@NotNull PsiFile file, @NotNull Consumer<@NotNull JavaCompilationError<?, ?>> consumer) {
myVisitor = new JavaErrorVisitor(file, consumer);
public JavaErrorCollector(@NotNull PsiFile file, @NotNull Consumer<@NotNull JavaCompilationError<?, ?>> consumer) {
this(file, null, consumer);
}
public JavaErrorCollector(@NotNull PsiFile file, @Nullable PsiJavaModule module,
@NotNull Consumer<@NotNull JavaCompilationError<?, ?>> consumer) {
myVisitor = new JavaErrorVisitor(file, module, consumer);
}
/**
@@ -18,6 +18,7 @@ import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,13 +44,15 @@ final class JavaErrorVisitor extends JavaElementVisitor {
final @NotNull ExpressionChecker myExpressionChecker = new ExpressionChecker(this);
private final @NotNull StatementChecker myStatementChecker = new StatementChecker(this);
private final @NotNull LiteralChecker myLiteralChecker = new LiteralChecker(this);
private final @Nullable PsiJavaModule myJavaModule;
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.
JavaErrorVisitor(@NotNull PsiFile file, @NotNull Consumer<JavaCompilationError<?, ?>> consumer) {
JavaErrorVisitor(@NotNull PsiFile file, @Nullable PsiJavaModule module, @NotNull Consumer<JavaCompilationError<?, ?>> consumer) {
myFile = file;
myProject = file.getProject();
myLanguageLevel = PsiUtil.getLanguageLevel(file);
myErrorConsumer = consumer;
myJavaModule = module;
}
void report(@NotNull JavaCompilationError<?, ?> error) {
@@ -335,6 +338,21 @@ final class JavaErrorVisitor extends JavaElementVisitor {
if (!hasErrorResults()) myClassChecker.checkStaticDeclarationInInnerClass(keyword);
}
@Override
public void visitImportStaticStatement(@NotNull PsiImportStaticStatement statement) {
checkFeature(statement, JavaFeature.STATIC_IMPORTS);
if (!hasErrorResults()) {
PsiJavaCodeReferenceElement importReference = statement.getImportReference();
PsiClass targetClass = statement.resolveTargetClass();
if (importReference != null) {
PsiElement referenceNameElement = importReference.getReferenceNameElement();
if (referenceNameElement != null && targetClass != null) {
myGenericsChecker.checkClassSupersAccessibility(targetClass, referenceNameElement, myFile.getResolveScope());
}
}
}
}
@Override
public void visitClass(@NotNull PsiClass aClass) {
super.visitClass(aClass);
@@ -345,6 +363,8 @@ final class JavaErrorVisitor extends JavaElementVisitor {
if (!hasErrorResults()) myClassChecker.checkPublicClassInRightFile(aClass);
if (!hasErrorResults()) myClassChecker.checkSealedClassInheritors(aClass);
if (!hasErrorResults()) myClassChecker.checkSealedSuper(aClass);
if (!hasErrorResults()) myGenericsChecker.checkInterfaceMultipleInheritance(aClass);
if (!hasErrorResults()) myGenericsChecker.checkClassSupersAccessibility(aClass);
if (!hasErrorResults()) myRecordChecker.checkRecordHeader(aClass);
}
@@ -355,6 +375,16 @@ final class JavaErrorVisitor extends JavaElementVisitor {
visitExpression(expression);
if (hasErrorResults()) return;
}
PsiElement parent = expression.getParent();
PsiExpression qualifierExpression = expression.getQualifierExpression();
if (!hasErrorResults() && myJavaModule == null && qualifierExpression != null) {
if (parent instanceof PsiMethodCallExpression) {
PsiClass psiClass = RefactoringChangeUtil.getQualifierClass(expression);
if (psiClass != null) {
myGenericsChecker.checkClassSupersAccessibility(psiClass, expression, myFile.getResolveScope());
}
}
}
}
@Override
@@ -188,6 +188,7 @@ public final class JavaErrorKinds {
.withAnchor(parameter -> requireNonNullElse(parameter.getTypeElement(), parameter)).parameterized();
public static final Parameterized<PsiReceiverParameter, @Nullable String> RECEIVER_NAME_MISMATCH =
error(PsiReceiverParameter.class, "receiver.name.mismatch").withAnchor(PsiReceiverParameter::getIdentifier).parameterized();
// PsiMember = PsiClass | PsiEnumConstant
public static final Parameterized<PsiMember, PsiMethod> CLASS_NO_ABSTRACT_METHOD =
error(PsiMember.class, "class.must.implement.method")
@@ -293,7 +294,23 @@ public final class JavaErrorKinds {
.withRawDescription((psi, ctx) -> message(
"class.cannot.be.referenced.from.static.context",
formatClass(ctx.outerClass()) + "." + (psi instanceof PsiSuperExpression ? PsiKeyword.SUPER : PsiKeyword.THIS)));
public static final Parameterized<PsiClass, InheritTypeClashContext> CLASS_INHERITANCE_DIFFERENT_TYPE_ARGUMENTS =
parameterized(PsiClass.class, InheritTypeClashContext.class, "class.inheritance.different.type.arguments")
.withRange((cls, ctx) -> getClassDeclarationTextRange(cls))
.withRawDescription((cls, ctx) -> message("class.inheritance.different.type.arguments",
formatClass(ctx.superClass()),
formatType(ctx.type1()),
formatType(ctx.type2())));
public static final Parameterized<PsiClass, InheritTypeClashContext> CLASS_INHERITANCE_RAW_AND_GENERIC =
parameterized(PsiClass.class, InheritTypeClashContext.class, "class.inheritance.raw.and.generic")
.withRange((cls, ctx) -> getClassDeclarationTextRange(cls))
.withRawDescription((cls, ctx) -> message("class.inheritance.raw.and.generic",
formatClass(ctx.superClass()),
formatType(ctx.type1() != null ? ctx.type1() : ctx.type2())));
public static final Parameterized<PsiElement, PsiClass> CLASS_NOT_ACCESSIBLE =
parameterized(PsiElement.class, PsiClass.class, "class.not.accessible")
.withRange((psi, cls) -> psi instanceof PsiMember member ? getMemberDeclarationTextRange(member) : null)
.withRawDescription((psi, cls) -> message("class.not.accessible", formatClass(cls)));
public static final Simple<PsiJavaCodeReferenceElement> VALUE_CLASS_EXTENDS_NON_ABSTRACT = error("value.class.extends.non.abstract");
@@ -625,6 +642,8 @@ public final class JavaErrorKinds {
public record OverrideClashContext(@NotNull PsiMethod method, @NotNull PsiMethod superMethod) {
}
public record InheritTypeClashContext(@NotNull PsiClass superClass, @Nullable PsiType type1, @Nullable PsiType type2) {}
public record IncompatibleOverrideReturnTypeContext(@NotNull PsiMethod method,
@NotNull PsiType methodReturnType,
@@ -315,66 +315,6 @@ public final class GenericsHighlightUtil {
}
}
static HighlightInfo.Builder checkInterfaceMultipleInheritance(@NotNull PsiClass aClass) {
PsiClassType[] types = aClass.getSuperTypes();
if (types.length < 2) return null;
TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass);
return checkInterfaceMultipleInheritance(aClass,
aClass,
PsiSubstitutor.EMPTY, new HashMap<>(),
new HashSet<>(), textRange);
}
private static HighlightInfo.Builder checkInterfaceMultipleInheritance(@NotNull PsiClass aClass,
@NotNull PsiElement place,
@NotNull PsiSubstitutor derivedSubstitutor,
@NotNull Map<PsiClass, PsiSubstitutor> inheritedClasses,
@NotNull Set<? super PsiClass> visited,
@NotNull TextRange textRange) {
List<PsiClassType.ClassResolveResult> superTypes = PsiClassImplUtil.getScopeCorrectedSuperTypes(aClass, place.getResolveScope());
for (PsiClassType.ClassResolveResult result : superTypes) {
PsiClass superClass = result.getElement();
if (superClass == null || visited.contains(superClass)) continue;
PsiSubstitutor superTypeSubstitutor = result.getSubstitutor();
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(aClass.getProject());
//JLS 4.8 The superclasses (respectively, superinterfaces) of a raw type are the erasures of the superclasses (superinterfaces) of any of the parameterizations of the generic type.
superTypeSubstitutor = PsiUtil.isRawSubstitutor(aClass, derivedSubstitutor) ? elementFactory.createRawSubstitutor(superClass)
: MethodSignatureUtil.combineSubstitutors(superTypeSubstitutor, derivedSubstitutor);
PsiSubstitutor inheritedSubstitutor = inheritedClasses.get(superClass);
if (inheritedSubstitutor != null) {
PsiTypeParameter[] typeParameters = superClass.getTypeParameters();
for (PsiTypeParameter typeParameter : typeParameters) {
PsiType type1 = inheritedSubstitutor.substitute(typeParameter);
PsiType type2 = superTypeSubstitutor.substitute(typeParameter);
if (!Comparing.equal(type1, type2)) {
String description;
if (type1 != null && type2 != null) {
description = JavaErrorBundle.message("generics.cannot.be.inherited.with.different.type.arguments",
HighlightUtil.formatClass(superClass),
JavaHighlightUtil.formatType(type1),
JavaHighlightUtil.formatType(type2));
}
else {
description = JavaErrorBundle.message("generics.cannot.be.inherited.as.raw.and.generic",
HighlightUtil.formatClass(superClass),
JavaHighlightUtil.formatType(type1 != null ? type1 : type2));
}
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description);
}
}
}
inheritedClasses.put(superClass, superTypeSubstitutor);
visited.add(superClass);
HighlightInfo.Builder builder = checkInterfaceMultipleInheritance(superClass, place, superTypeSubstitutor, inheritedClasses, visited, textRange);
visited.remove(superClass);
if (builder != null) return builder;
}
return null;
}
static void computeOverrideEquivalentMethodErrors(@NotNull PsiClass aClass,
@NotNull Set<? super PsiClass> overrideEquivalentMethodsVisitedClasses,
@NotNull Map<PsiMember, HighlightInfo.Builder> overrideEquivalentMethodsErrors) {
@@ -1189,32 +1129,6 @@ public final class GenericsHighlightUtil {
return null;
}
static HighlightInfo.Builder checkClassSupersAccessibility(@NotNull PsiClass aClass) {
HighlightInfo.Builder builder = checkClassSupersAccessibility(aClass, aClass.getResolveScope(), true);
return builder == null ? null : builder.range(HighlightNamesUtil.getClassDeclarationTextRange(aClass));
}
static HighlightInfo.Builder checkClassSupersAccessibility(@NotNull PsiClass aClass, @NotNull PsiElement ref, @NotNull GlobalSearchScope scope) {
HighlightInfo.Builder builder = checkClassSupersAccessibility(aClass, scope, false);
return builder == null ? null : builder.range(ref.getTextRange());
}
private static HighlightInfo.Builder checkClassSupersAccessibility(@NotNull PsiClass aClass,
@NotNull GlobalSearchScope resolveScope,
boolean checkParameters) {
JavaPsiFacade factory = JavaPsiFacade.getInstance(aClass.getProject());
for (PsiClassType superType : aClass.getSuperTypes()) {
HashSet<PsiClass> checked = new HashSet<>();
checked.add(aClass);
String notAccessibleErrorMessage = isTypeAccessible(superType, checked, checkParameters, true, resolveScope, factory);
if (notAccessibleErrorMessage != null) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.descriptionAndTooltip(notAccessibleErrorMessage);
}
}
return null;
}
static HighlightInfo.Builder checkMemberSignatureTypesAccessibility(@NotNull PsiReferenceExpression ref) {
String message = null;
@@ -44,7 +44,6 @@ 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.refactoring.util.RefactoringChangeUtil;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.NewUI;
import com.intellij.util.JavaPsiConstructorUtil;
@@ -221,7 +220,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myJavaModule = JavaFeature.MODULES.isSufficient(myLanguageLevel) ? JavaModuleGraphUtil.findDescriptorByElement(file) : null;
myPreviewFeatureVisitor = myLanguageLevel.isPreview() ? null : new PreviewFeatureUtil.PreviewFeatureVisitor(myLanguageLevel, myErrorSink);
JavaErrorFixProvider errorFixProvider = JavaErrorFixProvider.getInstance();
myCollector = new JavaErrorCollector(myFile, error -> reportError(error, errorFixProvider));
myCollector = new JavaErrorCollector(myFile, myJavaModule, error -> reportError(error, errorFixProvider));
}
private void reportError(JavaCompilationError<?, ?> error, JavaErrorFixProvider errorFixProvider) {
@@ -458,8 +457,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
public void visitClass(@NotNull PsiClass aClass) {
super.visitClass(aClass);
if (aClass instanceof PsiSyntheticClass) return;
if (!hasErrorResults()) add(GenericsHighlightUtil.checkInterfaceMultipleInheritance(aClass));
if (!hasErrorResults()) add(GenericsHighlightUtil.checkClassSupersAccessibility(aClass));
if (!hasErrorResults()) add(HighlightUtil.checkImplicitThisReferenceBeforeSuper(aClass, myJavaSdkVersion));
if (!hasErrorResults()) GenericsHighlightUtil.checkTypeParameterOverrideEquivalentMethods(aClass, myLanguageLevel, myErrorSink, myOverrideEquivalentMethodsVisitedClasses, myOverrideEquivalentMethodsErrors);
}
@@ -619,21 +616,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitImportStaticStatement(@NotNull PsiImportStaticStatement statement) {
add(checkFeature(statement, JavaFeature.STATIC_IMPORTS));
visitElement(statement);
if (!hasErrorResults()) add(ImportsHighlightUtil.checkStaticOnDemandImportResolvesToClass(statement));
if (!hasErrorResults()) {
PsiJavaCodeReferenceElement importReference = statement.getImportReference();
PsiClass targetClass = statement.resolveTargetClass();
if (importReference != null) {
PsiElement referenceNameElement = importReference.getReferenceNameElement();
if (referenceNameElement != null && targetClass != null) {
add(GenericsHighlightUtil.checkClassSupersAccessibility(targetClass, referenceNameElement, myFile.getResolveScope()));
}
}
if (!hasErrorResults()) {
PreviewFeatureUtil.checkPreviewFeature(statement, myPreviewFeatureVisitor);
}
}
if (!hasErrorResults()) PreviewFeatureUtil.checkPreviewFeature(statement, myPreviewFeatureVisitor);
}
@Override
@@ -1172,15 +1157,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
PsiExpression qualifierExpression = expression.getQualifierExpression();
add(HighlightUtil.checkUnqualifiedSuperInDefaultMethod(myLanguageLevel, expression, qualifierExpression));
if (!hasErrorResults() && myJavaModule == null && qualifierExpression != null) {
if (parent instanceof PsiMethodCallExpression) {
PsiClass psiClass = RefactoringChangeUtil.getQualifierClass(expression);
if (psiClass != null) {
add(GenericsHighlightUtil.checkClassSupersAccessibility(psiClass, expression, myFile.getResolveScope()));
}
}
if (!hasErrorResults()) {
add(GenericsHighlightUtil.checkMemberSignatureTypesAccessibility(expression));
}
add(GenericsHighlightUtil.checkMemberSignatureTypesAccessibility(expression));
}
if (!hasErrorResults() && resolved instanceof PsiModifierListOwner) {
PreviewFeatureUtil.checkPreviewFeature(expression, myPreviewFeatureVisitor);
@@ -4,7 +4,7 @@ import static p.<error descr="Cannot access p.BaseClass">ChildClass</error>.*;
class Sample {
public static void main(String[] args) {
ChildClass.<error descr="Cannot resolve method 'foo' in 'ChildClass'">foo</error>();
<error descr="Cannot access p.BaseClass">ChildClass.foo</error>();
foo();
ChildClass cc = ChildClass2.childClass();
}