warn when accessing static method of interfaces in language levels prior to 1.8 (IDEA-134814)

This commit is contained in:
Anna Kozlova
2014-12-29 18:57:41 +01:00
parent b57746c55e
commit e9beee7c66
4 changed files with 39 additions and 9 deletions
@@ -347,8 +347,10 @@ public class HighlightMethodUtil {
TextRange fixRange = getFixRange(methodCall);
highlightInfo = HighlightUtil.checkUnhandledExceptions(methodCall, fixRange);
if (highlightInfo == null) {
if (!LambdaUtil.isValidQualifier4InterfaceStaticMethodCall((PsiMethod)resolved, methodCall.getMethodExpression(), resolveResult.getCurrentFileResolveScope(), languageLevel)) {
highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip("Static method may be invoked on containing interface class only").range(fixRange).create();
final String invalidCallMessage =
LambdaUtil.getInvalidQualifier4StaticInterfaceMethodMessage((PsiMethod)resolved, methodCall.getMethodExpression(), resolveResult.getCurrentFileResolveScope(), languageLevel);
if (invalidCallMessage != null) {
highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip(invalidCallMessage).range(fixRange).create();
} else {
highlightInfo = GenericsHighlightUtil.checkInferredIntersections(substitutor, fixRange);
}
@@ -457,15 +457,28 @@ public class LambdaUtil {
public static boolean isValidQualifier4InterfaceStaticMethodCall(@NotNull PsiMethod method,
@NotNull PsiReferenceExpression methodReferenceExpression,
@Nullable PsiElement scope, @NotNull LanguageLevel languageLevel) {
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
final PsiExpression qualifierExpression = methodReferenceExpression.getQualifierExpression();
final PsiClass containingClass = method.getContainingClass();
if (containingClass != null && containingClass.isInterface() && method.hasModifierProperty(PsiModifier.STATIC)) {
return qualifierExpression == null && (scope instanceof PsiImportStaticStatement || PsiTreeUtil.isAncestor(containingClass, methodReferenceExpression, true))||
qualifierExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression)qualifierExpression).resolve() == containingClass;
return getInvalidQualifier4StaticInterfaceMethodMessage(method, methodReferenceExpression, scope, languageLevel) == null;
}
@Nullable
public static String getInvalidQualifier4StaticInterfaceMethodMessage(@NotNull PsiMethod method,
@NotNull PsiReferenceExpression methodReferenceExpression,
@Nullable PsiElement scope, @NotNull LanguageLevel languageLevel) {
final PsiExpression qualifierExpression = methodReferenceExpression.getQualifierExpression();
final PsiClass containingClass = method.getContainingClass();
if (containingClass != null && containingClass.isInterface() && method.hasModifierProperty(PsiModifier.STATIC)) {
if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
return "Static interface method invocations are not supported at this language level";
}
if (qualifierExpression == null &&
(scope instanceof PsiImportStaticStatement || PsiTreeUtil.isAncestor(containingClass, methodReferenceExpression, true)) ||
qualifierExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression)qualifierExpression).resolve() == containingClass) {
return null;
}
return "Static method may be invoked on containing interface class only";
}
return true;
return null;
}
//JLS 14.8 Expression Statements
@@ -0,0 +1,14 @@
class Test {
interface I {
<error descr="Extension methods are not supported at this language level">static void foo() {}</error>
}
abstract class IImpl implements I {}
interface I2 extends I {}
{
<error descr="Static interface method invocations are not supported at this language level">I.foo();</error>
<error descr="Static interface method invocations are not supported at this language level">IImpl.foo();</error>
<error descr="Static interface method invocations are not supported at this language level">I2.foo();</error>
}
}
@@ -187,4 +187,5 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
public void testIDEA111420() { doTest(false, false); }
public void testIDEA111450() { doTest(true, false); }
public void testExternalizable() { doTest(true, false); }
public void testAccessToStaticMethodsFromInterfaces() { doTest(true, false); }
}