Delegated properties.

This commit is contained in:
Dmitry Petrov
2016-09-01 12:52:49 +03:00
committed by Dmitry Petrov
parent 865d2c43c7
commit 759f0168c2
19 changed files with 415 additions and 58 deletions
@@ -76,7 +76,6 @@ fun IrBuilderWithScope.irThis() =
IrThisReferenceImpl(startOffset, endOffset, classOwner.defaultType, classOwner)
}
fun IrBuilderWithScope.irGet(variable: VariableDescriptor) =
IrGetVariableImpl(startOffset, endOffset, variable)
@@ -127,3 +126,6 @@ fun IrBuilderWithScope.irString(value: String) =
fun IrBuilderWithScope.irConcat() =
IrStringConcatenationImpl(startOffset, endOffset, context.builtIns.stringType)
fun IrBuilderWithScope.irCallableReference(type: KotlinType, descriptor: CallableDescriptor) =
IrCallableReferenceImpl(startOffset, endOffset, type, descriptor)
@@ -66,6 +66,11 @@ open class IrBlockBodyBuilder(
) : IrStatementsBuilder<IrBlockBody>(context, scope, startOffset, endOffset) {
private val irBlockBody = IrBlockBodyImpl(startOffset, endOffset)
inline fun blockBody(body: IrBlockBodyBuilder.() -> Unit): IrBlockBody {
body()
return doBuild()
}
override fun addStatement(irStatement: IrStatement) {
irBlockBody.addStatement(irStatement)
}
@@ -123,4 +128,10 @@ inline fun GeneratorWithScope.irBlock(ktElement: KtElement? = null, operator: Ir
ktElement?.startOffset ?: UNDEFINED_OFFSET,
ktElement?.endOffset ?: UNDEFINED_OFFSET,
operator, resultType
).block(body)
).block(body)
inline fun GeneratorWithScope.irBlockBody(ktElement: KtElement? = null, body: IrBlockBodyBuilder.() -> Unit) : IrBlockBody =
IrBlockBodyBuilder(context, scope,
ktElement?.startOffset ?: UNDEFINED_OFFSET,
ktElement?.endOffset ?: UNDEFINED_OFFSET
).blockBody(body)
@@ -20,11 +20,19 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrFunctionBase
import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptor
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.builders.irBlockBody
import org.jetbrains.kotlin.psi2ir.builders.irCallableReference
import org.jetbrains.kotlin.psi2ir.builders.irGet
import org.jetbrains.kotlin.psi2ir.builders.irReturn
import org.jetbrains.kotlin.psi2ir.intermediate.VariableLValue
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
import org.jetbrains.kotlin.resolve.BindingContext
import java.lang.AssertionError
import java.util.*
class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context: GeneratorContext): GeneratorWithScope {
@@ -59,7 +67,7 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
return irBlockBody
}
fun generatePropertyInitializerBody(ktInitializer: KtExpression): IrBody =
fun generatePropertyInitializerBody(ktInitializer: KtExpression): IrExpressionBody =
IrExpressionBodyImpl(ktInitializer.startOffset, ktInitializer.endOffset,
createStatementGenerator().generateExpression(ktInitializer))
@@ -277,5 +285,34 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
private fun createPropertyInitializationExpression(ktElement: KtElement, propertyDescriptor: PropertyDescriptor, value: IrExpression) =
IrSetBackingFieldImpl(ktElement.startOffset, ktElement.endOffset, propertyDescriptor, value)
fun generateDelegatedPropertyGetter(
ktDelegate: KtPropertyDelegate,
delegateDescriptor: IrPropertyDelegateDescriptor,
getterDescriptor: PropertyGetterDescriptor
): IrBody =
irBlockBody(ktDelegate) {
val statementGenerator = createStatementGenerator()
val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor)
val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall)
conventionMethodCall.setExplicitReceiverValue(VariableLValue(ktDelegate.startOffset, ktDelegate.endOffset, delegateDescriptor))
conventionMethodCall.irValueArgumentsByIndex[1] = irCallableReference(delegateDescriptor.kPropertyType, delegateDescriptor.correspondingProperty)
+irReturn(CallGenerator(statementGenerator).generateCall(ktDelegate.startOffset, ktDelegate.endOffset, conventionMethodCall))
}
fun generateDelegatedPropertySetter(
ktDelegate: KtPropertyDelegate,
delegateDescriptor: IrPropertyDelegateDescriptor,
setterDescriptor: PropertySetterDescriptor
): IrBody =
irBlockBody(ktDelegate) {
val statementGenerator = createStatementGenerator()
val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor)
val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall)
conventionMethodCall.setExplicitReceiverValue(VariableLValue(ktDelegate.startOffset, ktDelegate.endOffset, delegateDescriptor))
conventionMethodCall.irValueArgumentsByIndex[1] = irCallableReference(delegateDescriptor.kPropertyType, delegateDescriptor.correspondingProperty)
conventionMethodCall.irValueArgumentsByIndex[2] = irGet(setterDescriptor.valueParameters[0])
+irReturn(CallGenerator(statementGenerator).generateCall(ktDelegate.startOffset, ktDelegate.endOffset, conventionMethodCall))
}
}
@@ -17,7 +17,9 @@
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
@@ -90,27 +92,64 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
fun generatePropertyDeclaration(ktProperty: KtProperty): IrProperty {
val propertyDescriptor = getPropertyDescriptor(ktProperty)
if (ktProperty.hasDelegate()) TODO("handle delegated property")
val ktDelegate = ktProperty.delegate
return if (ktDelegate != null)
generateDelegatedProperty(ktProperty, ktDelegate, propertyDescriptor)
else
generateSimpleProperty(ktProperty, propertyDescriptor)
}
private fun generateDelegatedProperty(ktProperty: KtProperty, ktDelegate: KtPropertyDelegate, propertyDescriptor: PropertyDescriptor): IrProperty {
val ktDelegateExpression = ktDelegate.expression!!
val delegateType = getInferredTypeWithImplicitCasts(ktDelegateExpression)!!
val propertyReceiverType = propertyDescriptor.extensionReceiverParameter?.type ?:
propertyDescriptor.dispatchReceiverParameter?.type
val kPropertyType = context.reflectionTypes.getKPropertyType(
Annotations.EMPTY, propertyReceiverType, propertyDescriptor.type, propertyDescriptor.isVar)
val delegateDescriptor = IrPropertyDelegateDescriptorImpl(delegateType, propertyDescriptor, kPropertyType)
val irDelegateInitializer = generateInitializerBody(delegateDescriptor, ktDelegateExpression)
val irDelegate = IrDelegateImpl(ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATE,
delegateDescriptor, irDelegateInitializer)
val irProperty = IrDelegatedPropertyImpl(ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED,
propertyDescriptor, irDelegate)
val getterDescriptor = propertyDescriptor.getter ?: throw AssertionError("Delegated property should have getter: $propertyDescriptor")
val getterBody = createBodyGenerator(getterDescriptor).generateDelegatedPropertyGetter(ktDelegate, delegateDescriptor, getterDescriptor)
irProperty.getter = IrPropertyGetterImpl(ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR,
getterDescriptor, getterBody)
if (propertyDescriptor.isVar) {
val setterDescriptor = propertyDescriptor.setter ?: throw AssertionError("Delegated property should have setter: $propertyDescriptor")
val setterBody = createBodyGenerator(setterDescriptor).generateDelegatedPropertySetter(ktDelegate, delegateDescriptor, setterDescriptor)
irProperty.setter = IrPropertySetterImpl(ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR,
setterDescriptor, setterBody)
}
return irProperty
}
private fun generateSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor): IrSimplePropertyImpl {
val initializer = ktProperty.initializer?.let { generateInitializerBody(propertyDescriptor, it) }
val irProperty = IrSimplePropertyImpl(ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED,
propertyDescriptor, initializer)
ktProperty.getter?.let { ktGetter ->
irProperty.getter = ktProperty.getter?.let { ktGetter ->
val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktGetter)
val getterDescriptor = accessorDescriptor as? PropertyGetterDescriptor ?: TODO("not a getter?")
val irGetterBody = generateFunctionBody(getterDescriptor, ktGetter.bodyExpression ?: TODO("default getter"))
val irGetter = IrPropertyGetterImpl(ktGetter.startOffset, ktGetter.endOffset, IrDeclarationOrigin.DEFINED,
getterDescriptor, irGetterBody)
irProperty.getter = irGetter
irGetter
}
ktProperty.setter?.let { ktSetter ->
irProperty.setter = ktProperty.setter?.let { ktSetter ->
val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktSetter)
val setterDescriptor = accessorDescriptor as? PropertySetterDescriptor ?: TODO("not a setter?")
val irSetterBody = generateFunctionBody(setterDescriptor, ktSetter.bodyExpression ?: TODO("default setter"))
val irSetter = IrPropertySetterImpl(ktSetter.startOffset, ktSetter.endOffset, IrDeclarationOrigin.DEFINED,
setterDescriptor, irSetterBody)
irProperty.setter = irSetter
irSetter
}
return irProperty
@@ -126,7 +165,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
private fun generateFunctionBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody =
createBodyGenerator(scopeOwner).generateFunctionBody(ktBody)
private fun generateInitializerBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody =
private fun generateInitializerBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrExpressionBody =
createBodyGenerator(scopeOwner).generatePropertyInitializerBody(ktBody)
private fun createBodyGenerator(descriptor: CallableDescriptor) =
@@ -17,20 +17,23 @@
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.ReflectionTypes
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
class GeneratorContext(
val moduleDescriptor: ModuleDescriptor,
val bindingContext: BindingContext
) {
val storageManager = LockBasedStorageManager.NO_LOCKS
val storageManager: StorageManager = LockBasedStorageManager.NO_LOCKS
val sourceManager = PsiSourceManager()
val syntheticDescriptorsFactory by lazy { SyntheticDescriptorsFactory(storageManager) }
val reflectionTypes = ReflectionTypes(moduleDescriptor)
val builtIns: KotlinBuiltIns get() = moduleDescriptor.builtIns
val irBuiltIns = IrBuiltIns(builtIns)
}
@@ -205,7 +205,10 @@ class StatementGenerator(
entry.expression!!.genExpr()
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, data: Nothing?): IrExpression {
val resolvedCall = getResolvedCall(expression) ?: throw AssertionError("No resolved call for ${expression.text}")
val resolvedCall = getResolvedCall(expression) ?:
return IrDummyExpression(expression.startOffset, expression.endOffset,
context.builtIns.nothingType,
"No resolved call for ${expression.text}")
if (resolvedCall is VariableAsFunctionResolvedCall) {
val variableCall = pregenerateCall(resolvedCall.variableCall)
@@ -31,8 +31,8 @@ class VariableLValue(
val descriptor: VariableDescriptor,
val irOperator: IrOperator? = null
) : LValue, AssignmentReceiver {
constructor(irVariable: IrVariable, irOperator: IrOperator? = null) :
this(irVariable.startOffset, irVariable.endOffset, irVariable.descriptor, irOperator)
constructor(irVariable: IrVariable, irOperator: IrOperator? = null) : this(
irVariable.startOffset, irVariable.endOffset, irVariable.descriptor, irOperator)
override val type: KotlinType get() = descriptor.type
@@ -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)
@@ -0,0 +1,8 @@
val test1 by lazy { 42 }
class C(val map: MutableMap<String, Any>) {
val test2 by lazy { 42 }
var test3 by map
}
var test4 by hashMapOf<String, Any>()
@@ -0,0 +1,82 @@
FILE /delegatedProperties.kt
PROPERTY public val test1: kotlin.Int
DELEGATE val `test1$delegate`: kotlin.Lazy<kotlin.Int>
EXPRESSION_BODY
CALL .lazy type=kotlin.Lazy<kotlin.Int> operator=null
initializer: BLOCK type=() -> kotlin.Int operator=LAMBDA
FUN local final fun <anonymous>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from=<anonymous>
CONST Int type=kotlin.Int value='42'
CALLABLE_REFERENCE local final fun <anonymous>(): kotlin.Int type=() -> kotlin.Int
PROPERTY_GETTER public fun <get-test1>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from=<get-test1>
CALL .getValue type=kotlin.Int operator=null
$receiver: GET_VAR test1$delegate type=kotlin.Lazy<kotlin.Int> operator=null
thisRef: CONST Null type=kotlin.Nothing? value='null'
property: CALLABLE_REFERENCE public val test1: kotlin.Int type=kotlin.reflect.KProperty0<kotlin.Int>
CLASS CLASS C
CONSTRUCTOR public constructor C(/*0*/ map: kotlin.collections.MutableMap<kotlin.String, kotlin.Any>)
BLOCK_BODY
SET_BACKING_FIELD map type=kotlin.Unit operator=null
GET_VAR map type=kotlin.collections.MutableMap<kotlin.String, kotlin.Any> operator=INITIALIZE_PROPERTY_FROM_PARAMETER
PROPERTY public final val map: kotlin.collections.MutableMap<kotlin.String, kotlin.Any>
EXPRESSION_BODY
GET_VAR map type=kotlin.collections.MutableMap<kotlin.String, kotlin.Any> operator=INITIALIZE_PROPERTY_FROM_PARAMETER
PROPERTY public final val test2: kotlin.Int
DELEGATE val `test2$delegate`: kotlin.Lazy<kotlin.Int>
EXPRESSION_BODY
CALL .lazy type=kotlin.Lazy<kotlin.Int> operator=null
initializer: BLOCK type=() -> kotlin.Int operator=LAMBDA
FUN local final fun <anonymous>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from=<anonymous>
CONST Int type=kotlin.Int value='42'
CALLABLE_REFERENCE local final fun <anonymous>(): kotlin.Int type=() -> kotlin.Int
PROPERTY_GETTER public final fun <get-test2>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from=<get-test2>
CALL .getValue type=kotlin.Int operator=null
$receiver: GET_VAR test2$delegate type=kotlin.Lazy<kotlin.Int> operator=null
thisRef: THIS public final class C type=C
property: CALLABLE_REFERENCE public final val test2: kotlin.Int type=kotlin.reflect.KProperty1<C, kotlin.Int>
PROPERTY public final var test3: kotlin.Any
DELEGATE val `test3$delegate`: kotlin.collections.MutableMap<kotlin.String, kotlin.Any>
EXPRESSION_BODY
CALL .<get-map> type=kotlin.collections.MutableMap<kotlin.String, kotlin.Any> operator=GET_PROPERTY
$this: THIS public final class C type=C
PROPERTY_GETTER public final fun <get-test3>(): kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from=<get-test3>
CALL .getValue type=kotlin.Any operator=null
$receiver: GET_VAR test3$delegate type=kotlin.collections.MutableMap<kotlin.String, kotlin.Any> operator=null
thisRef: THIS public final class C type=C
property: CALLABLE_REFERENCE public final var test3: kotlin.Any type=kotlin.reflect.KMutableProperty1<C, kotlin.Any>
PROPERTY_SETTER public final fun <set-test3>(/*0*/ <set-?>: kotlin.Any): kotlin.Unit
BLOCK_BODY
RETURN type=kotlin.Nothing from=<set-test3>
CALL .setValue type=kotlin.Unit operator=null
$receiver: GET_VAR test3$delegate type=kotlin.collections.MutableMap<kotlin.String, kotlin.Any> operator=null
thisRef: THIS public final class C type=C
property: CALLABLE_REFERENCE public final var test3: kotlin.Any type=kotlin.reflect.KMutableProperty1<C, kotlin.Any>
value: GET_VAR <set-?> type=kotlin.Any operator=null
PROPERTY public var test4: kotlin.Any
DELEGATE val `test4$delegate`: java.util.HashMap<kotlin.String, kotlin.Any>
EXPRESSION_BODY
CALL .hashMapOf type=java.util.HashMap<kotlin.String, kotlin.Any> operator=null
PROPERTY_GETTER public fun <get-test4>(): kotlin.Any
BLOCK_BODY
RETURN type=kotlin.Nothing from=<get-test4>
CALL .getValue type=kotlin.Any operator=null
$receiver: GET_VAR test4$delegate type=java.util.HashMap<kotlin.String, kotlin.Any> operator=null
thisRef: CONST Null type=kotlin.Nothing? value='null'
property: CALLABLE_REFERENCE public var test4: kotlin.Any type=kotlin.reflect.KMutableProperty0<kotlin.Any>
PROPERTY_SETTER public fun <set-test4>(/*0*/ <set-?>: kotlin.Any): kotlin.Unit
BLOCK_BODY
RETURN type=kotlin.Nothing from=<set-test4>
CALL .setValue type=kotlin.Unit operator=null
$receiver: GET_VAR test4$delegate type=java.util.HashMap<kotlin.String, kotlin.Any> operator=null
thisRef: CONST Null type=kotlin.Nothing? value='null'
property: CALLABLE_REFERENCE public var test4: kotlin.Any type=kotlin.reflect.KMutableProperty0<kotlin.Any>
value: GET_VAR <set-?> type=kotlin.Any operator=null
@@ -35,12 +35,6 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/ir/irText"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("defaultArguments.kt")
public void testDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/defaultArguments.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/ir/irText/classes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -152,6 +146,27 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
}
}
@TestMetadata("compiler/testData/ir/irText/declarations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Declarations extends AbstractIrTextTestCase {
public void testAllFilesPresentInDeclarations() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/ir/irText/declarations"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("defaultArguments.kt")
public void testDefaultArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/declarations/defaultArguments.kt");
doTest(fileName);
}
@TestMetadata("delegatedProperties.kt")
public void testDelegatedProperties() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/declarations/delegatedProperties.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/ir/irText/expressions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)