[FE] Prohibit missed MUST_BE_INITIALIZED when there is no primary constructor
^KT-58472 Fixed Review: https://jetbrains.team/p/kt/reviews/9967
This commit is contained in:
+1
-1
@@ -327,7 +327,7 @@ class ControlFlowInformationProviderImpl private constructor(
|
||||
private fun markUninitializedVariables() {
|
||||
val varWithUninitializedErrorGenerated = hashSetOf<VariableDescriptor>()
|
||||
val varWithValReassignErrorGenerated = hashSetOf<VariableDescriptor>()
|
||||
val processClassOrObject = subroutine is KtClassOrObject
|
||||
val processClassOrObject = subroutine is KtClassOrObject || subroutine is KtSecondaryConstructor
|
||||
|
||||
val initializers = pseudocodeVariablesData.variableInitializers
|
||||
val declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode, true)
|
||||
|
||||
@@ -673,9 +673,11 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtProperty> PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
|
||||
DiagnosticFactory0<KtProperty> MUST_BE_INITIALIZED = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtProperty> MUST_BE_INITIALIZED_WARNING = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtProperty> MUST_BE_INITIALIZED_OR_BE_FINAL = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtProperty> MUST_BE_INITIALIZED_OR_BE_FINAL_WARNING = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtProperty> MUST_BE_INITIALIZED_OR_BE_ABSTRACT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtProperty> MUST_BE_INITIALIZED_OR_BE_ABSTRACT_WARNING = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtProperty> MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<KtProperty> MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT_WARNING = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE);
|
||||
|
||||
|
||||
+2
@@ -307,9 +307,11 @@ public class DefaultErrorMessages {
|
||||
MAP.put(BACKING_FIELD_IN_INTERFACE, "Property in an interface cannot have a backing field");
|
||||
|
||||
MAP.put(MUST_BE_INITIALIZED, "Property must be initialized");
|
||||
MAP.put(MUST_BE_INITIALIZED_WARNING, "Property must be initialized. This warning will become an error in future releases.");
|
||||
MAP.put(MUST_BE_INITIALIZED_OR_BE_FINAL, "Property must be initialized or be final");
|
||||
MAP.put(MUST_BE_INITIALIZED_OR_BE_FINAL_WARNING, "Property must be initialized or be final. This warning will become an error in future releases.");
|
||||
MAP.put(MUST_BE_INITIALIZED_OR_BE_ABSTRACT, "Property must be initialized or be abstract");
|
||||
MAP.put(MUST_BE_INITIALIZED_OR_BE_ABSTRACT_WARNING, "Property must be initialized or be abstract. This warning will become an error in future releases.");
|
||||
MAP.put(MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT, "Property must be initialized, be final, or be abstract");
|
||||
MAP.put(MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT_WARNING, "Property must be initialized, be final, or be abstract. This warning will become an error in future releases.");
|
||||
|
||||
|
||||
@@ -827,28 +827,40 @@ class DeclarationsChecker(
|
||||
propertyDescriptor.getEffectiveModality(languageVersionSettings) == Modality.OPEN &&
|
||||
!propertyDescriptor.isVar &&
|
||||
trace.bindingContext.get(IS_DEFINITELY_NOT_ASSIGNED_IN_CONSTRUCTOR, propertyDescriptor) == false
|
||||
|
||||
val factory = when {
|
||||
suggestMakingItFinal && suggestMakingItAbstract -> when (isOpenValDeferredInitDeprecationWarning) {
|
||||
true -> MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT_WARNING
|
||||
false -> MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT
|
||||
}
|
||||
suggestMakingItFinal -> when (isOpenValDeferredInitDeprecationWarning) {
|
||||
true -> MUST_BE_INITIALIZED_OR_BE_FINAL_WARNING
|
||||
false -> MUST_BE_INITIALIZED_OR_BE_FINAL
|
||||
}
|
||||
suggestMakingItAbstract -> when (isOpenValDeferredInitDeprecationWarning) {
|
||||
true -> error("Not reachable case. Every \"open val + deferred init\" case that could be made `abstract`, also could be made `final`")
|
||||
false -> MUST_BE_INITIALIZED_OR_BE_ABSTRACT
|
||||
}
|
||||
else -> when (isOpenValDeferredInitDeprecationWarning) {
|
||||
true -> error("Not reachable case. We can always suggest making `open val` property `final`")
|
||||
false -> MUST_BE_INITIALIZED
|
||||
}
|
||||
if (isOpenValDeferredInitDeprecationWarning && !suggestMakingItFinal && suggestMakingItAbstract) {
|
||||
error("Not reachable case. Every \"open val + deferred init\" case that could be made `abstract`, also could be made `final`")
|
||||
}
|
||||
trace.report(factory.on(property))
|
||||
val isMissedMustBeInitializedDeprecationWarning =
|
||||
!languageVersionSettings.supportsFeature(LanguageFeature.ProhibitMissedMustBeInitializedWhenThereIsNoPrimaryConstructor) &&
|
||||
containingDeclaration is ClassDescriptor &&
|
||||
containingDeclaration.constructors.none { it.isPrimary } &&
|
||||
trace.bindingContext.get(IS_DEFINITELY_NOT_ASSIGNED_IN_CONSTRUCTOR, propertyDescriptor) == false
|
||||
val factory = when {
|
||||
suggestMakingItFinal && suggestMakingItAbstract -> MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT
|
||||
suggestMakingItFinal -> MUST_BE_INITIALIZED_OR_BE_FINAL
|
||||
suggestMakingItAbstract -> MUST_BE_INITIALIZED_OR_BE_ABSTRACT
|
||||
else -> MUST_BE_INITIALIZED
|
||||
}
|
||||
if (isOpenValDeferredInitDeprecationWarning && factory == MUST_BE_INITIALIZED) {
|
||||
error("Not reachable case. We can always suggest making `open val` property `final`")
|
||||
}
|
||||
trace.report(
|
||||
when (isMissedMustBeInitializedDeprecationWarning || isOpenValDeferredInitDeprecationWarning) {
|
||||
true -> factory.deprecationWarning
|
||||
false -> factory
|
||||
}.on(property)
|
||||
)
|
||||
}
|
||||
|
||||
private val DiagnosticFactory0<KtProperty>.deprecationWarning: DiagnosticFactory0<KtProperty>
|
||||
get() = when (this) {
|
||||
MUST_BE_INITIALIZED -> MUST_BE_INITIALIZED_WARNING
|
||||
MUST_BE_INITIALIZED_OR_BE_ABSTRACT -> MUST_BE_INITIALIZED_OR_BE_ABSTRACT_WARNING
|
||||
MUST_BE_INITIALIZED_OR_BE_FINAL -> MUST_BE_INITIALIZED_OR_BE_FINAL_WARNING
|
||||
MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT -> MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT_WARNING
|
||||
else -> error("Only MUST_BE_INITIALIZED is supported")
|
||||
}
|
||||
|
||||
private fun noExplicitTypeOrGetterType(property: KtProperty) =
|
||||
property.typeReference == null
|
||||
&& (property.getter == null || (property.getter!!.hasBlockBody() && property.getter!!.returnTypeReference == null))
|
||||
|
||||
Reference in New Issue
Block a user