[FIR2IR] Introduce lazy properties
This commit is contained in:
+26
-4
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyConstructor
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
@@ -494,7 +495,7 @@ class Fir2IrDeclarationStorage(
|
||||
return symbolTable.declareSimpleFunction(signature, { Fir2IrSimpleFunctionSymbol(signature, containerSource) }, factory)
|
||||
}
|
||||
|
||||
private fun createIrPropertyAccessor(
|
||||
internal fun createIrPropertyAccessor(
|
||||
propertyAccessor: FirPropertyAccessor?,
|
||||
property: FirProperty,
|
||||
correspondingProperty: IrProperty,
|
||||
@@ -560,7 +561,7 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrProperty.createBackingField(
|
||||
internal fun IrProperty.createBackingField(
|
||||
property: FirProperty,
|
||||
origin: IrDeclarationOrigin,
|
||||
descriptor: PropertyDescriptor,
|
||||
@@ -589,7 +590,7 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
private val FirProperty.fieldVisibility: Visibility
|
||||
internal val FirProperty.fieldVisibility: Visibility
|
||||
get() = when {
|
||||
isLateInit -> setter?.visibility ?: status.visibility
|
||||
isConst -> status.visibility
|
||||
@@ -908,14 +909,35 @@ class Fir2IrDeclarationStorage(
|
||||
propertyCache[fir]?.let { return it.symbol }
|
||||
val signature = signatureComposer.composeSignature(fir)
|
||||
val irParent = findIrParent(fir)
|
||||
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
|
||||
if (signature != null) {
|
||||
symbolTable.referencePropertyIfAny(signature)?.let { irPropertySymbol ->
|
||||
val irProperty = irPropertySymbol.owner
|
||||
propertyCache[fir] = irProperty
|
||||
return irPropertySymbol
|
||||
}
|
||||
// TODO: package fragment members (?)
|
||||
if (irParent is Fir2IrLazyClass) {
|
||||
if (parentOrigin == IrDeclarationOrigin.DEFINED) {
|
||||
throw AssertionError()
|
||||
}
|
||||
val symbol = Fir2IrPropertySymbol(signature, fir.containerSource)
|
||||
val irProperty = fir.convertWithOffsets { startOffset, endOffset ->
|
||||
symbolTable.declareProperty(signature, { symbol }) {
|
||||
val isFakeOverride =
|
||||
firVariableSymbol is FirPropertySymbol && firVariableSymbol.isFakeOverride &&
|
||||
firVariableSymbol.callableId != firVariableSymbol.overriddenSymbol?.callableId
|
||||
Fir2IrLazyProperty(
|
||||
components, startOffset, endOffset, parentOrigin, fir, symbol, isFakeOverride
|
||||
).apply {
|
||||
parent = irParent
|
||||
}
|
||||
}
|
||||
}
|
||||
propertyCache[fir] = irProperty
|
||||
return symbol
|
||||
}
|
||||
}
|
||||
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
|
||||
createIrProperty(fir, irParent, origin = parentOrigin).apply {
|
||||
setAndModifyParent(irParent)
|
||||
}.symbol
|
||||
|
||||
@@ -145,8 +145,7 @@ class Fir2IrLazyClass(
|
||||
processedNames += declaration.name
|
||||
scope.processPropertiesByName(declaration.name) {
|
||||
if (it is FirPropertySymbol) {
|
||||
// TODO: replace with getIrFieldOrPropertySymbol(it).owner with lazy property generation
|
||||
result += declarationStorage.createIrProperty(it.fir, irParent = this, origin = origin)
|
||||
result += declarationStorage.getIrPropertyOrFieldSymbol(it).owner as IrProperty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.lazy
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
|
||||
import org.jetbrains.kotlin.fir.backend.toIrConst
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class Fir2IrLazyProperty(
|
||||
components: Fir2IrComponents,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
fir: FirProperty,
|
||||
symbol: Fir2IrPropertySymbol,
|
||||
override val isFakeOverride: Boolean
|
||||
) : AbstractFir2IrLazyDeclaration<FirProperty, IrProperty>(
|
||||
components, startOffset, endOffset, origin, fir, symbol
|
||||
), IrProperty {
|
||||
init {
|
||||
symbol.bind(this)
|
||||
classifierStorage.preCacheTypeParameters(fir)
|
||||
typeParameters = emptyList()
|
||||
}
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
override val descriptor: PropertyDescriptor
|
||||
get() = super.descriptor as PropertyDescriptor
|
||||
|
||||
override val symbol: Fir2IrPropertySymbol
|
||||
get() = super.symbol as Fir2IrPropertySymbol
|
||||
|
||||
override val isVar: Boolean
|
||||
get() = fir.isVar
|
||||
|
||||
override val isConst: Boolean
|
||||
get() = fir.isConst
|
||||
|
||||
override val isLateinit: Boolean
|
||||
get() = fir.isLateInit
|
||||
|
||||
override val isDelegated: Boolean
|
||||
get() = fir.delegate != null
|
||||
|
||||
override val isExternal: Boolean
|
||||
get() = fir.isExternal
|
||||
|
||||
override val isExpect: Boolean
|
||||
get() = fir.isExpect
|
||||
|
||||
override val name: Name
|
||||
get() = fir.name
|
||||
|
||||
override var visibility: Visibility
|
||||
get() = fir.visibility
|
||||
set(_) {
|
||||
throw AssertionError("Mutating Fir2Ir lazy elements is not possible")
|
||||
}
|
||||
|
||||
override val modality: Modality
|
||||
get() = fir.modality!!
|
||||
|
||||
private val type: IrType by lazy {
|
||||
with(typeConverter) { fir.returnTypeRef.toIrType() }
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
override var backingField: IrField? by lazyVar {
|
||||
// TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself
|
||||
val parent = parent
|
||||
when {
|
||||
!fir.isConst && (fir.modality == Modality.ABSTRACT || parent is IrClass && parent.isInterface) -> {
|
||||
null
|
||||
}
|
||||
fir.initializer != null || fir.getter is FirDefaultPropertyGetter || fir.isVar && fir.setter is FirDefaultPropertySetter -> {
|
||||
with(declarationStorage) {
|
||||
createBackingField(
|
||||
fir, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, descriptor,
|
||||
fir.fieldVisibility, fir.name, fir.isVal, fir.initializer,
|
||||
type
|
||||
).also { field ->
|
||||
val initializer = fir.initializer
|
||||
if (initializer is FirConstExpression<*>) {
|
||||
// TODO: Normally we shouldn't have error type here
|
||||
val constType = with(typeConverter) { initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type }
|
||||
field.initializer = IrExpressionBodyImpl(initializer.toIrConst(constType))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fir.delegate != null -> {
|
||||
with(declarationStorage) {
|
||||
createBackingField(
|
||||
fir, IrDeclarationOrigin.PROPERTY_DELEGATE, descriptor,
|
||||
fir.fieldVisibility, Name.identifier("${fir.name}\$delegate"), true, fir.delegate
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}?.apply {
|
||||
this.parent = this@Fir2IrLazyProperty.parent
|
||||
}
|
||||
}
|
||||
|
||||
override var getter: IrSimpleFunction? by lazyVar {
|
||||
declarationStorage.createIrPropertyAccessor(
|
||||
fir.getter, fir, this, type, parent, parent as? IrClass, false,
|
||||
when {
|
||||
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
|
||||
fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
|
||||
fir.getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
|
||||
else -> origin
|
||||
},
|
||||
startOffset, endOffset
|
||||
)
|
||||
}
|
||||
|
||||
override var setter: IrSimpleFunction? by lazyVar {
|
||||
if (!fir.isVar) return@lazyVar null
|
||||
declarationStorage.createIrPropertyAccessor(
|
||||
fir.setter, fir, this, type, parent, parent as? IrClass, true,
|
||||
when {
|
||||
fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
|
||||
fir.setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
|
||||
else -> origin
|
||||
},
|
||||
startOffset, endOffset
|
||||
)
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||
return visitor.visitProperty(this, data)
|
||||
}
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
backingField?.accept(visitor, data)
|
||||
getter?.accept(visitor, data)
|
||||
setter?.accept(visitor, data)
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
backingField = backingField?.transform(transformer, data) as? IrField
|
||||
getter = getter?.run { transform(transformer, data) as IrSimpleFunction }
|
||||
setter = setter?.run { transform(transformer, data) as IrSimpleFunction }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user