diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
index 68b97f73fdd5..664948b6c7cf 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
@@ -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);
}
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 31fb45a139de..8f072b7853e9 100644
--- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
@@ -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
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/AccessToStaticMethodsFromInterfaces.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/AccessToStaticMethodsFromInterfaces.java
new file mode 100644
index 000000000000..b2b0bb1feb9e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/AccessToStaticMethodsFromInterfaces.java
@@ -0,0 +1,14 @@
+class Test {
+ interface I {
+ static void foo() {}
+ }
+
+ abstract class IImpl implements I {}
+ interface I2 extends I {}
+
+ {
+ I.foo();
+ IImpl.foo();
+ I2.foo();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java
index 36861062d1a0..1c41cd93ea5d 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java
@@ -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); }
}