From 42988383e0765d11ec5d7ee4e59d006f75df6069 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 2 Sep 2016 10:18:06 +0300 Subject: [PATCH] Local delegated properties. --- .../kotlin/psi2ir/generators/BodyGenerator.kt | 32 +-- .../psi2ir/generators/ClassGenerator.kt | 14 +- .../psi2ir/generators/DeclarationGenerator.kt | 33 +-- .../generators/DelegatedPropertyGenerator.kt | 190 ++++++++++++++++++ .../psi2ir/generators/StatementGenerator.kt | 21 +- .../kotlin/ir/declarations/IrClass.kt | 4 +- .../kotlin/ir/declarations/IrDeclaration.kt | 10 +- .../kotlin/ir/declarations/IrDelegate.kt | 79 -------- .../ir/declarations/IrGeneralFunction.kt | 2 +- .../declarations/IrLocalDelegatedProperty.kt | 131 ++++++++++++ .../kotlin/ir/declarations/IrProperty.kt | 18 +- .../ir/declarations/IrPropertyAccessor.kt | 9 +- .../ir/descriptors/IrDelegateDescriptor.kt | 73 ++++++- .../jetbrains/kotlin/ir/util/DumpIrTree.kt | 8 + .../kotlin/ir/util/RenderIrElement.kt | 3 - .../kotlin/ir/visitors/IrElementVisitor.kt | 5 +- .../classes/delegatedImplementation.txt | 6 +- ...atedImplementationWithExplicitOverride.txt | 2 +- .../declarations/delegatedProperties.txt | 20 +- .../declarations/localDelegatedProperties.kt | 4 + .../declarations/localDelegatedProperties.txt | 21 ++ .../kotlin/ir/IrTextTestCaseGenerated.java | 6 + 22 files changed, 490 insertions(+), 201 deletions(-) create mode 100644 compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt delete mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDelegate.kt create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrLocalDelegatedProperty.kt create mode 100644 compiler/testData/ir/irText/declarations/localDelegatedProperties.kt create mode 100644 compiler/testData/ir/irText/declarations/localDelegatedProperties.txt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt index 9b012e7edcc..bb705223901 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt @@ -129,8 +129,7 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context: irBlockBody.addStatement(irDelegatingConstructorCall) } - private fun createStatementGenerator() = - StatementGenerator(context, scopeOwner, this, scope) + fun createStatementGenerator() = StatementGenerator(this, scope) fun putLoop(expression: KtLoopExpression, irLoop: IrLoop) { loopTable[expression] = irLoop @@ -261,34 +260,5 @@ 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)) - } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt index 47f0cfa01ff..98e29343477 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt @@ -81,8 +81,8 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator val superClass = superTypeConstructorDescriptor as? ClassDescriptor ?: throw AssertionError("Unexpected supertype constructor for delegation: $superTypeConstructorDescriptor") val delegateDescriptor = IrImplementingDelegateDescriptorImpl(irClass.descriptor, delegateType, superType) - val irDelegate = IrDelegateImpl(ktDelegateExpression.startOffset, ktDelegateExpression.endOffset, IrDeclarationOrigin.DELEGATE, - delegateDescriptor) + val irDelegate = IrSimplePropertyImpl(ktDelegateExpression.startOffset, ktDelegateExpression.endOffset, IrDeclarationOrigin.DELEGATE, + delegateDescriptor) val bodyGenerator = BodyGenerator(irClass.descriptor, context) irDelegate.initializer = bodyGenerator.generatePropertyInitializerBody(ktDelegateExpression) irClass.addMember(irDelegate) @@ -95,7 +95,7 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator } } - private fun generateDelegatedMember(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegatedMember: CallableMemberDescriptor, overriddenMember: CallableMemberDescriptor) { + private fun generateDelegatedMember(irClass: IrClassImpl, irDelegate: IrSimplePropertyImpl, delegatedMember: CallableMemberDescriptor, overriddenMember: CallableMemberDescriptor) { when (delegatedMember) { is FunctionDescriptor -> generateDelegatedFunction(irClass, irDelegate, delegatedMember, overriddenMember as FunctionDescriptor) @@ -105,7 +105,7 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator } - private fun generateDelegatedProperty(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegated: PropertyDescriptor, overridden: PropertyDescriptor) { + private fun generateDelegatedProperty(irClass: IrClassImpl, irDelegate: IrSimplePropertyImpl, delegated: PropertyDescriptor, overridden: PropertyDescriptor) { val irProperty = IrSimplePropertyImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated) val irGetter = IrPropertyGetterImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated.getter!!) @@ -121,13 +121,13 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator irClass.addMember(irProperty) } - private fun generateDelegatedFunction(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegated: FunctionDescriptor, overridden: FunctionDescriptor) { + private fun generateDelegatedFunction(irClass: IrClassImpl, irDelegate: IrSimplePropertyImpl, delegated: FunctionDescriptor, overridden: FunctionDescriptor) { val irFunction = IrFunctionImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated) irFunction.body = generateDelegateFunctionBody(irDelegate, delegated, overridden) irClass.addMember(irFunction) } - private fun generateDelegateFunctionBody(irDelegate: IrDelegateImpl, delegated: FunctionDescriptor, overridden: FunctionDescriptor): IrBlockBodyImpl { + private fun generateDelegateFunctionBody(irDelegate: IrSimplePropertyImpl, delegated: FunctionDescriptor, overridden: FunctionDescriptor): IrBlockBodyImpl { val irBlockBody = IrBlockBodyImpl(irDelegate.startOffset, irDelegate.endOffset) val returnType = overridden.returnType!! val irCall = IrCallImpl(irDelegate.startOffset, irDelegate.endOffset, returnType, overridden) @@ -197,7 +197,7 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator val irProperty = IrSimplePropertyImpl(ktParameter.startOffset, ktParameter.endOffset, IrDeclarationOrigin.DEFINED, propertyDescriptor) val irGetParameter = IrGetVariableImpl(ktParameter.startOffset, ktParameter.endOffset, valueParameterDescriptor, IrOperator.INITIALIZE_PROPERTY_FROM_PARAMETER) - irProperty.valueInitializer = IrExpressionBodyImpl(ktParameter.startOffset, ktParameter.endOffset, irGetParameter) + irProperty.initializer = IrExpressionBodyImpl(ktParameter.startOffset, ktParameter.endOffset, irGetParameter) return irProperty } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt index 4728cb4ab6f..fd2bb0fb339 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt @@ -17,10 +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.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset @@ -116,32 +115,8 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator { 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(propertyDescriptor, delegateType, 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 var 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 + val irDelegateInitializer = generateInitializerBody(propertyDescriptor, ktDelegateExpression) + return DelegatedPropertyGenerator(context).generateDelegatedProperty(ktProperty, ktDelegate, propertyDescriptor, irDelegateInitializer) } private fun generateSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor): IrSimplePropertyImpl { diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt new file mode 100644 index 00000000000..abe9abc3344 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt @@ -0,0 +1,190 @@ +/* + * 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.psi2ir.generators + +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.VariableAccessorDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.descriptors.IrLocalDelegatedPropertyDelegateDescriptor +import org.jetbrains.kotlin.ir.descriptors.IrLocalDelegatedPropertyDelegateDescriptorImpl +import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptor +import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptorImpl +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.KtPropertyDelegate +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.irGet +import org.jetbrains.kotlin.psi2ir.builders.irReturn +import org.jetbrains.kotlin.psi2ir.intermediate.BackingFieldLValue +import org.jetbrains.kotlin.psi2ir.intermediate.IntermediateValue +import org.jetbrains.kotlin.psi2ir.intermediate.VariableLValue +import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.types.KotlinType + + +class DelegatedPropertyGenerator(override val context: GeneratorContext) : Generator { + fun generateDelegatedProperty( + ktProperty: KtProperty, + ktDelegate: KtPropertyDelegate, + propertyDescriptor: PropertyDescriptor, + irDelegateInitializer: IrExpressionBody + ): IrDelegatedProperty { + val delegateDescriptor = createPropertyDelegateDescriptor(ktDelegate, propertyDescriptor) + + val irDelegate = IrSimplePropertyImpl( + ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATE, + delegateDescriptor, irDelegateInitializer) + + val irProperty = IrDelegatedPropertyImpl( + ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED, + propertyDescriptor, irDelegate) + + val delegateReceiverValue = createBackingFieldValueForDelegate(delegateDescriptor, ktDelegate) + val getterDescriptor = propertyDescriptor.getter!! + irProperty.getter = IrPropertyGetterImpl( + ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, + getterDescriptor, + generateDelegatedPropertyGetterBody( + ktDelegate, getterDescriptor, delegateReceiverValue, + createCallableReference(ktDelegate, delegateDescriptor.kPropertyType, propertyDescriptor))) + + if (propertyDescriptor.isVar) { + val setterDescriptor = propertyDescriptor.setter!! + irProperty.setter = IrPropertySetterImpl( + ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, + setterDescriptor, + generateDelegatedPropertySetterBody( + ktDelegate, setterDescriptor, delegateReceiverValue, + createCallableReference(ktDelegate, delegateDescriptor.kPropertyType, propertyDescriptor))) + } + + return irProperty + } + + private fun createBackingFieldValueForDelegate(delegateDescriptor: IrPropertyDelegateDescriptor, ktDelegate: KtPropertyDelegate) = + BackingFieldLValue(ktDelegate.startOffset, ktDelegate.endOffset, delegateDescriptor, null) + + private fun createCallableReference(ktElement: KtElement, type: KotlinType, referencedDescriptor: CallableDescriptor): IrCallableReference = + IrCallableReferenceImpl(ktElement.startOffset, ktElement.endOffset, type, referencedDescriptor) + + fun generateLocalDelegatedProperty( + ktProperty: KtProperty, + ktDelegate: KtPropertyDelegate, + variableDescriptor: VariableDescriptorWithAccessors, + irDelegateInitializer: IrExpression + ) : IrLocalDelegatedProperty { + val delegateDescriptor = createLocalPropertyDelegatedDescriptor(ktDelegate, variableDescriptor) + + val irDelegate = IrVariableImpl( + ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATE, + delegateDescriptor, irDelegateInitializer) + + val irLocalDelegatedProperty = IrLocalDelegatedPropertyImpl( + ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED, + variableDescriptor, irDelegate) + + val getterDescriptor = variableDescriptor.getter!! + val delegateReceiverValue = createVariableValueForDelegate(delegateDescriptor, ktDelegate) + irLocalDelegatedProperty.getter = createLocalPropertyAccessor( + getterDescriptor, ktDelegate, + generateDelegatedPropertyGetterBody( + ktDelegate, getterDescriptor, delegateReceiverValue, + createCallableReference(ktDelegate, delegateDescriptor.kPropertyType, delegateDescriptor.correspondingLocalProperty))) + + if (variableDescriptor.isVar) { + val setterDescriptor = variableDescriptor.setter!! + irLocalDelegatedProperty.setter = createLocalPropertyAccessor( + setterDescriptor, ktDelegate, + generateDelegatedPropertySetterBody( + ktDelegate, setterDescriptor, delegateReceiverValue, + createCallableReference(ktDelegate, delegateDescriptor.kPropertyType, delegateDescriptor.correspondingLocalProperty))) + + } + + return irLocalDelegatedProperty + } + + private fun createVariableValueForDelegate(delegateDescriptor: IrLocalDelegatedPropertyDelegateDescriptor, ktDelegate: KtPropertyDelegate) = + VariableLValue(ktDelegate.startOffset, ktDelegate.endOffset, delegateDescriptor) + + private fun createLocalPropertyAccessor(getterDescriptor: VariableAccessorDescriptor, ktDelegate: KtPropertyDelegate, body: IrBody) = + IrLocalPropertyAccessorImpl(ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, + getterDescriptor, body) + + private fun createLocalPropertyDelegatedDescriptor( + ktDelegate: KtPropertyDelegate, + variableDescriptor: VariableDescriptorWithAccessors + ): IrLocalDelegatedPropertyDelegateDescriptor { + val delegateType = getInferredTypeWithImplicitCastsOrFail(ktDelegate.expression!!) + val kPropertyType = context.reflectionTypes.getKPropertyType( + Annotations.EMPTY, null, variableDescriptor.type, variableDescriptor.isVar) + return IrLocalDelegatedPropertyDelegateDescriptorImpl(variableDescriptor, delegateType, kPropertyType) + } + + private fun createPropertyDelegateDescriptor( + ktDelegate: KtPropertyDelegate, + propertyDescriptor: PropertyDescriptor + ): IrPropertyDelegateDescriptor { + val delegateType = getInferredTypeWithImplicitCastsOrFail(ktDelegate.expression!!) + val propertyReceiverType = propertyDescriptor.extensionReceiverParameter?.type ?: + propertyDescriptor.dispatchReceiverParameter?.type + val kPropertyType = context.reflectionTypes.getKPropertyType( + Annotations.EMPTY, propertyReceiverType, propertyDescriptor.type, propertyDescriptor.isVar) + val delegateDescriptor = IrPropertyDelegateDescriptorImpl(propertyDescriptor, delegateType, kPropertyType) + return delegateDescriptor + } + + fun generateDelegatedPropertyGetterBody( + ktDelegate: KtPropertyDelegate, + getterDescriptor: VariableAccessorDescriptor, + delegateReceiverValue: IntermediateValue, + irPropertyReference: IrCallableReference + ): IrBody = with(BodyGenerator(getterDescriptor, context)) { + irBlockBody(ktDelegate) { + val statementGenerator = createStatementGenerator() + val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor) + val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall) + conventionMethodCall.setExplicitReceiverValue(delegateReceiverValue) + conventionMethodCall.irValueArgumentsByIndex[1] = irPropertyReference + +irReturn(CallGenerator(statementGenerator).generateCall(ktDelegate.startOffset, ktDelegate.endOffset, conventionMethodCall)) + } + } + + fun generateDelegatedPropertySetterBody( + ktDelegate: KtPropertyDelegate, + setterDescriptor: VariableAccessorDescriptor, + delegateReceiverValue: IntermediateValue, + irPropertyReference: IrCallableReference + ): IrBody = with(BodyGenerator(setterDescriptor, context)) { + irBlockBody(ktDelegate) { + val statementGenerator = createStatementGenerator() + val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, setterDescriptor) + val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall) + conventionMethodCall.setExplicitReceiverValue(delegateReceiverValue) + conventionMethodCall.irValueArgumentsByIndex[1] = irPropertyReference + conventionMethodCall.irValueArgumentsByIndex[2] = irGet(setterDescriptor.valueParameters[0]) + +irReturn(CallGenerator(statementGenerator).generateCall(ktDelegate.startOffset, ktDelegate.endOffset, conventionMethodCall)) + } + } +} \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt index 2b154af4444..60d5c34208f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt @@ -43,11 +43,12 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils import java.lang.AssertionError class StatementGenerator( - override val context: GeneratorContext, - val scopeOwner: DeclarationDescriptor, val bodyGenerator: BodyGenerator, override val scope: Scope ) : KtVisitor(), GeneratorWithScope { + override val context: GeneratorContext get() = bodyGenerator.context + val scopeOwner: DeclarationDescriptor get() = bodyGenerator.scopeOwner + fun generateStatement(ktElement: KtElement): IrStatement = ktElement.genStmt() @@ -64,15 +65,27 @@ class StatementGenerator( createDummyExpression(expression, expression.javaClass.simpleName) override fun visitProperty(property: KtProperty, data: Nothing?): IrStatement { - if (property.delegateExpression != null) TODO("Local delegated property") - val variableDescriptor = getOrFail(BindingContext.VARIABLE, property) + property.delegate?.let { ktDelegate -> + return generateLocalDelegatedProperty(property, ktDelegate, variableDescriptor as VariableDescriptorWithAccessors) + } + val irLocalVariable = IrVariableImpl(property.startOffset, property.endOffset, IrDeclarationOrigin.DEFINED, variableDescriptor) irLocalVariable.initializer = property.initializer?.genExpr() return irLocalVariable } + private fun generateLocalDelegatedProperty( + ktProperty: KtProperty, + ktDelegate: KtPropertyDelegate, + variableDescriptor: VariableDescriptorWithAccessors + ): IrStatement = + DelegatedPropertyGenerator(context).generateLocalDelegatedProperty( + ktProperty, ktDelegate, variableDescriptor, + ktDelegate.expression!!.genExpr() + ) + override fun visitDestructuringDeclaration(multiDeclaration: KtDestructuringDeclaration, data: Nothing?): IrStatement { // TODO use some special form that introduces multiple declarations into surrounding scope? diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt index fb8a5d899f7..8659904ee55 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt @@ -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 diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt index 2cbb32261a0..386c3212fc0 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt @@ -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; } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDelegate.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDelegate.kt deleted file mode 100644 index 2fb9aee1f03..00000000000 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDelegate.kt +++ /dev/null @@ -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 accept(visitor: IrElementVisitor, data: D): R { - return visitor.visitDelegate(this, data) - } - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - initializer.accept(visitor, data) - } -} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrGeneralFunction.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrGeneralFunction.kt index 08468c4710a..5e651c795ae 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrGeneralFunction.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrGeneralFunction.kt @@ -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 diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrLocalDelegatedProperty.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrLocalDelegatedProperty.kt new file mode 100644 index 00000000000..060e4f73bc5 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrLocalDelegatedProperty.kt @@ -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 accept(visitor: IrElementVisitor, data: D): R = + visitor.visitLocalDelegatedProperty(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, 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 accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitLocalPropertyAccessor(this, data) + } +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt index 9f73c3f25a1..4d36991d3e3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt @@ -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 acceptChildren(visitor: IrElementVisitor, 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() diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrPropertyAccessor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrPropertyAccessor.kt index 8721d12cf87..8d3a4001ab8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrPropertyAccessor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrPropertyAccessor.kt @@ -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( diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrDelegateDescriptor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrDelegateDescriptor.kt index 7a0a344a683..f053512c6cc 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrDelegateDescriptor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrDelegateDescriptor.kt @@ -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") \ No newline at end of file + "\$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 accept(visitor: DeclarationDescriptorVisitor, data: D): R = + visitor.visitVariableDescriptor(this, data) +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt index 2353e497676..0650aea5048 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt @@ -51,6 +51,14 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor { 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 -> diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt index 529048ad320..2158b804b5a 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt @@ -63,9 +63,6 @@ class RenderIrElementVisitor : IrElementVisitor { 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()}" diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt index 07850efa0fb..260aef265df 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt @@ -36,8 +36,9 @@ interface IrElementVisitor { 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 { // 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) - - } diff --git a/compiler/testData/ir/irText/classes/delegatedImplementation.txt b/compiler/testData/ir/irText/classes/delegatedImplementation.txt index b295c93498a..abad07840a8 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementation.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementation.txt @@ -51,7 +51,7 @@ FILE /delegatedImplementation.kt CONSTRUCTOR public constructor Test1() BLOCK_BODY INSTANCE_INITIALIZER_CALL classDescriptor=Test1 - DELEGATE val `Test1$IBase$delegate`: BaseImpl + PROPERTY val `Test1$IBase$delegate`: BaseImpl EXPRESSION_BODY GET_OBJECT BaseImpl type=BaseImpl FUN public open override /*1*/ /*delegation*/ fun foo(/*0*/ x: kotlin.Int, /*1*/ s: kotlin.String): kotlin.Unit @@ -74,7 +74,7 @@ FILE /delegatedImplementation.kt CONSTRUCTOR public constructor Test2() BLOCK_BODY INSTANCE_INITIALIZER_CALL classDescriptor=Test2 - DELEGATE val `Test2$IBase$delegate`: BaseImpl + PROPERTY val `Test2$IBase$delegate`: BaseImpl EXPRESSION_BODY GET_OBJECT BaseImpl type=BaseImpl FUN public open override /*1*/ /*delegation*/ fun foo(/*0*/ x: kotlin.Int, /*1*/ s: kotlin.String): kotlin.Unit @@ -93,7 +93,7 @@ FILE /delegatedImplementation.kt CALL .qux type=kotlin.Unit operator=null $this: GET_VAR Test2$IBase$delegate type=BaseImpl operator=null $receiver: $RECEIVER of: qux type=kotlin.String - DELEGATE val `Test2$IOther$delegate`: IOther + PROPERTY val `Test2$IOther$delegate`: IOther EXPRESSION_BODY CALL .otherImpl type=IOther operator=null x0: CONST String type=kotlin.String value='' diff --git a/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.txt b/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.txt index 276fe1b78f3..1c89217f3db 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.txt @@ -14,7 +14,7 @@ FILE /delegatedImplementationWithExplicitOverride.kt CONSTRUCTOR public constructor C() BLOCK_BODY INSTANCE_INITIALIZER_CALL classDescriptor=C - DELEGATE val `C$IFooBar$delegate`: FooBarImpl + PROPERTY val `C$IFooBar$delegate`: FooBarImpl EXPRESSION_BODY GET_OBJECT FooBarImpl type=FooBarImpl FUN public open override /*1*/ /*delegation*/ fun foo(): kotlin.Unit diff --git a/compiler/testData/ir/irText/declarations/delegatedProperties.txt b/compiler/testData/ir/irText/declarations/delegatedProperties.txt index 2344fefd47c..15fd9a2372c 100644 --- a/compiler/testData/ir/irText/declarations/delegatedProperties.txt +++ b/compiler/testData/ir/irText/declarations/delegatedProperties.txt @@ -1,6 +1,6 @@ FILE /delegatedProperties.kt PROPERTY public val test1: kotlin.Int - DELEGATE val `test1$delegate`: kotlin.Lazy + delegate: PROPERTY val `test1$delegate`: kotlin.Lazy EXPRESSION_BODY CALL .lazy type=kotlin.Lazy operator=null initializer: BLOCK type=() -> kotlin.Int operator=LAMBDA @@ -13,7 +13,7 @@ FILE /delegatedProperties.kt BLOCK_BODY RETURN type=kotlin.Nothing from= CALL .getValue type=kotlin.Int operator=null - $receiver: GET_VAR test1$delegate type=kotlin.Lazy operator=null + $receiver: GET_BACKING_FIELD test1$delegate type=kotlin.Lazy operator=null thisRef: CONST Null type=kotlin.Nothing? value='null' property: CALLABLE_REFERENCE public val test1: kotlin.Int type=kotlin.reflect.KProperty0 CLASS CLASS C @@ -26,7 +26,7 @@ FILE /delegatedProperties.kt EXPRESSION_BODY GET_VAR map type=kotlin.collections.MutableMap operator=INITIALIZE_PROPERTY_FROM_PARAMETER PROPERTY public final val test2: kotlin.Int - DELEGATE val `test2$delegate`: kotlin.Lazy + delegate: PROPERTY val `test2$delegate`: kotlin.Lazy EXPRESSION_BODY CALL .lazy type=kotlin.Lazy operator=null initializer: BLOCK type=() -> kotlin.Int operator=LAMBDA @@ -39,11 +39,11 @@ FILE /delegatedProperties.kt BLOCK_BODY RETURN type=kotlin.Nothing from= CALL .getValue type=kotlin.Int operator=null - $receiver: GET_VAR test2$delegate type=kotlin.Lazy operator=null + $receiver: GET_BACKING_FIELD test2$delegate type=kotlin.Lazy operator=null thisRef: THIS public final class C type=C property: CALLABLE_REFERENCE public final val test2: kotlin.Int type=kotlin.reflect.KProperty1 PROPERTY public final var test3: kotlin.Any - DELEGATE val `test3$delegate`: kotlin.collections.MutableMap + delegate: PROPERTY val `test3$delegate`: kotlin.collections.MutableMap EXPRESSION_BODY CALL . type=kotlin.collections.MutableMap operator=GET_PROPERTY $this: THIS public final class C type=C @@ -51,33 +51,33 @@ FILE /delegatedProperties.kt BLOCK_BODY RETURN type=kotlin.Nothing from= CALL .getValue type=kotlin.Any operator=null - $receiver: GET_VAR test3$delegate type=kotlin.collections.MutableMap operator=null + $receiver: GET_BACKING_FIELD test3$delegate type=kotlin.collections.MutableMap operator=null thisRef: THIS public final class C type=C property: CALLABLE_REFERENCE public final var test3: kotlin.Any type=kotlin.reflect.KMutableProperty1 PROPERTY_SETTER public final fun (/*0*/ : kotlin.Any): kotlin.Unit BLOCK_BODY RETURN type=kotlin.Nothing from= CALL .setValue type=kotlin.Unit operator=null - $receiver: GET_VAR test3$delegate type=kotlin.collections.MutableMap operator=null + $receiver: GET_BACKING_FIELD test3$delegate type=kotlin.collections.MutableMap operator=null thisRef: THIS public final class C type=C property: CALLABLE_REFERENCE public final var test3: kotlin.Any type=kotlin.reflect.KMutableProperty1 value: GET_VAR type=kotlin.Any operator=null PROPERTY public var test4: kotlin.Any - DELEGATE val `test4$delegate`: java.util.HashMap + delegate: PROPERTY val `test4$delegate`: java.util.HashMap EXPRESSION_BODY CALL .hashMapOf type=java.util.HashMap operator=null PROPERTY_GETTER public fun (): kotlin.Any BLOCK_BODY RETURN type=kotlin.Nothing from= CALL .getValue type=kotlin.Any operator=null - $receiver: GET_VAR test4$delegate type=java.util.HashMap operator=null + $receiver: GET_BACKING_FIELD test4$delegate type=java.util.HashMap operator=null thisRef: CONST Null type=kotlin.Nothing? value='null' property: CALLABLE_REFERENCE public var test4: kotlin.Any type=kotlin.reflect.KMutableProperty0 PROPERTY_SETTER public fun (/*0*/ : kotlin.Any): kotlin.Unit BLOCK_BODY RETURN type=kotlin.Nothing from= CALL .setValue type=kotlin.Unit operator=null - $receiver: GET_VAR test4$delegate type=java.util.HashMap operator=null + $receiver: GET_BACKING_FIELD test4$delegate type=java.util.HashMap operator=null thisRef: CONST Null type=kotlin.Nothing? value='null' property: CALLABLE_REFERENCE public var test4: kotlin.Any type=kotlin.reflect.KMutableProperty0 value: GET_VAR type=kotlin.Any operator=null diff --git a/compiler/testData/ir/irText/declarations/localDelegatedProperties.kt b/compiler/testData/ir/irText/declarations/localDelegatedProperties.kt new file mode 100644 index 00000000000..33c3df9b896 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/localDelegatedProperties.kt @@ -0,0 +1,4 @@ +fun test1() { + val x by lazy { 42 } + println(x) +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/declarations/localDelegatedProperties.txt b/compiler/testData/ir/irText/declarations/localDelegatedProperties.txt new file mode 100644 index 00000000000..cc11b75af34 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/localDelegatedProperties.txt @@ -0,0 +1,21 @@ +FILE /localDelegatedProperties.kt + FUN public fun test1(): kotlin.Unit + BLOCK_BODY + ? IrLocalDelegatedPropertyImpl x + VAR val `x$delegate`: kotlin.Lazy + CALL .lazy type=kotlin.Lazy operator=null + initializer: BLOCK type=() -> kotlin.Int operator=LAMBDA + FUN local final fun (): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from= + CONST Int type=kotlin.Int value='42' + CALLABLE_REFERENCE local final fun (): kotlin.Int type=() -> kotlin.Int + ? IrLocalPropertyAccessorImpl + BLOCK_BODY + RETURN type=kotlin.Nothing from= + CALL .getValue type=kotlin.Int operator=null + $receiver: GET_VAR x$delegate type=kotlin.Lazy operator=null + thisRef: CONST Null type=kotlin.Nothing? value='null' + property: CALLABLE_REFERENCE val x: kotlin.Int type=kotlin.reflect.KProperty0 + CALL .println type=kotlin.Unit operator=null + message: GET_VAR x type=kotlin.Int operator=null diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index da69652946b..c5d943b536e 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -184,6 +184,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("localDelegatedProperties.kt") + public void testLocalDelegatedProperties() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/declarations/localDelegatedProperties.kt"); + doTest(fileName); + } + @TestMetadata("typeAlias.kt") public void testTypeAlias() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/declarations/typeAlias.kt");