From fb8144344cbe50f22091e108675b4347c4ab8ab2 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 30 May 2013 14:07:44 +0400 Subject: [PATCH] static interface methods: forbid on instance members, inheritors (IDEA-107794) --- .../impl/analysis/HighlightMethodUtil.java | 3 +++ .../src/com/intellij/psi/LambdaUtil.java | 12 +++++++++ .../interfaceMethods/StaticMethodCalls.java | 25 +++++++++++++++++++ .../Interface8MethodsHighlightingTest.java | 1 + 4 files changed, 41 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/StaticMethodCalls.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index a38a5c11013a..80f4b1715a1c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -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; diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index d66962410665..ab97463cab91 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -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 { private PsiMethod myMethod; private final PsiClass myClass; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/StaticMethodCalls.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/StaticMethodCalls.java new file mode 100644 index 000000000000..0c517e99a7c7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/StaticMethodCalls.java @@ -0,0 +1,25 @@ + +class Bug { + + interface Function { + public R apply(T t); + + static Function identity() { + return k -> k; + } + } + + interface IFunction extends Function { + static void a() { + Function identity = identity(); + } + } + + public void foo() { + Function f = Function.identity(); + + Function g = f.identity(); + + Function h = IFunction.identity(); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java index e77dff317192..cf99110228b8 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java @@ -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);