Delegated properties.
This commit is contained in:
committed by
Dmitry Petrov
parent
865d2c43c7
commit
759f0168c2
@@ -36,5 +36,6 @@ const val FINALLY_EXPRESSION_SLOT = -2
|
||||
const val NESTED_INITIALIZERS_SLOT = -1
|
||||
const val PROPERTY_GETTER_SLOT = -1
|
||||
const val PROPERTY_SETTER_SLOT = -2
|
||||
const val DELEGATE_SLOT = -3
|
||||
const val ENUM_ENTRY_CLASS_SLOT = -1
|
||||
const val ENUM_ENTRY_INITIALIZER_SLOT = -2
|
||||
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.ir.IrElementBase
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
|
||||
interface IrDeclaration : IrStatement {
|
||||
val descriptor: DeclarationDescriptor?
|
||||
val descriptor: DeclarationDescriptor
|
||||
val declarationKind: IrDeclarationKind
|
||||
val origin: IrDeclarationOrigin
|
||||
}
|
||||
@@ -35,6 +35,7 @@ enum class IrDeclarationKind {
|
||||
CONSTRUCTOR,
|
||||
PROPERTY,
|
||||
VARIABLE,
|
||||
DELEGATE,
|
||||
CLASS,
|
||||
TYPEALIAS,
|
||||
ENUM_ENTRY,
|
||||
@@ -43,6 +44,8 @@ enum class IrDeclarationKind {
|
||||
|
||||
enum class IrDeclarationOrigin {
|
||||
DEFINED,
|
||||
DELEGATE,
|
||||
DELEGATED_PROPERTY_ACCESSOR,
|
||||
CLASS_FOR_ENUM_ENTRY,
|
||||
ENUM_CLASS_SPECIAL_MEMBER,
|
||||
GENERATED_DATA_CLASS_MEMBER,
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.IrExpression
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -35,10 +35,9 @@ interface IrSimpleProperty : IrProperty {
|
||||
}
|
||||
|
||||
interface IrDelegatedProperty : IrProperty {
|
||||
var delegateInitializer: IrBody
|
||||
var delegate: IrDelegate
|
||||
}
|
||||
|
||||
// TODO synchronization?
|
||||
abstract class IrPropertyBase(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
@@ -119,26 +118,37 @@ class IrDelegatedPropertyImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
descriptor: PropertyDescriptor,
|
||||
delegateInitializer: IrBody
|
||||
descriptor: PropertyDescriptor
|
||||
) : IrPropertyBase(startOffset, endOffset, origin, descriptor), IrDelegatedProperty {
|
||||
override var delegateInitializer: IrBody = delegateInitializer
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
descriptor: PropertyDescriptor,
|
||||
delegate: IrDelegate
|
||||
) : this(startOffset, endOffset, origin, descriptor) {
|
||||
this.delegate = delegate
|
||||
}
|
||||
|
||||
private var delegateImpl: IrDelegate? = null
|
||||
override var delegate: IrDelegate
|
||||
get() = delegateImpl!!
|
||||
set(value) {
|
||||
value.assertDetached()
|
||||
field.detach()
|
||||
field = value
|
||||
value.setTreeLocation(this, INITIALIZER_SLOT)
|
||||
delegateImpl?.detach()
|
||||
delegateImpl = value
|
||||
value.setTreeLocation(this, DELEGATE_SLOT)
|
||||
}
|
||||
|
||||
override fun getChild(slot: Int): IrElement? =
|
||||
when (slot) {
|
||||
INITIALIZER_SLOT -> delegateInitializer
|
||||
DELEGATE_SLOT -> delegate
|
||||
else -> super.getChild(slot)
|
||||
}
|
||||
|
||||
override fun replaceChild(slot: Int, newChild: IrElement) {
|
||||
when (slot) {
|
||||
INITIALIZER_SLOT -> delegateInitializer = newChild.assertCast()
|
||||
DELEGATE_SLOT -> delegate = newChild.assertCast()
|
||||
else -> super.replaceChild(slot, newChild)
|
||||
}
|
||||
}
|
||||
@@ -147,7 +157,7 @@ class IrDelegatedPropertyImpl(
|
||||
visitor.visitDelegatedProperty(this, data)
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
delegateInitializer.accept(visitor, data)
|
||||
delegate.accept(visitor, data)
|
||||
getter?.accept(visitor, data)
|
||||
setter?.accept(visitor, data)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
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
|
||||
|
||||
interface IrDelegateDescriptor : VariableDescriptor
|
||||
|
||||
interface IrPropertyDelegateDescriptor : IrDelegateDescriptor {
|
||||
val correspondingProperty: PropertyDescriptor
|
||||
val kPropertyType: KotlinType
|
||||
}
|
||||
|
||||
class IrPropertyDelegateDescriptorImpl(
|
||||
outType: KotlinType,
|
||||
override val correspondingProperty: PropertyDescriptor,
|
||||
override val kPropertyType: KotlinType
|
||||
) : IrPropertyDelegateDescriptor,
|
||||
VariableDescriptorImpl(correspondingProperty.containingDeclaration,
|
||||
Annotations.EMPTY,
|
||||
getDelegateName(correspondingProperty.name),
|
||||
outType, SourceElement.NO_SOURCE
|
||||
) {
|
||||
override fun getCompileTimeInitializer(): ConstantValue<*>? = null
|
||||
|
||||
override fun getVisibility(): Visibility = Visibilities.PRIVATE
|
||||
|
||||
override fun substitute(substitutor: TypeSubstitutor): VariableDescriptor {
|
||||
throw UnsupportedOperationException("Property delegate descriptor shouldn't be substituted: $this")
|
||||
}
|
||||
|
||||
override fun isVar(): Boolean = false
|
||||
|
||||
override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R =
|
||||
visitor.visitVariableDescriptor(this, data)
|
||||
}
|
||||
|
||||
internal fun getDelegateName(name: Name): Name =
|
||||
Name.identifier(name.asString() + "\$delegate")
|
||||
@@ -34,7 +34,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
|
||||
"? ${element.javaClass.simpleName}"
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclaration, data: Nothing?): String =
|
||||
"? ${declaration.javaClass.simpleName} ${declaration.descriptor?.name}"
|
||||
"? ${declaration.javaClass.simpleName} ${declaration.descriptor.name}"
|
||||
|
||||
override fun visitFile(declaration: IrFile, data: Nothing?): String =
|
||||
"FILE ${declaration.name}"
|
||||
@@ -63,6 +63,9 @@ 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()}"
|
||||
|
||||
@@ -187,12 +190,12 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
|
||||
}
|
||||
|
||||
internal fun IrDeclaration.name(): String =
|
||||
descriptor?.let { it.name.toString() } ?: "<none>"
|
||||
descriptor.let { it.name.toString() }
|
||||
|
||||
internal fun DeclarationDescriptor?.render(): String =
|
||||
this?.let { DESCRIPTOR_RENDERER.render(it) } ?: "<none>"
|
||||
internal fun DeclarationDescriptor.render(): String =
|
||||
DESCRIPTOR_RENDERER.render(this)
|
||||
|
||||
internal fun KotlinType?.render(): String =
|
||||
this?.let { DESCRIPTOR_RENDERER.renderType(it) } ?: "<no-type>"
|
||||
internal fun KotlinType.render(): String =
|
||||
DESCRIPTOR_RENDERER.renderType(this)
|
||||
}
|
||||
}
|
||||
@@ -22,34 +22,35 @@ import org.jetbrains.kotlin.ir.expressions.*
|
||||
|
||||
interface IrElementVisitor<out R, in D> {
|
||||
fun visitElement(element: IrElement, data: D): R
|
||||
fun visitModule(declaration: IrModule, data: D): R = visitElement(declaration, data)
|
||||
fun visitFile(declaration: IrFile, data: D): R = visitElement(declaration, data)
|
||||
fun visitModule(declaration: IrModule, data: D) = visitElement(declaration, data)
|
||||
fun visitFile(declaration: IrFile, data: D) = visitElement(declaration, data)
|
||||
|
||||
fun visitDeclaration(declaration: IrDeclaration, data: D): R = visitElement(declaration, data)
|
||||
fun visitClass(declaration: IrClass, data: D): R = visitDeclaration(declaration, data)
|
||||
fun visitTypeAlias(declaration: IrTypeAlias, data: D): R = visitDeclaration(declaration, data)
|
||||
fun visitDeclaration(declaration: IrDeclaration, data: D) = visitElement(declaration, data)
|
||||
fun visitClass(declaration: IrClass, data: D) = visitDeclaration(declaration, data)
|
||||
fun visitTypeAlias(declaration: IrTypeAlias, data: D) = visitDeclaration(declaration, data)
|
||||
fun visitGeneralFunction(declaration: IrGeneralFunction, data: D) = visitDeclaration(declaration, data)
|
||||
fun visitFunction(declaration: IrFunction, data: D): R = visitGeneralFunction(declaration, data)
|
||||
fun visitPropertyGetter(declaration: IrPropertyGetter, data: D): R = visitGeneralFunction(declaration, data)
|
||||
fun visitPropertySetter(declaration: IrPropertySetter, data: D): R = visitGeneralFunction(declaration, data)
|
||||
fun visitConstructor(declaration: IrConstructor, data: D): R = visitGeneralFunction(declaration, data)
|
||||
fun visitProperty(declaration: IrProperty, data: D): R = visitDeclaration(declaration, data)
|
||||
fun visitSimpleProperty(declaration: IrSimpleProperty, data: D): R = visitProperty(declaration, data)
|
||||
fun visitDelegatedProperty(declaration: IrDelegatedProperty, data: D): R = visitProperty(declaration, data)
|
||||
fun visitFunction(declaration: IrFunction, data: D) = visitGeneralFunction(declaration, data)
|
||||
fun visitPropertyGetter(declaration: IrPropertyGetter, data: D) = visitGeneralFunction(declaration, data)
|
||||
fun visitPropertySetter(declaration: IrPropertySetter, data: D) = visitGeneralFunction(declaration, data)
|
||||
fun visitConstructor(declaration: IrConstructor, data: D) = visitGeneralFunction(declaration, data)
|
||||
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 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 visitBody(body: IrBody, data: D): R = visitElement(body, data)
|
||||
fun visitExpressionBody(body: IrExpressionBody, data: D): R = visitBody(body, data)
|
||||
fun visitBody(body: IrBody, data: D) = visitElement(body, data)
|
||||
fun visitExpressionBody(body: IrExpressionBody, data: D) = visitBody(body, data)
|
||||
fun visitBlockBody(body: IrBlockBody, data: D) = visitBody(body, data)
|
||||
fun visitSyntheticBody(body: IrSyntheticBody, data: D) = visitBody(body, data)
|
||||
|
||||
fun visitExpression(expression: IrExpression, data: D): R = visitElement(expression, data)
|
||||
fun <T> visitConst(expression: IrConst<T>, data: D): R = visitExpression(expression, data)
|
||||
fun visitVararg(expression: IrVararg, data: D): R = visitExpression(expression, data)
|
||||
fun visitSpreadElement(spread: IrSpreadElement, data: D): R = visitElement(spread, data)
|
||||
fun visitExpression(expression: IrExpression, data: D) = visitElement(expression, data)
|
||||
fun <T> visitConst(expression: IrConst<T>, data: D) = visitExpression(expression, data)
|
||||
fun visitVararg(expression: IrVararg, data: D) = visitExpression(expression, data)
|
||||
fun visitSpreadElement(spread: IrSpreadElement, data: D) = visitElement(spread, data)
|
||||
|
||||
fun visitBlock(expression: IrBlock, data: D): R = visitExpression(expression, data)
|
||||
fun visitBlock(expression: IrBlock, data: D) = visitExpression(expression, data)
|
||||
fun visitStringConcatenation(expression: IrStringConcatenation, data: D) = visitExpression(expression, data)
|
||||
fun visitThisReference(expression: IrThisReference, data: D) = visitExpression(expression, data)
|
||||
|
||||
@@ -84,8 +85,8 @@ interface IrElementVisitor<out R, in D> {
|
||||
fun visitBreak(jump: IrBreak, data: D) = visitBreakContinue(jump, data)
|
||||
fun visitContinue(jump: IrContinue, data: D) = visitBreakContinue(jump, data)
|
||||
|
||||
fun visitReturn(expression: IrReturn, data: D): R = visitExpression(expression, data)
|
||||
fun visitThrow(expression: IrThrow, data: D): R = visitExpression(expression, data)
|
||||
fun visitReturn(expression: IrReturn, data: D) = visitExpression(expression, data)
|
||||
fun visitThrow(expression: IrThrow, data: D) = visitExpression(expression, data)
|
||||
|
||||
// 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)
|
||||
|
||||
Reference in New Issue
Block a user