From 2dcab690d55404e8ad6f70f944ee39348f376e8c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 15 Jun 2020 21:46:15 +0200 Subject: [PATCH] java sealed types: functional interface can't be sealed (IDEA-243536) GitOrigin-RevId: 7660808963e79d51b8d1507927d1095d119bcdb5 --- .../daemon/impl/analysis/AnnotationsHighlightUtil.java | 10 +++++++++- .../daemon/impl/analysis/LambdaHighlightingUtil.java | 3 ++- .../src/messages/JavaErrorBundle.properties | 1 + .../SealedFunctionalInterface.java | 4 ++++ .../daemon/LightSealedTypesHighlightingTest.java | 5 ++--- 5 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedFunctionalInterface.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java index cc18adfedb3e..92c9db003873 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java @@ -565,10 +565,18 @@ public class AnnotationsHighlightUtil { if (owner instanceof PsiModifierList) { final PsiElement parent = ((PsiModifierList)owner).getParent(); if (parent instanceof PsiClass) { - final String errorMessage = LambdaHighlightingUtil.checkInterfaceFunctional((PsiClass)parent, ((PsiClass)parent).getName() + " is not a functional interface"); + final String errorMessage = LambdaHighlightingUtil.checkInterfaceFunctional((PsiClass)parent, JavaErrorBundle.message("not.a.functional.interface", ((PsiClass)parent).getName())); if (errorMessage != null) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(annotation).descriptionAndTooltip(errorMessage).create(); } + + if (HighlightingFeature.SEALED_CLASSES.isSufficient(languageLevel) && + ((PsiClass)parent).hasModifierProperty(PsiModifier.SEALED)) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(annotation) + .descriptionAndTooltip(JavaErrorBundle.message("functional.interface.must.not.be.sealed.error.description", PsiModifier.SEALED)) + .create(); + } } } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/LambdaHighlightingUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/LambdaHighlightingUtil.java index d76794dd22c8..2b111654d927 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/LambdaHighlightingUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/LambdaHighlightingUtil.java @@ -24,6 +24,7 @@ import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import java.util.HashSet; @@ -37,7 +38,7 @@ public class LambdaHighlightingUtil { return checkInterfaceFunctional(psiClass, JavaErrorBundle.message("target.type.of.a.lambda.conversion.must.be.an.interface")); } - static String checkInterfaceFunctional(@NotNull PsiClass psiClass, @NotNull String interfaceNonFunctionalMessage) { + static String checkInterfaceFunctional(@NotNull PsiClass psiClass, @NotNull @Nls String interfaceNonFunctionalMessage) { if (psiClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference final List signatures = LambdaUtil.findFunctionCandidates(psiClass); if (signatures == null) return interfaceNonFunctionalMessage; diff --git a/java/java-psi-impl/src/messages/JavaErrorBundle.properties b/java/java-psi-impl/src/messages/JavaErrorBundle.properties index ca0504f27b1d..dec8db70378f 100644 --- a/java/java-psi-impl/src/messages/JavaErrorBundle.properties +++ b/java/java-psi-impl/src/messages/JavaErrorBundle.properties @@ -464,3 +464,4 @@ class.cannot.be.inherited.with.different.arguments={0} cannot be inherited with bad.type.in.switch.expression=Bad type in switch expression: {0} cannot be converted to {1} switch.expression.cannot.be.void=Target type for switch expression cannot be void annotation.on.static.member.qualifying.type.family.name=Move type annotation +functional.interface.must.not.be.sealed.error.description=Functional interface can''t be declared as ''{0}'' diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedFunctionalInterface.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedFunctionalInterface.java new file mode 100644 index 000000000000..bb87fa355bd2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedFunctionalInterface.java @@ -0,0 +1,4 @@ +@FunctionalInterface +sealed interface I { + void m(); +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightSealedTypesHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightSealedTypesHighlightingTest.java index 974495ff19a5..7b24b7520ac9 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightSealedTypesHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightSealedTypesHighlightingTest.java @@ -18,9 +18,8 @@ public class LightSealedTypesHighlightingTest extends LightJavaCodeInsightFixtur return JAVA_15; } - public void testSealedTypesBasics() { - doTest(); - } + public void testSealedTypesBasics() { doTest(); } + public void testSealedFunctionalInterface() { doTest(); } private void doTest() { myFixture.configureByFile(getTestName(false) + ".java");