[FE] Replace some MUST_BE_INITIALIZED messages with MUST_BE_INITIALIZED_OR_BE_FINAL
From user point of view it's an improvement in compilation message. From technical point of view it's an introduction of new compilation diagnostic. Review: https://jetbrains.team/p/kt/reviews/9967 I'm going to deprecate `open val` case in the next few commits KT-57553. But it is always possible to suggest using `final` for `open val` case.
This commit is contained in:
+3
@@ -1009,7 +1009,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val PROPERTY_WITH_NO_TYPE_NO_INITIALIZER by error<KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
|
||||
val MUST_BE_INITIALIZED by error<KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
val MUST_BE_INITIALIZED_OR_BE_FINAL by error<KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
val MUST_BE_INITIALIZED_OR_BE_ABSTRACT by error<KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
val MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT by error<KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
|
||||
val EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT by error<KtProperty>(PositioningStrategy.DECLARATION_SIGNATURE)
|
||||
val UNNECESSARY_LATEINIT by warning<KtProperty>(PositioningStrategy.LATEINIT_MODIFIER)
|
||||
|
||||
|
||||
@@ -533,7 +533,9 @@ object FirErrors {
|
||||
val PROPERTY_INITIALIZER_IN_INTERFACE by error0<KtExpression>()
|
||||
val PROPERTY_WITH_NO_TYPE_NO_INITIALIZER by error0<KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val MUST_BE_INITIALIZED by error0<KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val MUST_BE_INITIALIZED_OR_BE_FINAL by error0<KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val MUST_BE_INITIALIZED_OR_BE_ABSTRACT by error0<KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT by error0<KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT by error0<KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val UNNECESSARY_LATEINIT by warning0<KtProperty>(SourceElementPositioningStrategies.LATEINIT_MODIFIER)
|
||||
val BACKING_FIELD_IN_INTERFACE by error0<KtProperty>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
|
||||
+25
-5
@@ -153,11 +153,7 @@ internal fun checkPropertyInitializer(
|
||||
if (property.receiverParameter != null && !property.hasAnyAccessorImplementation) {
|
||||
reporter.reportOn(propertySource, FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT, context)
|
||||
} else if (reachable) { // TODO: can be suppressed not to report diagnostics about no body
|
||||
if (containingClass == null || property.hasAnyAccessorImplementation) {
|
||||
reporter.reportOn(propertySource, FirErrors.MUST_BE_INITIALIZED, context)
|
||||
} else {
|
||||
reporter.reportOn(propertySource, FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT, context)
|
||||
}
|
||||
reportMustBeInitialized(property, isDefinitelyAssignedInConstructor, containingClass, propertySource, reporter, context)
|
||||
}
|
||||
}
|
||||
if (property.isLateInit) {
|
||||
@@ -175,6 +171,30 @@ internal fun checkPropertyInitializer(
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportMustBeInitialized(
|
||||
property: FirProperty,
|
||||
isDefinitelyAssignedInConstructor: Boolean,
|
||||
containingClass: FirClass?,
|
||||
propertySource: KtSourceElement,
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext,
|
||||
) {
|
||||
check(!property.isAbstract) { "${::reportMustBeInitialized.name} isn't called for abstract properties" }
|
||||
val suggestMakingItFinal = containingClass != null &&
|
||||
!property.hasSetterAccessorImplementation &&
|
||||
property.getEffectiveModality(containingClass, context.languageVersionSettings) != Modality.FINAL &&
|
||||
isDefinitelyAssignedInConstructor
|
||||
val suggestMakingItAbstract = containingClass != null && !property.hasAnyAccessorImplementation
|
||||
|
||||
val factory = when {
|
||||
suggestMakingItFinal && suggestMakingItAbstract -> FirErrors.MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT
|
||||
suggestMakingItFinal -> FirErrors.MUST_BE_INITIALIZED_OR_BE_FINAL
|
||||
suggestMakingItAbstract -> FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT
|
||||
else -> FirErrors.MUST_BE_INITIALIZED
|
||||
}
|
||||
reporter.reportOn(propertySource, factory, context)
|
||||
}
|
||||
|
||||
private val FirPropertyAccessor?.hasImplementation: Boolean
|
||||
get() = (this !is FirDefaultPropertyAccessor && this?.hasBody == true)
|
||||
private val FirProperty.hasSetterAccessorImplementation: Boolean
|
||||
|
||||
+5
@@ -337,6 +337,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_P
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED_OR_BE_FINAL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_ARGUMENTS_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_PARAMETER_NOT_FOUND
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAME_FOR_AMBIGUOUS_PARAMETER
|
||||
@@ -1629,7 +1631,10 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
map.put(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, "Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly")
|
||||
|
||||
map.put(MUST_BE_INITIALIZED, "Property must be initialized")
|
||||
map.put(MUST_BE_INITIALIZED_OR_BE_FINAL, "Property must be initialized or be final")
|
||||
map.put(MUST_BE_INITIALIZED_OR_BE_ABSTRACT, "Property must be initialized or be abstract")
|
||||
map.put(MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT, "Property must be initialized, be final, or be abstract");
|
||||
|
||||
map.put(EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT, "Extension property must have accessors or be abstract")
|
||||
map.put(UNNECESSARY_LATEINIT, "Lateinit is unnecessary: definitely initialized in constructors")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user