java: highlight static import if interface method is not accessible (IDEA-262496)

GitOrigin-RevId: 8e45087f2b8a95b9333f835eb2779fac1b6fb764
This commit is contained in:
Anna Kozlova
2021-02-19 11:02:17 +01:00
committed by intellij-monorepo-bot
parent ba64a1152a
commit 89bf390fb1
4 changed files with 51 additions and 22 deletions

View File

@@ -628,7 +628,7 @@ public final class HighlightMethodUtil {
}
}
static HighlightInfo checkStaticInterfaceCallQualifier(@NotNull PsiReferenceExpression referenceToMethod,
static HighlightInfo checkStaticInterfaceCallQualifier(@NotNull PsiJavaCodeReferenceElement referenceToMethod,
@NotNull JavaResolveResult resolveResult,
@NotNull PsiElement elementToHighlight,
@NotNull PsiClass containingClass) {
@@ -636,40 +636,47 @@ public final class HighlightMethodUtil {
if (message != null) {
HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(message)
.range(getFixRange(elementToHighlight)).create();
QuickFixAction
.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createAccessStaticViaInstanceFix(referenceToMethod, resolveResult));
if (referenceToMethod instanceof PsiReferenceExpression) {
QuickFixAction
.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createAccessStaticViaInstanceFix((PsiReferenceExpression)referenceToMethod, resolveResult));
}
return highlightInfo;
}
return null;
}
/* see also PsiReferenceExpressionImpl.hasValidQualifier() */
private static @NlsContexts.DetailedDescription String checkStaticInterfaceMethodCallQualifier(@NotNull PsiReferenceExpression ref,
private static @NlsContexts.DetailedDescription String checkStaticInterfaceMethodCallQualifier(@NotNull PsiJavaCodeReferenceElement ref,
@Nullable PsiElement scope,
@NotNull PsiClass containingClass) {
PsiExpression qualifierExpression = ref.getQualifierExpression();
if (qualifierExpression == null && (scope instanceof PsiImportStaticStatement || PsiTreeUtil.isAncestor(containingClass, ref, true))) {
@Nullable PsiElement qualifierExpression = ref.getQualifier();
if (qualifierExpression == null && PsiTreeUtil.isAncestor(containingClass, ref, true)) {
return null;
}
if (qualifierExpression instanceof PsiReferenceExpression) {
PsiElement resolve = ((PsiReferenceExpression)qualifierExpression).resolve();
if (containingClass.getManager().areElementsEquivalent(resolve, containingClass)) {
return null;
PsiElement resolve = null;
if (qualifierExpression == null && scope instanceof PsiImportStaticStatement) {
resolve = ((PsiImportStaticStatement)scope).resolveTargetClass();
}
else if (qualifierExpression instanceof PsiJavaCodeReferenceElement) {
resolve = ((PsiJavaCodeReferenceElement)qualifierExpression).resolve();
}
if (containingClass.getManager().areElementsEquivalent(resolve, containingClass)) {
return null;
}
if (resolve instanceof PsiTypeParameter) {
Set<PsiClass> classes = new HashSet<>();
for (PsiClassType type : ((PsiTypeParameter)resolve).getExtendsListTypes()) {
PsiClass aClass = type.resolve();
if (aClass != null) {
classes.add(aClass);
}
}
if (resolve instanceof PsiTypeParameter) {
Set<PsiClass> classes = new HashSet<>();
for (PsiClassType type : ((PsiTypeParameter)resolve).getExtendsListTypes()) {
PsiClass aClass = type.resolve();
if (aClass != null) {
classes.add(aClass);
}
}
if (classes.size() == 1 && classes.contains(containingClass)) {
return null;
}
if (classes.size() == 1 && classes.contains(containingClass)) {
return null;
}
}

View File

@@ -828,6 +828,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
if (!myHolder.hasErrorResults() && results.length == 1) {
myHolder.add(HighlightUtil.checkReference(ref, results[0], myFile, myLanguageLevel));
if (!myHolder.hasErrorResults()) {
PsiElement element = results[0].getElement();
PsiClass containingClass = element instanceof PsiMethod ? ((PsiMethod)element).getContainingClass() : null;
if (containingClass != null && containingClass.isInterface()) {
myHolder.add(HighlightMethodUtil.checkStaticInterfaceCallQualifier(ref, results[0], ObjectUtils.notNull(ref.getReferenceNameElement(), ref), containingClass));
}
}
}
if (!myHolder.hasErrorResults()) {
PsiElement resolved = results.length >= 1 ? results[0].getElement() : null;

View File

@@ -0,0 +1,7 @@
import static p.Foo.FooEx.<error descr="Static method may be invoked on containing interface class only">foo</error>;
class FooImpl {
public void baz() {
<error descr="Static method may be invoked on containing interface class only">foo();</error>
}
}

View File

@@ -88,6 +88,14 @@ public class Interface8MethodsHighlightingTest extends LightJavaCodeInsightFixtu
doTest(false, false);
}
public void testStaticMethodAccessibleThroughInheritance() {
myFixture.addClass("package p; public interface Foo {" +
" static void foo() {}" +
" interface FooEx extends Foo {} " +
"}");
doTest(false, false);
}
public void testSuperProtectedCalls() {
myFixture.addClass("package p; public class Foo {" +
" protected void foo(){}" +