Delegated implementations for properties and extension properties.
This commit is contained in:
committed by
Dmitry Petrov
parent
d27f22ae0e
commit
e42116bb6a
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import java.lang.AssertionError
|
|
||||||
|
|
||||||
class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator {
|
class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator {
|
||||||
override val context: GeneratorContext get() = declarationGenerator.context
|
override val context: GeneratorContext get() = declarationGenerator.context
|
||||||
@@ -107,13 +106,29 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDelegatedProperty(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegated: PropertyDescriptor, overridden: PropertyDescriptor) {
|
private fun generateDelegatedProperty(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegated: PropertyDescriptor, overridden: PropertyDescriptor) {
|
||||||
// TODO
|
val irProperty = IrSimplePropertyImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated)
|
||||||
|
|
||||||
|
val irGetter = IrPropertyGetterImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated.getter!!)
|
||||||
|
irGetter.body = generateDelegateFunctionBody(irDelegate, delegated.getter!!, overridden.getter!!)
|
||||||
|
irProperty.getter = irGetter
|
||||||
|
|
||||||
|
if (delegated.isVar) {
|
||||||
|
val irSetter = IrPropertySetterImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated.setter!!)
|
||||||
|
irSetter.body = generateDelegateFunctionBody(irDelegate, delegated.setter!!, overridden.setter!!)
|
||||||
|
irProperty.setter = irSetter
|
||||||
|
}
|
||||||
|
|
||||||
|
irClass.addMember(irProperty)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDelegatedFunction(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegated: FunctionDescriptor, overridden: FunctionDescriptor) {
|
private fun generateDelegatedFunction(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegated: FunctionDescriptor, overridden: FunctionDescriptor) {
|
||||||
val irFunction = IrFunctionImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated)
|
val irFunction = IrFunctionImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated)
|
||||||
val irBlockBody = IrBlockBodyImpl(irDelegate.startOffset, irDelegate.endOffset)
|
irFunction.body = generateDelegateFunctionBody(irDelegate, delegated, overridden)
|
||||||
|
irClass.addMember(irFunction)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateDelegateFunctionBody(irDelegate: IrDelegateImpl, delegated: FunctionDescriptor, overridden: FunctionDescriptor): IrBlockBodyImpl {
|
||||||
|
val irBlockBody = IrBlockBodyImpl(irDelegate.startOffset, irDelegate.endOffset)
|
||||||
val returnType = overridden.returnType!!
|
val returnType = overridden.returnType!!
|
||||||
val irCall = IrCallImpl(irDelegate.startOffset, irDelegate.endOffset, returnType, overridden)
|
val irCall = IrCallImpl(irDelegate.startOffset, irDelegate.endOffset, returnType, overridden)
|
||||||
irCall.dispatchReceiver = IrGetVariableImpl(irDelegate.startOffset, irDelegate.endOffset, irDelegate.descriptor)
|
irCall.dispatchReceiver = IrGetVariableImpl(irDelegate.startOffset, irDelegate.endOffset, irDelegate.descriptor)
|
||||||
@@ -128,11 +143,10 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
|
|||||||
irBlockBody.addStatement(irCall)
|
irBlockBody.addStatement(irCall)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
irBlockBody.addStatement(IrReturnImpl(irDelegate.startOffset, irDelegate.endOffset, context.builtIns.nothingType, delegated, irCall))
|
val irReturn = IrReturnImpl(irDelegate.startOffset, irDelegate.endOffset, context.builtIns.nothingType, delegated, irCall)
|
||||||
|
irBlockBody.addStatement(irReturn)
|
||||||
}
|
}
|
||||||
|
return irBlockBody
|
||||||
irFunction.body = irBlockBody
|
|
||||||
irClass.addMember(irFunction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateAdditionalMembersForDataClass(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
|
private fun generateAdditionalMembersForDataClass(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
|
||||||
|
|||||||
@@ -43,17 +43,25 @@ interface IrPropertySetter : IrPropertyAccessor {
|
|||||||
abstract class IrPropertyAccessorBase(
|
abstract class IrPropertyAccessorBase(
|
||||||
startOffset: Int,
|
startOffset: Int,
|
||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
origin: IrDeclarationOrigin,
|
origin: IrDeclarationOrigin
|
||||||
body: IrBody
|
) : IrGeneralFunctionBase(startOffset, endOffset, origin), IrPropertyAccessor
|
||||||
) : IrGeneralFunctionBase(startOffset, endOffset, origin, body), IrPropertyAccessor
|
|
||||||
|
|
||||||
class IrPropertyGetterImpl(
|
class IrPropertyGetterImpl(
|
||||||
startOffset: Int,
|
startOffset: Int,
|
||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
origin: IrDeclarationOrigin,
|
origin: IrDeclarationOrigin,
|
||||||
override val descriptor: PropertyGetterDescriptor,
|
override val descriptor: PropertyGetterDescriptor
|
||||||
body: IrBody
|
) : IrPropertyAccessorBase(startOffset, endOffset, origin), IrPropertyGetter {
|
||||||
) : IrPropertyAccessorBase(startOffset, endOffset, origin, body), IrPropertyGetter {
|
constructor(
|
||||||
|
startOffset: Int,
|
||||||
|
endOffset: Int,
|
||||||
|
origin: IrDeclarationOrigin,
|
||||||
|
descriptor: PropertyGetterDescriptor,
|
||||||
|
body: IrBody
|
||||||
|
) : this(startOffset, endOffset, origin, descriptor) {
|
||||||
|
this.body = body
|
||||||
|
}
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||||
visitor.visitPropertyGetter(this, data)
|
visitor.visitPropertyGetter(this, data)
|
||||||
}
|
}
|
||||||
@@ -62,9 +70,18 @@ class IrPropertySetterImpl(
|
|||||||
startOffset: Int,
|
startOffset: Int,
|
||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
origin: IrDeclarationOrigin,
|
origin: IrDeclarationOrigin,
|
||||||
override val descriptor: PropertySetterDescriptor,
|
override val descriptor: PropertySetterDescriptor
|
||||||
body: IrBody
|
) : IrPropertyAccessorBase(startOffset, endOffset, origin), IrPropertySetter {
|
||||||
) : IrPropertyAccessorBase(startOffset, endOffset, origin, body), IrPropertySetter {
|
constructor(
|
||||||
|
startOffset: Int,
|
||||||
|
endOffset: Int,
|
||||||
|
origin: IrDeclarationOrigin,
|
||||||
|
descriptor: PropertySetterDescriptor,
|
||||||
|
body: IrBody
|
||||||
|
) : this(startOffset, endOffset, origin, descriptor) {
|
||||||
|
this.body = body
|
||||||
|
}
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||||
visitor.visitPropertySetter(this, data)
|
visitor.visitPropertySetter(this, data)
|
||||||
}
|
}
|
||||||
@@ -10,9 +10,22 @@ object BaseImpl : IBase {
|
|||||||
override fun String.qux() {}
|
override fun String.qux() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IOther
|
interface IOther {
|
||||||
fun otherImpl(): IOther = object : IOther {}
|
val x: String
|
||||||
|
var y: Int
|
||||||
|
val Byte.z1: Int
|
||||||
|
var Byte.z2: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
fun otherImpl(x0: String, y0: Int): IOther = object : IOther {
|
||||||
|
override val x: String = x0
|
||||||
|
override var y: Int = y0
|
||||||
|
override val Byte.z1: Int get() = 1
|
||||||
|
override var Byte.z2: Int
|
||||||
|
get() = 2
|
||||||
|
set(value) {}
|
||||||
|
}
|
||||||
|
|
||||||
class Test1 : IBase by BaseImpl
|
class Test1 : IBase by BaseImpl
|
||||||
|
|
||||||
class Test2 : IBase by BaseImpl, IOther by otherImpl()
|
class Test2 : IBase by BaseImpl, IOther by otherImpl("", 42)
|
||||||
@@ -16,7 +16,11 @@ FILE /delegatedImplementation.kt
|
|||||||
FUN public open override /*1*/ fun kotlin.String.qux(): kotlin.Unit
|
FUN public open override /*1*/ fun kotlin.String.qux(): kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
CLASS INTERFACE IOther
|
CLASS INTERFACE IOther
|
||||||
FUN public fun otherImpl(): IOther
|
PROPERTY public abstract val x: kotlin.String
|
||||||
|
PROPERTY public abstract var y: kotlin.Int
|
||||||
|
PROPERTY public abstract val kotlin.Byte.z1: kotlin.Int
|
||||||
|
PROPERTY public abstract var kotlin.Byte.z2: kotlin.Int
|
||||||
|
FUN public fun otherImpl(/*0*/ x0: kotlin.String, /*1*/ y0: kotlin.Int): IOther
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from=otherImpl
|
RETURN type=kotlin.Nothing from=otherImpl
|
||||||
BLOCK type=otherImpl.<no name provided> operator=OBJECT_LITERAL
|
BLOCK type=otherImpl.<no name provided> operator=OBJECT_LITERAL
|
||||||
@@ -24,6 +28,24 @@ FILE /delegatedImplementation.kt
|
|||||||
CONSTRUCTOR public constructor <no name provided>()
|
CONSTRUCTOR public constructor <no name provided>()
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
INSTANCE_INITIALIZER_CALL classDescriptor=<no name provided>
|
INSTANCE_INITIALIZER_CALL classDescriptor=<no name provided>
|
||||||
|
PROPERTY public open override /*1*/ val x: kotlin.String
|
||||||
|
EXPRESSION_BODY
|
||||||
|
GET_VAR x0 type=kotlin.String operator=null
|
||||||
|
PROPERTY public open override /*1*/ var y: kotlin.Int
|
||||||
|
EXPRESSION_BODY
|
||||||
|
GET_VAR y0 type=kotlin.Int operator=null
|
||||||
|
PROPERTY public open override /*1*/ val kotlin.Byte.z1: kotlin.Int
|
||||||
|
PROPERTY_GETTER public open override /*1*/ fun kotlin.Byte.<get-z1>(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from=<get-z1>
|
||||||
|
CONST Int type=kotlin.Int value='1'
|
||||||
|
PROPERTY public open override /*1*/ var kotlin.Byte.z2: kotlin.Int
|
||||||
|
PROPERTY_GETTER public open override /*1*/ fun kotlin.Byte.<get-z2>(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from=<get-z2>
|
||||||
|
CONST Int type=kotlin.Int value='2'
|
||||||
|
PROPERTY_SETTER public open override /*1*/ fun kotlin.Byte.<set-z2>(/*0*/ value: kotlin.Int): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
CALL .<init> type=otherImpl.<no name provided> operator=OBJECT_LITERAL
|
CALL .<init> type=otherImpl.<no name provided> operator=OBJECT_LITERAL
|
||||||
CLASS CLASS Test1
|
CLASS CLASS Test1
|
||||||
CONSTRUCTOR public constructor Test1()
|
CONSTRUCTOR public constructor Test1()
|
||||||
@@ -74,3 +96,42 @@ FILE /delegatedImplementation.kt
|
|||||||
DELEGATE val `Test2$IOther$delegate`: IOther
|
DELEGATE val `Test2$IOther$delegate`: IOther
|
||||||
EXPRESSION_BODY
|
EXPRESSION_BODY
|
||||||
CALL .otherImpl type=IOther operator=null
|
CALL .otherImpl type=IOther operator=null
|
||||||
|
x0: CONST String type=kotlin.String value=''
|
||||||
|
y0: CONST Int type=kotlin.Int value='42'
|
||||||
|
PROPERTY public open override /*1*/ /*delegation*/ val x: kotlin.String
|
||||||
|
PROPERTY_GETTER public open override /*1*/ /*delegation*/ fun <get-x>(): kotlin.String
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from=<get-x>
|
||||||
|
CALL .<get-x> type=kotlin.String operator=null
|
||||||
|
$this: GET_VAR Test2$IOther$delegate type=IOther operator=null
|
||||||
|
PROPERTY public open override /*1*/ /*delegation*/ var y: kotlin.Int
|
||||||
|
PROPERTY_GETTER public open override /*1*/ /*delegation*/ fun <get-y>(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from=<get-y>
|
||||||
|
CALL .<get-y> type=kotlin.Int operator=null
|
||||||
|
$this: GET_VAR Test2$IOther$delegate type=IOther operator=null
|
||||||
|
PROPERTY_SETTER public open override /*1*/ /*delegation*/ fun <set-y>(/*0*/ <set-?>: kotlin.Int): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL .<set-y> type=kotlin.Unit operator=null
|
||||||
|
$this: GET_VAR Test2$IOther$delegate type=IOther operator=null
|
||||||
|
<set-?>: GET_VAR <set-?> type=kotlin.Int operator=null
|
||||||
|
PROPERTY public open override /*1*/ /*delegation*/ val kotlin.Byte.z1: kotlin.Int
|
||||||
|
PROPERTY_GETTER public open override /*1*/ /*delegation*/ fun kotlin.Byte.<get-z1>(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from=<get-z1>
|
||||||
|
CALL .<get-z1> type=kotlin.Int operator=null
|
||||||
|
$this: GET_VAR Test2$IOther$delegate type=IOther operator=null
|
||||||
|
$receiver: $RECEIVER of: z1 type=kotlin.Byte
|
||||||
|
PROPERTY public open override /*1*/ /*delegation*/ var kotlin.Byte.z2: kotlin.Int
|
||||||
|
PROPERTY_GETTER public open override /*1*/ /*delegation*/ fun kotlin.Byte.<get-z2>(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from=<get-z2>
|
||||||
|
CALL .<get-z2> type=kotlin.Int operator=null
|
||||||
|
$this: GET_VAR Test2$IOther$delegate type=IOther operator=null
|
||||||
|
$receiver: $RECEIVER of: z2 type=kotlin.Byte
|
||||||
|
PROPERTY_SETTER public open override /*1*/ /*delegation*/ fun kotlin.Byte.<set-z2>(/*0*/ <set-?>: kotlin.Int): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL .<set-z2> type=kotlin.Unit operator=null
|
||||||
|
$this: GET_VAR Test2$IOther$delegate type=IOther operator=null
|
||||||
|
$receiver: $RECEIVER of: z2 type=kotlin.Byte
|
||||||
|
<set-?>: GET_VAR <set-?> type=kotlin.Int operator=null
|
||||||
|
|||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
interface IFooBar {
|
||||||
|
fun foo()
|
||||||
|
fun bar()
|
||||||
|
}
|
||||||
|
|
||||||
|
object FooBarImpl : IFooBar {
|
||||||
|
override fun foo() {}
|
||||||
|
override fun bar() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class C : IFooBar by FooBarImpl {
|
||||||
|
override fun bar() {}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
FILE /delegatedImplementationWithExplicitOverride.kt
|
||||||
|
CLASS INTERFACE IFooBar
|
||||||
|
FUN public abstract fun foo(): kotlin.Unit
|
||||||
|
FUN public abstract fun bar(): kotlin.Unit
|
||||||
|
CLASS OBJECT FooBarImpl
|
||||||
|
CONSTRUCTOR private constructor FooBarImpl()
|
||||||
|
BLOCK_BODY
|
||||||
|
INSTANCE_INITIALIZER_CALL classDescriptor=FooBarImpl
|
||||||
|
FUN public open override /*1*/ fun foo(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
FUN public open override /*1*/ fun bar(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CLASS CLASS C
|
||||||
|
CONSTRUCTOR public constructor C()
|
||||||
|
BLOCK_BODY
|
||||||
|
INSTANCE_INITIALIZER_CALL classDescriptor=C
|
||||||
|
DELEGATE val `C$IFooBar$delegate`: FooBarImpl
|
||||||
|
EXPRESSION_BODY
|
||||||
|
GET_OBJECT FooBarImpl type=FooBarImpl
|
||||||
|
FUN public open override /*1*/ /*delegation*/ fun foo(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL .foo type=kotlin.Unit operator=null
|
||||||
|
$this: GET_VAR C$IFooBar$delegate type=FooBarImpl operator=null
|
||||||
|
FUN public open override /*1*/ fun bar(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
@@ -79,6 +79,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("delegatedImplementationWithExplicitOverride.kt")
|
||||||
|
public void testDelegatedImplementationWithExplicitOverride() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/delegatedImplementationWithExplicitOverride.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("delegatingConstructorCallsInSecondaryConstructors.kt")
|
@TestMetadata("delegatingConstructorCallsInSecondaryConstructors.kt")
|
||||||
public void testDelegatingConstructorCallsInSecondaryConstructors() throws Exception {
|
public void testDelegatingConstructorCallsInSecondaryConstructors() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/delegatingConstructorCallsInSecondaryConstructors.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/delegatingConstructorCallsInSecondaryConstructors.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user