Delegated implementations for functions and extension functions.
This commit is contained in:
committed by
Dmitry Petrov
parent
2438876173
commit
d27f22ae0e
+1
-1
@@ -51,7 +51,7 @@ fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: R
|
||||
IrGetObjectValueImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
|
||||
receiver.classQualifier.descriptor)
|
||||
is ExtensionReceiver ->
|
||||
IrGetExtensionReceiverImpl(ktDefaultElement.startOffset, ktDefaultElement.startOffset, receiver.type,
|
||||
IrGetExtensionReceiverImpl(ktDefaultElement.startOffset, ktDefaultElement.startOffset,
|
||||
receiver.declarationDescriptor.extensionReceiverParameter!!)
|
||||
else ->
|
||||
TODO("Receiver: ${receiver.javaClass.simpleName}")
|
||||
|
||||
@@ -16,12 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir.generators
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrImplementingDelegateDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetVariableImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrOperator
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
@@ -29,6 +28,8 @@ import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import java.lang.AssertionError
|
||||
|
||||
class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator {
|
||||
override val context: GeneratorContext get() = declarationGenerator.context
|
||||
@@ -58,18 +59,28 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
|
||||
|
||||
private fun generateMembersDeclaredInSupertypeList(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
|
||||
ktClassOrObject.getSuperTypeList()?.let { ktSuperTypeList ->
|
||||
val delegatedMembers = irClass.descriptor.unsubstitutedMemberScope
|
||||
.getContributedDescriptors(DescriptorKindFilter.CALLABLES)
|
||||
.filterIsInstance<CallableMemberDescriptor>()
|
||||
.filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }
|
||||
if (delegatedMembers.isEmpty()) return
|
||||
|
||||
for (ktEntry in ktSuperTypeList.entries) {
|
||||
if (ktEntry is KtDelegatedSuperTypeEntry) {
|
||||
generateDelegatedImplementationMembers(irClass, ktEntry)
|
||||
generateDelegatedImplementationMembers(irClass, ktEntry, delegatedMembers)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateDelegatedImplementationMembers(irClass: IrClassImpl, ktEntry: KtDelegatedSuperTypeEntry) {
|
||||
private fun generateDelegatedImplementationMembers(irClass: IrClassImpl, ktEntry: KtDelegatedSuperTypeEntry,
|
||||
delegatedMembers: List<CallableMemberDescriptor>) {
|
||||
val ktDelegateExpression = ktEntry.delegateExpression!!
|
||||
val delegateType = getInferredTypeWithImplicitCastsOrFail(ktDelegateExpression)
|
||||
val superType = getOrFail(BindingContext.TYPE, ktEntry.typeReference!!)
|
||||
val superTypeConstructorDescriptor = superType.constructor.declarationDescriptor
|
||||
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)
|
||||
@@ -77,7 +88,51 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
|
||||
irDelegate.initializer = bodyGenerator.generatePropertyInitializerBody(ktDelegateExpression)
|
||||
irClass.addMember(irDelegate)
|
||||
|
||||
// TODO add delegated members
|
||||
for (delegatedMember in delegatedMembers) {
|
||||
val overriddenMember = delegatedMember.overriddenDescriptors.find { it.containingDeclaration.original == superClass.original }
|
||||
if (overriddenMember != null) {
|
||||
generateDelegatedMember(irClass, irDelegate, delegatedMember, overriddenMember)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateDelegatedMember(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegatedMember: CallableMemberDescriptor, overriddenMember: CallableMemberDescriptor) {
|
||||
when (delegatedMember) {
|
||||
is FunctionDescriptor ->
|
||||
generateDelegatedFunction(irClass, irDelegate, delegatedMember, overriddenMember as FunctionDescriptor)
|
||||
is PropertyDescriptor ->
|
||||
generateDelegatedProperty(irClass, irDelegate, delegatedMember, overriddenMember as PropertyDescriptor)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun generateDelegatedProperty(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegated: PropertyDescriptor, overridden: PropertyDescriptor) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
private fun generateDelegatedFunction(irClass: IrClassImpl, irDelegate: IrDelegateImpl, delegated: FunctionDescriptor, overridden: FunctionDescriptor) {
|
||||
val irFunction = IrFunctionImpl(irDelegate.startOffset, irDelegate.endOffset, IrDeclarationOrigin.DELEGATED_MEMBER, delegated)
|
||||
val irBlockBody = IrBlockBodyImpl(irDelegate.startOffset, irDelegate.endOffset)
|
||||
|
||||
val returnType = overridden.returnType!!
|
||||
val irCall = IrCallImpl(irDelegate.startOffset, irDelegate.endOffset, returnType, overridden)
|
||||
irCall.dispatchReceiver = IrGetVariableImpl(irDelegate.startOffset, irDelegate.endOffset, irDelegate.descriptor)
|
||||
irCall.extensionReceiver = delegated.extensionReceiverParameter?.let { extensionReceiver ->
|
||||
IrGetExtensionReceiverImpl(irDelegate.startOffset, irDelegate.endOffset, extensionReceiver)
|
||||
}
|
||||
irCall.mapValueParameters { overriddenValueParameter ->
|
||||
val delegatedValueParameter = delegated.valueParameters[overriddenValueParameter.index]
|
||||
IrGetVariableImpl(irDelegate.startOffset, irDelegate.endOffset, delegatedValueParameter)
|
||||
}
|
||||
if (KotlinBuiltIns.isUnit(returnType) || KotlinBuiltIns.isNothing(returnType)) {
|
||||
irBlockBody.addStatement(irCall)
|
||||
}
|
||||
else {
|
||||
irBlockBody.addStatement(IrReturnImpl(irDelegate.startOffset, irDelegate.endOffset, context.builtIns.nothingType, delegated, irCall))
|
||||
}
|
||||
|
||||
irFunction.body = irBlockBody
|
||||
irClass.addMember(irFunction)
|
||||
}
|
||||
|
||||
private fun generateAdditionalMembersForDataClass(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
|
||||
|
||||
+1
-5
@@ -285,11 +285,7 @@ class StatementGenerator(
|
||||
)
|
||||
is CallableDescriptor -> {
|
||||
val extensionReceiver = referenceTarget.extensionReceiverParameter ?: TODO("No extension receiver: $referenceTarget")
|
||||
IrGetExtensionReceiverImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
extensionReceiver.type,
|
||||
extensionReceiver
|
||||
)
|
||||
IrGetExtensionReceiverImpl(expression.startOffset, expression.endOffset, extensionReceiver)
|
||||
}
|
||||
else ->
|
||||
error("Expected this or receiver: $referenceTarget")
|
||||
|
||||
@@ -47,6 +47,7 @@ enum class IrDeclarationOrigin {
|
||||
DEFINED,
|
||||
DELEGATE,
|
||||
DELEGATED_PROPERTY_ACCESSOR,
|
||||
DELEGATED_MEMBER,
|
||||
CLASS_FOR_ENUM_ENTRY,
|
||||
ENUM_CLASS_SPECIAL_MEMBER,
|
||||
GENERATED_DATA_CLASS_MEMBER,
|
||||
|
||||
+2
-4
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.ir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
interface IrGetExtensionReceiver : IrDeclarationReference, IrExpressionWithCopy {
|
||||
override val descriptor: ReceiverParameterDescriptor
|
||||
@@ -29,12 +28,11 @@ interface IrGetExtensionReceiver : IrDeclarationReference, IrExpressionWithCopy
|
||||
class IrGetExtensionReceiverImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: KotlinType,
|
||||
descriptor: ReceiverParameterDescriptor
|
||||
) : IrTerminalDeclarationReferenceBase<ReceiverParameterDescriptor>(startOffset, endOffset, type, descriptor), IrGetExtensionReceiver {
|
||||
) : IrTerminalDeclarationReferenceBase<ReceiverParameterDescriptor>(startOffset, endOffset, descriptor.type, descriptor), IrGetExtensionReceiver {
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitGetExtensionReceiver(this, data)
|
||||
|
||||
override fun copy(): IrGetExtensionReceiver =
|
||||
IrGetExtensionReceiverImpl(startOffset, endOffset, type, descriptor)
|
||||
IrGetExtensionReceiverImpl(startOffset, endOffset, descriptor)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
interface IBase
|
||||
object BaseImpl : IBase
|
||||
interface IBase {
|
||||
fun foo(x: Int, s: String)
|
||||
fun bar(): Int
|
||||
fun String.qux()
|
||||
}
|
||||
|
||||
object BaseImpl : IBase {
|
||||
override fun foo(x: Int, s: String) {}
|
||||
override fun bar(): Int = 42
|
||||
override fun String.qux() {}
|
||||
}
|
||||
|
||||
interface IOther
|
||||
fun otherImpl(): IOther = object : IOther {}
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
FILE /delegatedImplementation.kt
|
||||
CLASS INTERFACE IBase
|
||||
FUN public abstract fun foo(/*0*/ x: kotlin.Int, /*1*/ s: kotlin.String): kotlin.Unit
|
||||
FUN public abstract fun bar(): kotlin.Int
|
||||
FUN public abstract fun kotlin.String.qux(): kotlin.Unit
|
||||
CLASS OBJECT BaseImpl
|
||||
CONSTRUCTOR private constructor BaseImpl()
|
||||
BLOCK_BODY
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor=BaseImpl
|
||||
FUN public open override /*1*/ fun foo(/*0*/ x: kotlin.Int, /*1*/ s: kotlin.String): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
FUN public open override /*1*/ fun bar(): kotlin.Int
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=bar
|
||||
CONST Int type=kotlin.Int value='42'
|
||||
FUN public open override /*1*/ fun kotlin.String.qux(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
CLASS INTERFACE IOther
|
||||
FUN public fun otherImpl(): IOther
|
||||
BLOCK_BODY
|
||||
@@ -21,6 +32,22 @@ FILE /delegatedImplementation.kt
|
||||
DELEGATE 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
|
||||
BLOCK_BODY
|
||||
CALL .foo type=kotlin.Unit operator=null
|
||||
$this: GET_VAR Test1$IBase$delegate type=BaseImpl operator=null
|
||||
x: GET_VAR x type=kotlin.Int operator=null
|
||||
s: GET_VAR s type=kotlin.String operator=null
|
||||
FUN public open override /*1*/ /*delegation*/ fun bar(): kotlin.Int
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=bar
|
||||
CALL .bar type=kotlin.Int operator=null
|
||||
$this: GET_VAR Test1$IBase$delegate type=BaseImpl operator=null
|
||||
FUN public open override /*1*/ /*delegation*/ fun kotlin.String.qux(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
CALL .qux type=kotlin.Unit operator=null
|
||||
$this: GET_VAR Test1$IBase$delegate type=BaseImpl operator=null
|
||||
$receiver: $RECEIVER of: qux type=kotlin.String
|
||||
CLASS CLASS Test2
|
||||
CONSTRUCTOR public constructor Test2()
|
||||
BLOCK_BODY
|
||||
@@ -28,6 +55,22 @@ FILE /delegatedImplementation.kt
|
||||
DELEGATE 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
|
||||
BLOCK_BODY
|
||||
CALL .foo type=kotlin.Unit operator=null
|
||||
$this: GET_VAR Test2$IBase$delegate type=BaseImpl operator=null
|
||||
x: GET_VAR x type=kotlin.Int operator=null
|
||||
s: GET_VAR s type=kotlin.String operator=null
|
||||
FUN public open override /*1*/ /*delegation*/ fun bar(): kotlin.Int
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=bar
|
||||
CALL .bar type=kotlin.Int operator=null
|
||||
$this: GET_VAR Test2$IBase$delegate type=BaseImpl operator=null
|
||||
FUN public open override /*1*/ /*delegation*/ fun kotlin.String.qux(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
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
|
||||
EXPRESSION_BODY
|
||||
CALL .otherImpl type=IOther operator=null
|
||||
|
||||
Reference in New Issue
Block a user