From be3b895bb20f34f10568f48222abaca5ef10199e Mon Sep 17 00:00:00 2001 From: "Roman.Ivanov" Date: Wed, 8 Jul 2020 17:22:07 +0700 Subject: [PATCH] Make enums with fields with class bodies implicitly sealed GitOrigin-RevId: c1077073a038df9853e3a38a33672bf4dc21c28c --- .../daemon/impl/analysis/HighlightClassUtil.java | 10 +++++++++- .../intellij/psi/impl/source/PsiModifierListImpl.java | 5 ++++- .../advHighlightingSealedTypes/SealedTypesBasics.java | 4 ++++ .../sealClass/afterImplicitlySealedEnumInheritor.java | 9 +++++++++ .../quickFix/sealClass/beforeImplicitlySealedEnum.java | 5 +++++ .../sealClass/beforeImplicitlySealedEnumInheritor.java | 9 +++++++++ .../uast-tests/java/Simple/EnumValueMembers.render.txt | 2 +- 7 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/afterImplicitlySealedEnumInheritor.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/beforeImplicitlySealedEnum.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/beforeImplicitlySealedEnumInheritor.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java index e041b05c8217..e36a44aab72f 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java @@ -1091,6 +1091,12 @@ public class HighlightClassUtil { if (psiClass.hasModifierProperty(PsiModifier.SEALED) && psiClass.getPermitsListTypes().length == 0) { PsiIdentifier nameIdentifier = psiClass.getNameIdentifier(); if (nameIdentifier == null) return null; + if (psiClass.isEnum() && StreamEx.of(psiClass.getAllFields()) + .select(PsiEnumConstant.class) + .anyMatch(field -> field.getInitializingClass() != null) + ) { + return null; + } if (!DirectClassInheritorsSearch.search(psiClass, new LocalSearchScope(psiClass.getContainingFile())).anyMatch(c -> !PsiUtil.isLocalOrAnonymousClass(c))) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(nameIdentifier) @@ -1107,7 +1113,9 @@ public class HighlightClassUtil { !aClass.hasModifierProperty(PsiModifier.SEALED) && !aClass.hasModifierProperty(PsiModifier.NON_SEALED) && !aClass.hasModifierProperty(PsiModifier.FINAL) && - Arrays.stream(aClass.getSuperTypes()).map(type -> type.resolve()).anyMatch(superClass -> superClass != null && superClass.hasModifierProperty(PsiModifier.SEALED))) { + Arrays.stream(aClass.getSuperTypes()) + .map(type -> type.resolve()) + .anyMatch(superClass -> superClass != null && superClass.hasModifierProperty(PsiModifier.SEALED) && !superClass.isEnum())) { HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(nameIdentifier) .descriptionAndTooltip(JavaErrorBundle.message("sealed.type.inheritor.expected.modifiers", PsiModifier.SEALED, PsiModifier.NON_SEALED, PsiModifier.FINAL)).create(); if (!aClass.isInterface()) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java index 30ab1076e049..2df589d425e0 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java @@ -134,7 +134,10 @@ public class PsiModifierListImpl extends JavaStubPsiElement List fields = parent instanceof PsiExtensibleClass ? ((PsiExtensibleClass)parent).getOwnFields() : Arrays.asList(((PsiClass)parent).getFields()); boolean hasSubClass = ContainerUtil.find(fields, field -> field instanceof PsiEnumConstant && ((PsiEnumConstant)field).getInitializingClass() != null) != null; - if (!hasSubClass) { + if (hasSubClass) { + implicitModifiers.add(SEALED); + } + else { implicitModifiers.add(FINAL); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedTypesBasics.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedTypesBasics.java index 5a8a3c18f3a0..0d719c88df4c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedTypesBasics.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedTypesBasics.java @@ -17,3 +17,7 @@ class ICSameFilenon-sealed interface ID extends ID1 {} + +enum ImplicitlySealedEnum { + A {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/afterImplicitlySealedEnumInheritor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/afterImplicitlySealedEnumInheritor.java new file mode 100644 index 000000000000..1271381496b7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/afterImplicitlySealedEnumInheritor.java @@ -0,0 +1,9 @@ +// "Seal class" "true" + +sealed interface Parent { + +} + +enum Foo implements Parent { + A {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/beforeImplicitlySealedEnum.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/beforeImplicitlySealedEnum.java new file mode 100644 index 000000000000..49296485a64c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/beforeImplicitlySealedEnum.java @@ -0,0 +1,5 @@ +// "Seal class" "false" + +enum Foo { + A {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/beforeImplicitlySealedEnumInheritor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/beforeImplicitlySealedEnumInheritor.java new file mode 100644 index 000000000000..a8b3c8c559fc --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/sealClass/beforeImplicitlySealedEnumInheritor.java @@ -0,0 +1,9 @@ +// "Seal class" "true" + +interface Parent { + +} + +enum Foo implements Parent { + A {} +} \ No newline at end of file diff --git a/uast/uast-tests/java/Simple/EnumValueMembers.render.txt b/uast/uast-tests/java/Simple/EnumValueMembers.render.txt index 8b2ec09d85b2..e78f45985e5e 100644 --- a/uast/uast-tests/java/Simple/EnumValueMembers.render.txt +++ b/uast/uast-tests/java/Simple/EnumValueMembers.render.txt @@ -1,4 +1,4 @@ -public enum Style { +public sealed enum Style { SHEET("foo") { @java.lang.Override public fun getExitAnimation() : java.lang.String {