[FE] Allow declaring protected constructors in sealed classes

#KT-44865 Fixed
This commit is contained in:
Dmitriy Novozhilov
2021-02-11 11:57:02 +03:00
committed by TeamCityServer
parent f3a8fcaea6
commit 7c61ddc72b
13 changed files with 447 additions and 8 deletions
@@ -346,6 +346,7 @@ public interface Errors {
DiagnosticFactory0<PsiElement> NON_PRIVATE_CONSTRUCTOR_IN_ENUM = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> NON_PRIVATE_CONSTRUCTOR_IN_SEALED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED = DiagnosticFactory0.create(ERROR);
// Inline and value classes
@@ -705,6 +705,7 @@ public class DefaultErrorMessages {
MAP.put(NON_PRIVATE_CONSTRUCTOR_IN_ENUM, "Constructor must be private in enum class");
MAP.put(NON_PRIVATE_CONSTRUCTOR_IN_SEALED, "Constructor must be private in sealed class");
MAP.put(NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED, "Constructor must be private or protected in sealed class");
MAP.put(INLINE_CLASS_NOT_TOP_LEVEL, "Inline classes cannot be local or inner");
MAP.put(INLINE_CLASS_NOT_FINAL, "Inline classes can be only final");
@@ -289,12 +289,22 @@ class DeclarationsChecker(
private fun checkConstructorVisibility(constructorDescriptor: ClassConstructorDescriptor, declaration: KtDeclaration) {
val visibilityModifier = declaration.visibilityModifier()
if (visibilityModifier != null && visibilityModifier.node?.elementType != KtTokens.PRIVATE_KEYWORD) {
val classDescriptor = constructorDescriptor.containingDeclaration
if (classDescriptor.kind == ClassKind.ENUM_CLASS) {
trace.report(NON_PRIVATE_CONSTRUCTOR_IN_ENUM.on(visibilityModifier))
} else if (classDescriptor.modality == Modality.SEALED) {
trace.report(NON_PRIVATE_CONSTRUCTOR_IN_SEALED.on(visibilityModifier))
val visibilityKeyword = visibilityModifier?.node?.elementType ?: return
val classDescriptor = constructorDescriptor.containingDeclaration
when {
classDescriptor.kind == ClassKind.ENUM_CLASS -> {
if (visibilityKeyword != KtTokens.PRIVATE_KEYWORD) {
trace.report(NON_PRIVATE_CONSTRUCTOR_IN_ENUM.on(visibilityModifier))
}
}
classDescriptor.modality == Modality.SEALED -> {
val protectedIsAllowed =
languageVersionSettings.supportsFeature(LanguageFeature.AllowSealedInheritorsInDifferentFilesOfSamePackage)
if (!(visibilityKeyword == KtTokens.PRIVATE_KEYWORD || (protectedIsAllowed && visibilityKeyword == KtTokens.PROTECTED_KEYWORD))) {
val factory = if (protectedIsAllowed) NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED else NON_PRIVATE_CONSTRUCTOR_IN_SEALED
trace.report(factory.on(visibilityModifier))
}
}
}
}