Introduce IrLazyProperty

This commit is contained in:
Georgy Bronnikov
2018-11-27 16:06:14 +03:00
parent f4a189fe82
commit a695e21e44
4 changed files with 111 additions and 20 deletions
@@ -0,0 +1,97 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.ir.declarations.lazy
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.hasBackingField
class IrLazyProperty(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
override val descriptor: PropertyDescriptor,
override val name: Name,
override val visibility: Visibility,
override val modality: Modality,
override val isVar: Boolean,
override val isConst: Boolean,
override val isLateinit: Boolean,
override val isDelegated: Boolean,
override val isExternal: Boolean,
private val stubGenerator: DeclarationStubGenerator,
typeTranslator: TypeTranslator,
private val bindingContext: BindingContext? = null
) :
IrLazyDeclarationBase(startOffset, endOffset, origin, stubGenerator, typeTranslator),
IrProperty {
constructor(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: PropertyDescriptor,
stubGenerator: DeclarationStubGenerator,
typeTranslator: TypeTranslator,
bindingContext: BindingContext?
) : this(
startOffset, endOffset, origin, descriptor,
descriptor.name, descriptor.visibility, descriptor.modality,
isVar = descriptor.isVar,
isConst = descriptor.isConst,
isLateinit = descriptor.isLateInit,
isDelegated = descriptor.isDelegated,
isExternal = descriptor.isEffectivelyExternal(),
stubGenerator = stubGenerator,
typeTranslator = typeTranslator,
bindingContext = bindingContext
)
override var backingField: IrField? by lazyVar {
if (descriptor.hasBackingField(bindingContext)) {
stubGenerator.generateFieldStub(descriptor, bindingContext).apply {
correspondingProperty = this@IrLazyProperty
}
} else null
}
override var getter: IrSimpleFunction? by lazyVar {
descriptor.getter?.let { stubGenerator.generateFunctionStub(it, createPropertyIfNeeded = false) }?.apply {
correspondingProperty = this@IrLazyProperty
}
}
override var setter: IrSimpleFunction? by lazyVar {
descriptor.setter?.let { stubGenerator.generateFunctionStub(it, createPropertyIfNeeded = false) }?.apply {
correspondingProperty = this@IrLazyProperty
}
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
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 }
}
}
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.declarations.lazy.*
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
@@ -83,25 +82,14 @@ class DeclarationStubGenerator(
internal fun generatePropertyStub(
descriptor: PropertyDescriptor,
bindingContext: BindingContext? = null
): IrProperty =
IrPropertyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irProperty ->
if (descriptor.hasBackingField(bindingContext)) {
irProperty.backingField = generateFieldStub(descriptor)
}
): IrProperty = symbolTable.referenceProperty(descriptor) {
IrLazyProperty(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor,
this, typeTranslator, bindingContext
)
}
irProperty.getter = descriptor.getter?.let { generateFunctionStub(it, createPropertyIfNeeded = false) }?.apply {
correspondingProperty = irProperty
}
irProperty.setter = descriptor.setter?.let { generateFunctionStub(it, createPropertyIfNeeded = false) }?.apply {
correspondingProperty = irProperty
}
// Do we ever generate stubs for file-level properties?
(descriptor.containingDeclaration as? ClassDescriptor)?.let {
irProperty.parent = generateClassStub(it)
}
}
private fun generateFieldStub(descriptor: PropertyDescriptor): IrField {
fun generateFieldStub(descriptor: PropertyDescriptor, bindingContext: BindingContext? = null): IrField {
val referenced = symbolTable.referenceField(descriptor)
if (referenced.isBound) {
return referenced.owner
@@ -119,6 +107,7 @@ class DeclarationStubGenerator(
descriptor.original,
descriptor.type.toIrType()
).apply {
correspondingProperty = generatePropertyStub(descriptor, bindingContext)
initializer = descriptor.compileTimeInitializer?.let {
IrExpressionBodyImpl(
constantValueGenerator.generateConstantValueAsExpression(
@@ -49,7 +49,7 @@ class ExternalDependenciesGenerator(
stubGenerator.generateEnumEntryStub(it.descriptor)
}
ArrayList(symbolTable.unboundFields).forEach {
stubGenerator.generatePropertyStub(it.descriptor, bindingContext)
stubGenerator.generateFieldStub(it.descriptor, bindingContext)
}
ArrayList(symbolTable.unboundSimpleFunctions).forEach {
stubGenerator.generateFunctionStub(it.descriptor)
@@ -39,6 +39,7 @@ interface ReferenceSymbolTable {
fun referenceEnumEntry(descriptor: ClassDescriptor): IrEnumEntrySymbol
fun referenceField(descriptor: PropertyDescriptor): IrFieldSymbol
fun referenceProperty(descriptor: PropertyDescriptor, generate: () -> IrProperty): IrProperty
fun referenceSimpleFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol
fun referenceDeclaredFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol
@@ -296,6 +297,10 @@ open class SymbolTable : ReferenceSymbolTable {
val unboundFields: Set<IrFieldSymbol> get() = fieldSymbolTable.unboundSymbols
val propertyTable = HashMap<PropertyDescriptor, IrProperty>()
override fun referenceProperty(descriptor: PropertyDescriptor, generate: () -> IrProperty): IrProperty =
propertyTable.getOrPut(descriptor, generate)
fun declareSimpleFunction(
startOffset: Int,
endOffset: Int,