diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java index ebdccd98d088..63416fa26746 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java @@ -406,6 +406,14 @@ public class AnnotationsHighlightUtil { return null; } + public static HighlightInfo checkFunctionalInterface(PsiAnnotation annotation) { + final String errorMessage = LambdaUtil.checkFunctionalInterface(annotation); + if (errorMessage != null) { + return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, annotation, errorMessage); + } + return null; + } + public static class AnnotationReturnTypeVisitor extends PsiTypeVisitor { public static final AnnotationReturnTypeVisitor INSTANCE = new AnnotationReturnTypeVisitor(); @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index fdf7506d9e39..88e1377636c2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -182,6 +182,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkTargetAnnotationDuplicates(annotation)); if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkDuplicateAnnotations(annotation)); if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkForeignInnerClassesUsed(annotation)); + if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkFunctionalInterface(annotation)); } @Override 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 9739e9467701..07c5d749a859 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -25,6 +25,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.util.*; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,6 +38,7 @@ import java.util.*; public class LambdaUtil { private static final Logger LOG = Logger.getInstance("#" + LambdaUtil.class.getName()); public static ThreadLocal> ourParams = new ThreadLocal>(); + @NonNls public static final String JAVA_LANG_FUNCTIONAL_INTERFACE = "java.lang.FunctionalInterface"; @Nullable public static PsiType getFunctionalInterfaceReturnType(PsiLambdaExpression expr) { @@ -659,6 +661,20 @@ public class LambdaUtil { return getFunctionalInterfaceReturnType(functionalInterfaceType); } + @Nullable + public static String checkFunctionalInterface(PsiAnnotation annotation) { + if (PsiUtil.isLanguageLevel8OrHigher(annotation) && Comparing.strEqual(annotation.getQualifiedName(), JAVA_LANG_FUNCTIONAL_INTERFACE)) { + final PsiAnnotationOwner owner = annotation.getOwner(); + if (owner instanceof PsiModifierList) { + final PsiElement parent = ((PsiModifierList)owner).getParent(); + if (parent instanceof PsiClass) { + return LambdaHighlightingUtil.checkInterfaceFunctional((PsiClass)parent); + } + } + } + return null; + } + static class TypeParamsChecker extends PsiTypeVisitor { private PsiMethod myMethod; private final PsiClass myClass; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation.java new file mode 100644 index 000000000000..05b2585c8405 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation.java @@ -0,0 +1,5 @@ +@FunctionalInterface +interface Test { + void foo(); + void bar(); +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index feaece4407eb..aa42c0b41db0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -200,6 +200,10 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(true); } + public void testFunctionalInterfaceAnnotation() throws Exception { + doTest(); + } + private void doTest() throws Exception { doTest(false); } diff --git a/java/mockJDK-1.7/jre/lib/rt.jar b/java/mockJDK-1.7/jre/lib/rt.jar index f2c43d2be6e6..797d0c1b7551 100644 Binary files a/java/mockJDK-1.7/jre/lib/rt.jar and b/java/mockJDK-1.7/jre/lib/rt.jar differ