Local delegated properties.

This commit is contained in:
Dmitry Petrov
2016-09-02 10:18:06 +03:00
committed by Dmitry Petrov
parent e42116bb6a
commit 42988383e0
22 changed files with 490 additions and 201 deletions
@@ -34,12 +34,10 @@ interface IrClass : IrDeclaration {
fun IrClass.getInstanceInitializerMembers() =
members.filter {
when (it) {
is IrDelegate ->
true
is IrAnonymousInitializer ->
true
is IrSimpleProperty ->
it.valueInitializer != null
it.initializer != null
is IrDelegatedProperty ->
true
else -> false
@@ -29,16 +29,16 @@ interface IrDeclaration : IrStatement {
enum class IrDeclarationKind {
MODULE,
FILE,
CLASS,
ENUM_ENTRY,
FUNCTION,
PROPERTY_GETTER,
PROPERTY_SETTER,
CONSTRUCTOR,
PROPERTY,
PROPERTY_ACCESSOR,
VARIABLE,
DELEGATE,
CLASS,
LOCAL_PROPERTY,
LOCAL_PROPERTY_ACCESSOR,
TYPEALIAS,
ENUM_ENTRY,
ANONYMOUS_INITIALIZER,
DUMMY;
}
@@ -1,79 +0,0 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.ir.declarations
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
interface IrDelegate : IrDeclaration {
override val descriptor: VariableDescriptor
var initializer: IrExpressionBody
override val declarationKind: IrDeclarationKind
get() = IrDeclarationKind.DELEGATE
}
class IrDelegateImpl(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
override val descriptor: VariableDescriptor
) : IrDeclarationBase(startOffset, endOffset, origin), IrDelegate {
constructor(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: VariableDescriptor,
initializer: IrExpressionBody
) : this(startOffset, endOffset, origin, descriptor) {
this.initializer = initializer
}
private var initializerImpl: IrExpressionBody? = null
override var initializer: IrExpressionBody
get() = initializerImpl!!
set(value) {
value.assertDetached()
initializerImpl?.detach()
initializerImpl = value
value.setTreeLocation(this, INITIALIZER_SLOT)
}
override fun getChild(slot: Int): IrElement? =
when (slot) {
INITIALIZER_SLOT -> initializer
else -> null
}
override fun replaceChild(slot: Int, newChild: IrElement) {
when (slot) {
INITIALIZER_SLOT -> initializer = newChild.assertCast()
else -> throwNoSuchSlot(slot)
}
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
return visitor.visitDelegate(this, data)
}
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
initializer.accept(visitor, data)
}
}
@@ -26,7 +26,7 @@ import java.util.*
interface IrGeneralFunction : IrDeclaration {
override val descriptor: FunctionDescriptor
val body: IrBody?
var body: IrBody?
override val declarationKind: IrDeclarationKind
get() = IrDeclarationKind.FUNCTION
@@ -0,0 +1,131 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.ir.declarations
import org.jetbrains.kotlin.descriptors.VariableAccessorDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
interface IrLocalDelegatedProperty : IrDeclaration {
override val descriptor: VariableDescriptorWithAccessors
var delegate: IrVariable
var getter: IrLocalPropertyAccessor
var setter: IrLocalPropertyAccessor?
override val declarationKind: IrDeclarationKind
get() = IrDeclarationKind.LOCAL_PROPERTY
}
interface IrLocalPropertyAccessor : IrGeneralFunction {
override val descriptor: VariableAccessorDescriptor
override val declarationKind: IrDeclarationKind
get() = IrDeclarationKind.LOCAL_PROPERTY_ACCESSOR
}
class IrLocalDelegatedPropertyImpl(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
override val descriptor: VariableDescriptorWithAccessors
) : IrDeclarationBase(startOffset, endOffset, origin), IrLocalDelegatedProperty {
constructor(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: VariableDescriptorWithAccessors,
delegate: IrVariable
) : this(startOffset, endOffset, origin, descriptor) {
this.delegate = delegate
}
private var delegateImpl: IrVariable? = null
override var delegate: IrVariable
get() = delegateImpl!!
set(value) {
value.assertDetached()
delegateImpl?.detach()
delegateImpl = value
value.setTreeLocation(this, DELEGATE_SLOT)
}
private var getterImpl: IrLocalPropertyAccessor? = null
override var getter: IrLocalPropertyAccessor
get() = getterImpl!!
set(value) {
value.assertDetached()
getterImpl?.detach()
getterImpl = value
value.setTreeLocation(this, PROPERTY_GETTER_SLOT)
}
override var setter: IrLocalPropertyAccessor? = null
set(value) {
value?.assertDetached()
field?.detach()
field = value
value?.setTreeLocation(this, PROPERTY_SETTER_SLOT)
}
override fun getChild(slot: Int): IrElement? =
when (slot) {
DELEGATE_SLOT -> delegate
PROPERTY_GETTER_SLOT -> getter
PROPERTY_SETTER_SLOT -> setter
else -> null
}
override fun replaceChild(slot: Int, newChild: IrElement) {
when (slot) {
DELEGATE_SLOT -> delegate = newChild.assertCast()
PROPERTY_GETTER_SLOT -> getter = newChild.assertCast()
PROPERTY_SETTER_SLOT -> setter = newChild.assertCast()
}
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitLocalDelegatedProperty(this, data)
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
delegate.accept(visitor, data)
getter.accept(visitor, data)
setter?.accept(visitor, data)
}
}
class IrLocalPropertyAccessorImpl(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
override val descriptor: VariableAccessorDescriptor
) : IrGeneralFunctionBase(startOffset, endOffset, origin), IrLocalPropertyAccessor {
constructor(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: VariableAccessorDescriptor,
body: IrBody
) : this(startOffset, endOffset, origin, descriptor) {
this.body = body
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
return visitor.visitLocalPropertyAccessor(this, data)
}
}
@@ -31,11 +31,11 @@ interface IrProperty : IrDeclaration {
}
interface IrSimpleProperty : IrProperty {
var valueInitializer: IrBody?
var initializer: IrBody?
}
interface IrDelegatedProperty : IrProperty {
var delegate: IrDelegate
var delegate: IrSimpleProperty
}
abstract class IrPropertyBase(
@@ -83,7 +83,7 @@ class IrSimplePropertyImpl(
descriptor: PropertyDescriptor,
valueInitializer: IrBody? = null
) : IrPropertyBase(startOffset, endOffset, origin, descriptor), IrSimpleProperty {
override var valueInitializer: IrBody? = valueInitializer
override var initializer: IrBody? = valueInitializer
set(value) {
value?.assertDetached()
field?.detach()
@@ -93,13 +93,13 @@ class IrSimplePropertyImpl(
override fun getChild(slot: Int): IrElement? =
when (slot) {
INITIALIZER_SLOT -> valueInitializer
INITIALIZER_SLOT -> initializer
else -> super.getChild(slot)
}
override fun replaceChild(slot: Int, newChild: IrElement) {
when (slot) {
INITIALIZER_SLOT -> valueInitializer = newChild.assertCast()
INITIALIZER_SLOT -> initializer = newChild.assertCast()
else -> super.replaceChild(slot, newChild)
}
}
@@ -108,7 +108,7 @@ class IrSimplePropertyImpl(
visitor.visitSimpleProperty(this, data)
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
valueInitializer?.accept(visitor, data)
initializer?.accept(visitor, data)
getter?.accept(visitor, data)
setter?.accept(visitor, data)
}
@@ -125,13 +125,13 @@ class IrDelegatedPropertyImpl(
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: PropertyDescriptor,
delegate: IrDelegate
delegate: IrSimpleProperty
) : this(startOffset, endOffset, origin, descriptor) {
this.delegate = delegate
}
private var delegateImpl: IrDelegate? = null
override var delegate: IrDelegate
private var delegateImpl: IrSimpleProperty? = null
override var delegate: IrSimpleProperty
get() = delegateImpl!!
set(value) {
value.assertDetached()
@@ -24,20 +24,19 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
interface IrPropertyAccessor : IrGeneralFunction {
override val descriptor: PropertyAccessorDescriptor
override val declarationKind: IrDeclarationKind
get() = IrDeclarationKind.PROPERTY_ACCESSOR
}
interface IrPropertyGetter : IrPropertyAccessor {
override val descriptor: PropertyGetterDescriptor
override val declarationKind: IrDeclarationKind
get() = IrDeclarationKind.PROPERTY_GETTER
}
interface IrPropertySetter : IrPropertyAccessor {
override val descriptor: PropertySetterDescriptor
override val declarationKind: IrDeclarationKind
get() = IrDeclarationKind.PROPERTY_SETTER
}
abstract class IrPropertyAccessorBase(
@@ -18,19 +18,28 @@ package org.jetbrains.kotlin.ir.descriptors
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.VariableDescriptorImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
import java.lang.UnsupportedOperationException
interface IrDelegateDescriptor : VariableDescriptor
interface IrDelegateDescriptor : PropertyDescriptor
interface IrPropertyDelegateDescriptor : IrDelegateDescriptor {
val correspondingProperty: PropertyDescriptor
val kPropertyType: KotlinType
}
interface IrLocalDelegateDescriptor : VariableDescriptor
interface IrLocalDelegatedPropertyDelegateDescriptor : IrLocalDelegateDescriptor {
val correspondingLocalProperty: VariableDescriptorWithAccessors
val kPropertyType: KotlinType
}
interface IrImplementingDelegateDescriptor : IrDelegateDescriptor {
val correspondingSuperType: KotlinType
}
@@ -39,12 +48,32 @@ abstract class IrDelegateDescriptorBase(
containingDeclaration: DeclarationDescriptor,
name: Name,
delegateType: KotlinType
) : VariableDescriptorImpl(containingDeclaration, Annotations.EMPTY, name, delegateType, SourceElement.NO_SOURCE) {
) : PropertyDescriptorImpl(
containingDeclaration,
null, // original
Annotations.EMPTY,
Modality.FINAL,
Visibilities.PRIVATE,
false, // isVar
name,
CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE,
false, // lateInit
false // isConst
) {
init {
setOutType(delegateType)
}
override final fun setOutType(outType: KotlinType?) {
super.setOutType(outType)
}
override fun getCompileTimeInitializer(): ConstantValue<*>? = null
override fun getVisibility(): Visibility = Visibilities.PRIVATE
override fun substitute(substitutor: TypeSubstitutor): VariableDescriptor {
override fun substitute(substitutor: TypeSubstitutor): PropertyDescriptor {
throw UnsupportedOperationException("Property delegate descriptor shouldn't be substituted: $this")
}
@@ -58,15 +87,21 @@ class IrPropertyDelegateDescriptorImpl(
override val correspondingProperty: PropertyDescriptor,
delegateType: KotlinType,
override val kPropertyType: KotlinType
) : IrPropertyDelegateDescriptor,
IrDelegateDescriptorBase(correspondingProperty.containingDeclaration, getDelegateName(correspondingProperty.name), delegateType)
) : IrDelegateDescriptorBase(
correspondingProperty.containingDeclaration,
getDelegateName(correspondingProperty.name),
delegateType
), IrPropertyDelegateDescriptor
class IrImplementingDelegateDescriptorImpl(
containingDeclaration: ClassDescriptor,
delegateType: KotlinType,
override val correspondingSuperType: KotlinType
) : IrImplementingDelegateDescriptor,
IrDelegateDescriptorBase(containingDeclaration, getDelegateName(containingDeclaration, correspondingSuperType), delegateType)
) : IrDelegateDescriptorBase(
containingDeclaration,
getDelegateName(containingDeclaration, correspondingSuperType),
delegateType
), IrImplementingDelegateDescriptor
internal fun getDelegateName(name: Name): Name =
Name.identifier(name.asString() + "\$delegate")
@@ -74,4 +109,26 @@ internal fun getDelegateName(name: Name): Name =
internal fun getDelegateName(classDescriptor: ClassDescriptor, superType: KotlinType): Name =
Name.identifier(classDescriptor.name.asString() + "\$" +
(superType.constructor.declarationDescriptor?.name ?: "\$") +
"\$delegate")
"\$delegate")
class IrLocalDelegatedPropertyDelegateDescriptorImpl(
override val correspondingLocalProperty: VariableDescriptorWithAccessors,
delegateType: KotlinType,
override val kPropertyType: KotlinType
) : IrLocalDelegatedPropertyDelegateDescriptor,
VariableDescriptorImpl(
correspondingLocalProperty.containingDeclaration,
Annotations.EMPTY,
getDelegateName(correspondingLocalProperty.name),
delegateType,
org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE
) {
override fun getCompileTimeInitializer(): ConstantValue<*>? = null
override fun isVar(): Boolean = false
override fun substitute(substitutor: TypeSubstitutor): VariableDescriptor? = throw UnsupportedOperationException()
override fun getVisibility(): Visibility = Visibilities.LOCAL
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R =
visitor.visitVariableDescriptor(this, data)
}
@@ -51,6 +51,14 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor<Unit, String> {
visitFunctionWithParameters(declaration, data)
}
override fun visitDelegatedProperty(declaration: IrDelegatedProperty, data: String) {
declaration.dumpLabeledElementWith(data) {
declaration.delegate.accept(this, "delegate")
declaration.getter?.accept(this, "")
declaration.setter?.accept(this, "")
}
}
private fun visitFunctionWithParameters(declaration: IrFunction, data: String) {
declaration.dumpLabeledElementWith(data) {
declaration.descriptor.valueParameters.forEach { valueParameter ->
@@ -63,9 +63,6 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
override fun visitVariable(declaration: IrVariable, data: Nothing?): String =
"VAR ${declaration.descriptor.render()}"
override fun visitDelegate(declaration: IrDelegate, data: Nothing?): String =
"DELEGATE ${declaration.descriptor.render()}"
override fun visitEnumEntry(declaration: IrEnumEntry, data: Nothing?): String =
"ENUM_ENTRY ${declaration.descriptor.render()}"
@@ -36,8 +36,9 @@ interface IrElementVisitor<out R, in D> {
fun visitProperty(declaration: IrProperty, data: D) = visitDeclaration(declaration, data)
fun visitSimpleProperty(declaration: IrSimpleProperty, data: D) = visitProperty(declaration, data)
fun visitDelegatedProperty(declaration: IrDelegatedProperty, data: D) = visitProperty(declaration, data)
fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty, data: D) = visitDeclaration(declaration, data)
fun visitLocalPropertyAccessor(declaration: IrLocalPropertyAccessor, data: D) = visitGeneralFunction(declaration, data)
fun visitVariable(declaration: IrVariable, data: D) = visitDeclaration(declaration, data)
fun visitDelegate(declaration: IrDelegate, data: D) = visitDeclaration(declaration, data)
fun visitEnumEntry(declaration: IrEnumEntry, data: D) = visitDeclaration(declaration, data)
fun visitAnonymousInitializer(declaration: IrAnonymousInitializer, data: D) = visitDeclaration(declaration, data)
@@ -92,6 +93,4 @@ interface IrElementVisitor<out R, in D> {
// NB Use it only for testing purposes; will be removed as soon as all Kotlin expression types are covered
fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: D) = visitDeclaration(declaration, data)
fun visitDummyExpression(expression: IrDummyExpression, data: D) = visitExpression(expression, data)
}