From f30027b4de7bf7d16ff6f8702122a585b6fceb4d Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Tue, 27 Sep 2016 12:37:31 +0300 Subject: [PATCH] Generate ir-accessors for interface properties --- .../jvm/lower/InterfaceDelegationLowering.kt | 4 +-- .../backend/jvm/lower/InterfaceLowering.kt | 19 ++++-------- .../psi2ir/generators/PropertyGenerator.kt | 2 -- .../classes/delegatedImplementation.txt | 30 ++++++++++++++++++ .../declarations/interfaceProperties.kt | 8 +++++ .../declarations/interfaceProperties.txt | 31 +++++++++++++++++++ .../kotlin/ir/IrTextTestCaseGenerated.java | 6 ++++ 7 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 compiler/testData/ir/irText/declarations/interfaceProperties.kt create mode 100644 compiler/testData/ir/irText/declarations/interfaceProperties.txt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt index a27fd7e592e..30d4ad4947f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt @@ -55,7 +55,7 @@ class InterfaceDelegationLowering(val state: GenerationState) : IrElementTransfo if (!interfaceFun.isDefinitelyNotDefaultImplsMethod()) { val inheritedFun = if (classDescriptor !== descriptor) { - InterfaceLowering.createDefaultImplFunDescriptor(descriptor as DefaultImplsClassDescriptorImpl, interfaceFun, classDescriptor) + InterfaceLowering.createDefaultImplFunDescriptor(descriptor as DefaultImplsClassDescriptorImpl, interfaceFun, classDescriptor, state.typeMapper) } else { value @@ -72,7 +72,7 @@ class InterfaceDelegationLowering(val state: GenerationState) : IrElementTransfo val interfaceDescriptor = interfaceFun.containingDeclaration as ClassDescriptor val defaultImpls = InterfaceLowering.createDefaultImplsClassDescriptor(interfaceDescriptor) - val defaultImplFun = InterfaceLowering.createDefaultImplFunDescriptor(defaultImpls, interfaceFun, interfaceDescriptor) + val defaultImplFun = InterfaceLowering.createDefaultImplFunDescriptor(defaultImpls, interfaceFun, interfaceDescriptor, state.typeMapper) val returnType = inheritedFun.returnType!! val irCallImpl = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, returnType, defaultImplFun, null, JvmLoweredStatementOrigin.DEFAULT_IMPLS_DELEGATION) irBody.statements.add(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, returnType, inheritedFun, irCallImpl)) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt index 9d9d8517ce7..e00519bce2c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt @@ -16,29 +16,21 @@ package org.jetbrains.kotlin.backend.jvm.lower -import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin -import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin -import org.jetbrains.kotlin.codegen.JvmCodegenUtil -import org.jetbrains.kotlin.codegen.isDefinitelyNotDefaultImplsMethod import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl -import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrDeclaration -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.load.java.JvmAbi @@ -53,7 +45,6 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid() return } - val interfaceDescriptor = irClass.descriptor val defaultImplsDescriptor = createDefaultImplsClassDescriptor(interfaceDescriptor) val defaultImplsIrClass = IrClassImpl(irClass.startOffset, irClass.endOffset, JvmLoweredDeclarationOrigin.DEFAULT_IMPLS, defaultImplsDescriptor) @@ -64,7 +55,7 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid() irClass.declarations.filterIsInstance().mapNotNull { val descriptor = it.descriptor if (descriptor.modality != Modality.ABSTRACT) { - val functionDescriptorImpl = createDefaultImplFunDescriptor(defaultImplsDescriptor, descriptor, interfaceDescriptor) + val functionDescriptorImpl = createDefaultImplFunDescriptor(defaultImplsDescriptor, descriptor, interfaceDescriptor, state.typeMapper) members.add(IrFunctionImpl(it.startOffset, it.endOffset, it.origin, functionDescriptorImpl, it.body)) it.body = null @@ -87,11 +78,13 @@ class InterfaceLowering(val state: GenerationState) : IrElementTransformerVoid() fun createDefaultImplFunDescriptor( defaultImplsDescriptor: DefaultImplsClassDescriptorImpl, descriptor: FunctionDescriptor, - interfaceDescriptor: ClassDescriptor + interfaceDescriptor: ClassDescriptor, typeMapper: KotlinTypeMapper ): SimpleFunctionDescriptorImpl { val newFunction = SimpleFunctionDescriptorImpl.create( - defaultImplsDescriptor, AnnotationsImpl(emptyList()), descriptor.name, descriptor.kind, descriptor.source + defaultImplsDescriptor, AnnotationsImpl(emptyList()), + Name.identifier(typeMapper.mapAsmMethod(descriptor).name), + descriptor.kind, descriptor.source ) val valueParameters = diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt index cbe361b9186..f3bd12a908c 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt @@ -110,7 +110,6 @@ class PropertyGenerator(val declarationGenerator: DeclarationGenerator) : Genera val getter = property.getter ?: return null val ktGetter = ktProperty.getter - if (DescriptorUtils.isInterface(property.containingDeclaration) && ktGetter == null) return null val irGetter = ktGetter?.let { IrFunctionImpl(it.startOffset, it.endOffset, IrDeclarationOrigin.DEFINED, getter) @@ -128,7 +127,6 @@ class PropertyGenerator(val declarationGenerator: DeclarationGenerator) : Genera val setter = property.setter ?: return null val ktSetter = ktProperty.setter - if (DescriptorUtils.isInterface(property.containingDeclaration) && ktSetter == null) return null val irSetter = ktSetter?.let { IrFunctionImpl(it.startOffset, it.endOffset, IrDeclarationOrigin.DEFINED, setter) diff --git a/compiler/testData/ir/irText/classes/delegatedImplementation.txt b/compiler/testData/ir/irText/classes/delegatedImplementation.txt index f52ebc6b71f..b81b7c3a8ef 100644 --- a/compiler/testData/ir/irText/classes/delegatedImplementation.txt +++ b/compiler/testData/ir/irText/classes/delegatedImplementation.txt @@ -18,9 +18,39 @@ FILE /delegatedImplementation.kt BLOCK_BODY CLASS INTERFACE IOther PROPERTY public abstract val x: kotlin.String + FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun (): kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): String' + GET_FIELD 'x: String' type=kotlin.String origin=null + receiver: THIS of 'IOther' type=IOther PROPERTY public abstract var y: kotlin.Int + FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun (): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'y: Int' type=kotlin.Int origin=null + receiver: THIS of 'IOther' type=IOther + FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun (: kotlin.Int): kotlin.Unit + BLOCK_BODY + SET_FIELD 'y: Int' type=kotlin.Unit origin=null + receiver: THIS of 'IOther' type=IOther + value: GET_VAR 'value-parameter : Int' type=kotlin.Int origin=null PROPERTY public abstract val kotlin.Byte.z1: kotlin.Int + FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun kotlin.Byte.(): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='() on Byte: Int' + GET_FIELD 'z1: Int on Byte' type=kotlin.Int origin=null + receiver: THIS of 'IOther' type=IOther PROPERTY public abstract var kotlin.Byte.z2: kotlin.Int + FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun kotlin.Byte.(): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='() on Byte: Int' + GET_FIELD 'z2: Int on Byte' type=kotlin.Int origin=null + receiver: THIS of 'IOther' type=IOther + FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun kotlin.Byte.(: kotlin.Int): kotlin.Unit + BLOCK_BODY + SET_FIELD 'z2: Int on Byte' type=kotlin.Unit origin=null + receiver: THIS of 'IOther' type=IOther + value: GET_VAR 'value-parameter : Int' type=kotlin.Int origin=null FUN public fun otherImpl(x0: kotlin.String, y0: kotlin.Int): IOther BLOCK_BODY RETURN type=kotlin.Nothing from='otherImpl(String, Int): IOther' diff --git a/compiler/testData/ir/irText/declarations/interfaceProperties.kt b/compiler/testData/ir/irText/declarations/interfaceProperties.kt new file mode 100644 index 00000000000..6570c71d638 --- /dev/null +++ b/compiler/testData/ir/irText/declarations/interfaceProperties.kt @@ -0,0 +1,8 @@ +// WITH_RUNTIME + +interface C { + val test1: Int + val test2: Int get() = 0 + var test3: Int + var test4: Int get() = 0; set(value) {} +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/declarations/interfaceProperties.txt b/compiler/testData/ir/irText/declarations/interfaceProperties.txt new file mode 100644 index 00000000000..9fc7e69856b --- /dev/null +++ b/compiler/testData/ir/irText/declarations/interfaceProperties.txt @@ -0,0 +1,31 @@ +FILE /interfaceProperties.kt + CLASS INTERFACE C + PROPERTY public abstract val test1: kotlin.Int + FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun (): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'test1: Int' type=kotlin.Int origin=null + receiver: THIS of 'C' type=C + PROPERTY public open val test2: kotlin.Int + FUN public open fun (): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + CONST Int type=kotlin.Int value='0' + PROPERTY public abstract var test3: kotlin.Int + FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun (): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'test3: Int' type=kotlin.Int origin=null + receiver: THIS of 'C' type=C + FUN DEFAULT_PROPERTY_ACCESSOR public abstract fun (: kotlin.Int): kotlin.Unit + BLOCK_BODY + SET_FIELD 'test3: Int' type=kotlin.Unit origin=null + receiver: THIS of 'C' type=C + value: GET_VAR 'value-parameter : Int' type=kotlin.Int origin=null + PROPERTY public open var test4: kotlin.Int + FUN public open fun (): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + CONST Int type=kotlin.Int value='0' + FUN public open fun (value: kotlin.Int): kotlin.Unit + BLOCK_BODY diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index c771f997f3e..15fc67d867e 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -214,6 +214,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("interfaceProperties.kt") + public void testInterfaceProperties() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/declarations/interfaceProperties.kt"); + doTest(fileName); + } + @TestMetadata("localDelegatedProperties.kt") public void testLocalDelegatedProperties() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/declarations/localDelegatedProperties.kt");