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 7c76a792220a..f85afa0270d8 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
@@ -1012,4 +1012,28 @@ public class HighlightClassUtil {
}
return null;
}
+
+ static HighlightInfo checkExtendsSealedClass(PsiClass aClass, PsiClass superClass, PsiJavaCodeReferenceElement elementToHighlight) {
+ if (superClass.hasModifierProperty(PsiModifier.SEALED)) {
+ PsiClassType[] permittedTypes = superClass.getPermitsListTypes();
+ if (permittedTypes.length > 0) {
+ if (Arrays.stream(permittedTypes).map(permittedType -> permittedType.resolve()).anyMatch(permittedClass -> aClass.equals(permittedClass))) {
+ return null;
+ }
+ }
+ else if (JavaPsiFacade.getInstance(aClass.getProject()).arePackagesTheSame(aClass, superClass)) {
+ return null;
+ }
+ else {
+ PsiJavaModule javaModule = JavaModuleGraphUtil.findDescriptorByElement(aClass);
+ if (javaModule != null && javaModule == JavaModuleGraphUtil.findDescriptorByElement(superClass)) {
+ return null;
+ }
+ }
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
+ .descriptionAndTooltip(JavaErrorBundle.message("not.allowed.in.sealed.hierarchy", aClass.getName()))
+ .range(elementToHighlight).create();
+ }
+ return null;
+ }
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
index 512b2f1c916c..e02efb254839 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
@@ -3153,6 +3153,9 @@ public class HighlightUtil {
if (highlightInfo == null) {
highlightInfo = GenericsHighlightUtil.checkCannotInheritFromTypeParameter(aClass, ref);
}
+ if (highlightInfo == null) {
+ highlightInfo = HighlightClassUtil.checkExtendsSealedClass((PsiClass)refGrandParent, aClass, ref);
+ }
}
}
else if (refGrandParent instanceof PsiMethod && ((PsiMethod)refGrandParent).getThrowsList() == referenceList) {
diff --git a/java/java-psi-impl/src/messages/JavaErrorBundle.properties b/java/java-psi-impl/src/messages/JavaErrorBundle.properties
index e5ce278d1dc7..ba34d1e2b5bd 100644
--- a/java/java-psi-impl/src/messages/JavaErrorBundle.properties
+++ b/java/java-psi-impl/src/messages/JavaErrorBundle.properties
@@ -476,3 +476,4 @@ type.parameter.has.incompatible.upper.bounds=Type parameter {0} has incompatible
safevarargs.not.allowed.on.methods.with.fixed.arity=@SafeVarargs is not allowed on methods with fixed arity
functional.interface.must.not.be.sealed.error.description=Functional interface can''t be declared as ''{0}''
sealed.type.inheritor.expected.modifiers={0}, {1} or {2} modifiers expected
+not.allowed.in.sealed.hierarchy={0} is not allowed in the sealed hierarchy
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedTypesBasics.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedTypesBasics.java
index 9ce1b21f2448..5a8a3c18f3a0 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedTypesBasics.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingSealedTypes/SealedTypesBasics.java
@@ -3,7 +3,7 @@ sealed class A permits B {}
sealed class B extends A permits C, D {}
final class C extends B {}
non-sealed class D extends B {}
-class E extends A {}
+class E extends A {}
sealed sealed class SealedSealed {}
sealed non-sealed class SealedNonSealed {}
sealed final class SealedFinal {}