java sealed types: check sealed class inheritors (IDEA-243536)

GitOrigin-RevId: 0390d8db04b10b8d5c1206987877d6356a93d535
This commit is contained in:
Anna Kozlova
2020-06-16 17:13:07 +03:00
committed by intellij-monorepo-bot
parent ed160cbeeb
commit 7d2384271f
4 changed files with 29 additions and 1 deletions
@@ -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;
}
}
@@ -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) {
@@ -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
@@ -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 <error descr="sealed, non-sealed or final modifiers expected">E</error> extends A {}
class E extends <error descr="E is not allowed in the sealed hierarchy">A</error> {}
<error descr="Illegal combination of modifiers: 'sealed' and 'sealed'">sealed</error> <error descr="Illegal combination of modifiers: 'sealed' and 'sealed'">sealed</error> class SealedSealed {}
<error descr="Illegal combination of modifiers: 'sealed' and 'non-sealed'">sealed</error> <error descr="Illegal combination of modifiers: 'non-sealed' and 'sealed'">non-sealed</error> class SealedNonSealed {}
<error descr="Illegal combination of modifiers: 'sealed' and 'final'">sealed</error> <error descr="Illegal combination of modifiers: 'final' and 'sealed'">final</error> class SealedFinal {}