[FIR] Make default accessors always present
This commit is contained in:
committed by
TeamCityServer
parent
cc0d63117a
commit
30e52186eb
+7
-2
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.hasExplicitBackingField
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
@@ -45,12 +47,15 @@ object FirPropertyFieldTypeChecker : FirPropertyChecker() {
|
||||
}
|
||||
}
|
||||
|
||||
private val FirPropertyAccessor?.isNotExplicit
|
||||
get() = this == null || this is FirDefaultPropertyAccessor
|
||||
|
||||
private fun checkAsPropertyNotSubtype(
|
||||
property: FirProperty,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
if (property.isVar && property.setter == null) {
|
||||
if (property.isVar && property.setter.isNotExplicit) {
|
||||
reporter.reportOn(property.source, FirErrors.PROPERTY_MUST_HAVE_SETTER, context)
|
||||
}
|
||||
}
|
||||
@@ -60,7 +65,7 @@ object FirPropertyFieldTypeChecker : FirPropertyChecker() {
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
if (property.getter == null) {
|
||||
if (property.getter.isNotExplicit) {
|
||||
reporter.reportOn(property.source, FirErrors.PROPERTY_MUST_HAVE_GETTER, context)
|
||||
}
|
||||
}
|
||||
|
||||
+8
-18
@@ -1132,24 +1132,19 @@ class DeclarationsConverter(
|
||||
isExternal = modifiers.hasExternal()
|
||||
}
|
||||
|
||||
val hasExplicitBackingField = backingField !is FirDefaultPropertyBackingField
|
||||
val convertedAccessors = accessors.map {
|
||||
convertGetterOrSetter(it, returnType, propertyVisibility, symbol, modifiers, hasExplicitBackingField)
|
||||
convertGetterOrSetter(it, returnType, propertyVisibility, symbol, modifiers)
|
||||
}
|
||||
this.getter = convertedAccessors.find { it.isGetter }
|
||||
?: if (!hasExplicitBackingField) {
|
||||
FirDefaultPropertyGetter(
|
||||
property.toFirSourceElement(FirFakeSourceElementKind.DefaultAccessor), moduleData, FirDeclarationOrigin.Source, returnType, propertyVisibility, symbol,
|
||||
).also {
|
||||
it.status = defaultAccessorStatus()
|
||||
it.initContainingClassAttr()
|
||||
}
|
||||
} else {
|
||||
null
|
||||
?: FirDefaultPropertyGetter(
|
||||
property.toFirSourceElement(FirFakeSourceElementKind.DefaultAccessor), moduleData, FirDeclarationOrigin.Source, returnType, propertyVisibility, symbol,
|
||||
).also {
|
||||
it.status = defaultAccessorStatus()
|
||||
it.initContainingClassAttr()
|
||||
}
|
||||
// NOTE: We still need the setter even for a val property so we can report errors (e.g., VAL_WITH_SETTER).
|
||||
this.setter = convertedAccessors.find { it.isSetter }
|
||||
?: if (isVar && !hasExplicitBackingField) {
|
||||
?: if (isVar) {
|
||||
FirDefaultPropertySetter(
|
||||
property.toFirSourceElement(FirFakeSourceElementKind.DefaultAccessor),
|
||||
moduleData,
|
||||
@@ -1259,7 +1254,6 @@ class DeclarationsConverter(
|
||||
propertyVisibility: Visibility,
|
||||
propertySymbol: FirPropertySymbol,
|
||||
propertyModifiers: Modifier,
|
||||
hasBackingField: Boolean,
|
||||
): FirPropertyAccessor {
|
||||
var modifiers = Modifier()
|
||||
var isGetter = true
|
||||
@@ -1298,11 +1292,7 @@ class DeclarationsConverter(
|
||||
isExternal = propertyModifiers.hasExternal() || modifiers.hasExternal()
|
||||
}
|
||||
val sourceElement = getterOrSetter.toFirSourceElement()
|
||||
// If an explicit backing field is present,
|
||||
// the default accessors might not be compatible
|
||||
// with it. We should check the types first, and
|
||||
// only then see if we can create the default accessors.
|
||||
if (block == null && expression == null && !hasBackingField) {
|
||||
if (block == null && expression == null) {
|
||||
return FirDefaultPropertyAccessor
|
||||
.createGetterOrSetter(
|
||||
sourceElement,
|
||||
|
||||
@@ -368,7 +368,6 @@ open class RawFirBuilder(
|
||||
propertyTypeRef: FirTypeRef,
|
||||
propertySymbol: FirPropertySymbol,
|
||||
isGetter: Boolean,
|
||||
hasExplicitBackingField: Boolean,
|
||||
): FirPropertyAccessor? {
|
||||
val accessorVisibility =
|
||||
if (this?.visibility != null && this.visibility != Visibilities.Unknown) this.visibility else property.visibility
|
||||
@@ -425,11 +424,7 @@ open class RawFirBuilder(
|
||||
this@RawFirBuilder.context.firFunctionTargets.removeLast()
|
||||
}
|
||||
}
|
||||
// If an explicit backing field is present,
|
||||
// the default accessors might not be compatible
|
||||
// with it. We should check the types first, and
|
||||
// only then see if we can create the default accessors.
|
||||
!hasExplicitBackingField && (isGetter || property.isVar) -> {
|
||||
isGetter || property.isVar -> {
|
||||
// Default getter for val/var properties, and default setter for var properties.
|
||||
val propertySource =
|
||||
this?.toFirSourceElement() ?: property.toFirPsiSourceElement(FirFakeSourceElementKind.DefaultAccessor)
|
||||
@@ -1531,20 +1526,17 @@ open class RawFirBuilder(
|
||||
propertyType,
|
||||
)
|
||||
|
||||
val hasExplicitBackingField = backingField !is FirDefaultPropertyBackingField
|
||||
getter = this@toFirProperty.getter.toFirPropertyAccessor(
|
||||
this@toFirProperty,
|
||||
propertyType,
|
||||
propertySymbol = symbol,
|
||||
isGetter = true,
|
||||
hasExplicitBackingField,
|
||||
isGetter = true
|
||||
)
|
||||
setter = this@toFirProperty.setter.toFirPropertyAccessor(
|
||||
this@toFirProperty,
|
||||
propertyType,
|
||||
propertySymbol = symbol,
|
||||
isGetter = false,
|
||||
hasExplicitBackingField,
|
||||
isGetter = false
|
||||
)
|
||||
|
||||
status = FirDeclarationStatusImpl(visibility, modality).apply {
|
||||
|
||||
-48
@@ -151,10 +151,6 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
||||
}
|
||||
property.transformBackingField(transformer, withExpectedType(property.returnTypeRef))
|
||||
}
|
||||
// In case an explicit backing field declaration
|
||||
// is present, and the default accessors haven't
|
||||
// been generated earlier.
|
||||
property.generateMissingDefaultAccessors()
|
||||
val delegate = property.delegate
|
||||
if (delegate != null) {
|
||||
transformPropertyAccessorsWithDelegate(property, delegate)
|
||||
@@ -185,50 +181,6 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirProperty.generateMissingDefaultAccessors() {
|
||||
val fieldDeclaration = backingField ?: return
|
||||
|
||||
if (
|
||||
!this.hasExplicitBackingField ||
|
||||
fieldDeclaration.returnTypeRef !is FirResolvedTypeRef
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
val typeCheckerContext = session.typeContext.newBaseTypeCheckerContext(
|
||||
errorTypesEqualToAnything = false,
|
||||
stubTypesEqualToAnything = false
|
||||
)
|
||||
|
||||
if (getter == null && fieldDeclaration.isSubtypeOf(this, typeCheckerContext)) {
|
||||
this.replaceGetter(
|
||||
FirDefaultPropertyGetter(
|
||||
null,
|
||||
this.moduleData,
|
||||
FirDeclarationOrigin.Source,
|
||||
this.returnTypeRef,
|
||||
this.visibility,
|
||||
this.symbol,
|
||||
).also {
|
||||
it.status = this.getDefaultAccessorStatus()
|
||||
}
|
||||
)
|
||||
} else if (this.isVar && this.isSubtypeOf(fieldDeclaration, typeCheckerContext)) {
|
||||
this.replaceSetter(
|
||||
FirDefaultPropertySetter(
|
||||
null,
|
||||
this.moduleData,
|
||||
FirDeclarationOrigin.Source,
|
||||
this.returnTypeRef,
|
||||
this.visibility,
|
||||
this.symbol,
|
||||
).also {
|
||||
it.status = this.getDefaultAccessorStatus()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun FirProperty.getDefaultAccessorStatus(): FirDeclarationStatus {
|
||||
// Downward propagation of `inline` and `external` modifiers (from property to its accessors)
|
||||
return FirDeclarationStatusImpl(this.visibility, this.modality).apply {
|
||||
|
||||
Reference in New Issue
Block a user