From a695e21e440c8000fce261d38df517415f3c7281 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Tue, 27 Nov 2018 16:06:14 +0300 Subject: [PATCH] Introduce IrLazyProperty --- .../ir/declarations/lazy/IrLazyProperty.kt | 97 +++++++++++++++++++ .../ir/util/DeclarationStubGenerator.kt | 27 ++---- .../ir/util/ExternalDependenciesGenerator.kt | 2 +- .../jetbrains/kotlin/ir/util/SymbolTable.kt | 5 + 4 files changed, 111 insertions(+), 20 deletions(-) create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt new file mode 100644 index 00000000000..63d8feb5ed0 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt @@ -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 accept(visitor: IrElementVisitor, data: D): R = + visitor.visitProperty(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + backingField?.accept(visitor, data) + getter?.accept(visitor, data) + setter?.accept(visitor, data) + } + + override fun transformChildren(transformer: IrElementTransformer, 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 } + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt index 18ae40d9f31..f5281ccc2f5 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt @@ -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( diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt index c7cd2f8fb79..3e4cd8c13c4 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt @@ -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) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt index 0655eb0b415..138d9b0851b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt @@ -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 get() = fieldSymbolTable.unboundSymbols + val propertyTable = HashMap() + override fun referenceProperty(descriptor: PropertyDescriptor, generate: () -> IrProperty): IrProperty = + propertyTable.getOrPut(descriptor, generate) + fun declareSimpleFunction( startOffset: Int, endOffset: Int,