static interface methods: forbid on instance members, inheritors (IDEA-107794)

This commit is contained in:
Anna Kozlova
2013-05-30 15:46:53 +04:00
parent ed52a33e87
commit fb8144344c
4 changed files with 41 additions and 0 deletions
@@ -326,6 +326,9 @@ public class HighlightMethodUtil {
if (resolved instanceof PsiMethod && resolveResult.isValidResult()) {
TextRange fixRange = getFixRange(methodCall);
highlightInfo = HighlightUtil.checkUnhandledExceptions(methodCall, fixRange);
if (highlightInfo == null && !LambdaUtil.isValidQualifier4InterfaceStaticMethodCall((PsiMethod)resolved, methodCall.getMethodExpression())) {
highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip("Static method may be invoked on containing interface class only").range(fixRange).create();
}
}
else {
PsiMethod resolvedMethod = null;
@@ -789,6 +789,18 @@ public class LambdaUtil {
return null;
}
public static boolean isValidQualifier4InterfaceStaticMethodCall(@NotNull PsiMethod method, @NotNull PsiReferenceExpression methodReferenceExpression) {
if (PsiUtil.isLanguageLevel8OrHigher(methodReferenceExpression)) {
final PsiExpression qualifierExpression = methodReferenceExpression.getQualifierExpression();
final PsiClass containingClass = method.getContainingClass();
if (containingClass != null && containingClass.isInterface() && method.hasModifierProperty(PsiModifier.STATIC)) {
return qualifierExpression == null && PsiTreeUtil.isAncestor(containingClass, methodReferenceExpression, true)||
qualifierExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression)qualifierExpression).resolve() == containingClass;
}
}
return true;
}
static class TypeParamsChecker extends PsiTypeVisitor<Boolean> {
private PsiMethod myMethod;
private final PsiClass myClass;
@@ -0,0 +1,25 @@
class Bug {
interface Function<T, R> {
public R apply(T t);
static <K> Function<K, K> identity() {
return k -> k;
}
}
interface IFunction extends Function<Integer, Integer> {
static void a() {
Function<Integer, Integer> identity = <error descr="Static method may be invoked on containing interface class only">identity();</error>
}
}
public void foo() {
Function<Integer, Integer> f = Function.identity();
Function<Integer, Integer> g = <error descr="Static method may be invoked on containing interface class only">f.identity();</error>
Function<Integer, Integer> h = <error descr="Static method may be invoked on containing interface class only">IFunction.identity();</error>
}
}
@@ -30,6 +30,7 @@ public class Interface8MethodsHighlightingTest extends LightDaemonAnalyzerTestCa
public void testStaticMethodsInFunctionalInterface() { doTest(false, false); }
public void testCyclicSubstitutor() { doTest(false, false); }
public void testThisAccessibility() { doTest(false, false); }
public void testStaticMethodCalls() { doTest(false, false); }
private void doTest() {
doTest(false, false);