[FIR] Support dispatch & extension receiver in component calls

This commit is contained in:
Mikhail Glukhikh
2020-04-08 17:08:03 +03:00
parent a93c7a39e0
commit cd5a4900e6
35 changed files with 25 additions and 45 deletions
@@ -37,6 +37,8 @@ class FirComponentCallBuilder : FirCallBuilder, FirAnnotationContainerBuilder, F
override var source: FirSourceElement? = null override var source: FirSourceElement? = null
override val annotations: MutableList<FirAnnotationCall> = mutableListOf() override val annotations: MutableList<FirAnnotationCall> = mutableListOf()
val typeArguments: MutableList<FirTypeProjection> = mutableListOf() val typeArguments: MutableList<FirTypeProjection> = mutableListOf()
var dispatchReceiver: FirExpression = FirNoReceiverExpression
var extensionReceiver: FirExpression = FirNoReceiverExpression
override var argumentList: FirArgumentList = FirEmptyArgumentList override var argumentList: FirArgumentList = FirEmptyArgumentList
lateinit var explicitReceiver: FirExpression lateinit var explicitReceiver: FirExpression
var componentIndex: Int by kotlin.properties.Delegates.notNull<Int>() var componentIndex: Int by kotlin.properties.Delegates.notNull<Int>()
@@ -46,6 +48,8 @@ class FirComponentCallBuilder : FirCallBuilder, FirAnnotationContainerBuilder, F
source, source,
annotations, annotations,
typeArguments, typeArguments,
dispatchReceiver,
extensionReceiver,
argumentList, argumentList,
explicitReceiver, explicitReceiver,
componentIndex, componentIndex,
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirArgumentList import org.jetbrains.kotlin.fir.expressions.FirArgumentList
import org.jetbrains.kotlin.fir.expressions.FirComponentCall import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeProjection
@@ -30,14 +29,14 @@ internal class FirComponentCallImpl(
override val source: FirSourceElement?, override val source: FirSourceElement?,
override val annotations: MutableList<FirAnnotationCall>, override val annotations: MutableList<FirAnnotationCall>,
override val typeArguments: MutableList<FirTypeProjection>, override val typeArguments: MutableList<FirTypeProjection>,
override var dispatchReceiver: FirExpression,
override var extensionReceiver: FirExpression,
override var argumentList: FirArgumentList, override var argumentList: FirArgumentList,
override var explicitReceiver: FirExpression, override var explicitReceiver: FirExpression,
override val componentIndex: Int, override val componentIndex: Int,
) : FirComponentCall() { ) : FirComponentCall() {
override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null) override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
override val safe: Boolean get() = false override val safe: Boolean get() = false
override val dispatchReceiver: FirExpression get() = FirNoReceiverExpression
override val extensionReceiver: FirExpression get() = FirNoReceiverExpression
override var calleeReference: FirNamedReference = FirSimpleNamedReference(source, Name.identifier("component$componentIndex"), null) override var calleeReference: FirNamedReference = FirSimpleNamedReference(source, Name.identifier("component$componentIndex"), null)
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) { override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
@@ -62,6 +61,12 @@ internal class FirComponentCallImpl(
argumentList = argumentList.transformSingle(transformer, data) argumentList = argumentList.transformSingle(transformer, data)
transformCalleeReference(transformer, data) transformCalleeReference(transformer, data)
explicitReceiver = explicitReceiver.transformSingle(transformer, data) explicitReceiver = explicitReceiver.transformSingle(transformer, data)
if (dispatchReceiver !== explicitReceiver) {
dispatchReceiver = dispatchReceiver.transformSingle(transformer, data)
}
if (extensionReceiver !== explicitReceiver && extensionReceiver !== dispatchReceiver) {
extensionReceiver = extensionReceiver.transformSingle(transformer, data)
}
return this return this
} }
@@ -76,10 +81,12 @@ internal class FirComponentCallImpl(
} }
override fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirComponentCallImpl { override fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirComponentCallImpl {
dispatchReceiver = dispatchReceiver.transformSingle(transformer, data)
return this return this
} }
override fun <D> transformExtensionReceiver(transformer: FirTransformer<D>, data: D): FirComponentCallImpl { override fun <D> transformExtensionReceiver(transformer: FirTransformer<D>, data: D): FirComponentCallImpl {
extensionReceiver = extensionReceiver.transformSingle(transformer, data)
return this return this
} }
@@ -125,6 +125,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
builder(componentCall) { builder(componentCall) {
parents += callBuilder parents += callBuilder
defaultNoReceivers(notNullExplicitReceiver = true)
default("argumentList") { default("argumentList") {
value = "FirEmptyArgumentList" value = "FirEmptyArgumentList"
} }
@@ -97,14 +97,8 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
value = "false" value = "false"
withGetter = true withGetter = true
} }
listOf("dispatchReceiver", "extensionReceiver").forEach {
default(it) {
value = "FirNoReceiverExpression"
withGetter = true
}
}
default("calleeReference", "FirSimpleNamedReference(source, Name.identifier(\"component\$componentIndex\"), null)") default("calleeReference", "FirSimpleNamedReference(source, Name.identifier(\"component\$componentIndex\"), null)")
useTypes(simpleNamedReferenceType, nameType, noReceiverExpressionType) useTypes(simpleNamedReferenceType, nameType)
optInToInternals() optInToInternals()
} }
@@ -23,8 +23,10 @@ abstract class AbstractBuilderConfigurator<T : AbstractFirTreeBuilder>(val firTr
types.forEach { builder.usedTypes += it } types.forEach { builder.usedTypes += it }
} }
fun defaultNoReceivers() { fun defaultNoReceivers(notNullExplicitReceiver: Boolean = false) {
defaultNull("explicitReceiver") if (!notNullExplicitReceiver) {
defaultNull("explicitReceiver")
}
default("dispatchReceiver", "FirNoReceiverExpression") default("dispatchReceiver", "FirNoReceiverExpression")
default("extensionReceiver", "FirNoReceiverExpression") default("extensionReceiver", "FirNoReceiverExpression")
useTypes(noReceiverExpressionType) useTypes(noReceiverExpressionType)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class C(val i: Int) { class C(val i: Int) {
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class C(val i: Int) { class C(val i: Int) {
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Int.component1() = this + 1 operator fun Int.component1() = this + 1
operator fun Int.component2() = this + 2 operator fun Int.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Int.component1() = this + 1 operator fun Int.component1() = this + 1
operator fun Int.component2() = this + 2 operator fun Int.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Long.component1() = this + 1 operator fun Long.component1() = this + 1
operator fun Long.component2() = this + 2 operator fun Long.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Long.component1() = this + 1 operator fun Long.component1() = this + 1
operator fun Long.component2() = this + 2 operator fun Long.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A<T>(val x: String, val y: String, val z: T) class A<T>(val x: String, val y: String, val z: T)
fun <T> foo(a: A<T>, block: (A<T>) -> String): String = block(a) fun <T> foo(a: A<T>, block: (A<T>) -> String): String = block(a)
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
// WITH_RUNTIME // WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
class C(val i: Int) { class C(val i: Int) {
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
class C(val i: Int) { class C(val i: Int) {
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Range(val from : C, val to: C) { class Range(val from : C, val to: C) {
operator fun iterator() = It(from, to) operator fun iterator() = It(from, to)
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Range(val from : C, val to: C) { class Range(val from : C, val to: C) {
operator fun iterator() = It(from, to) operator fun iterator() = It(from, to)
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Range(val from : C, val to: C) { class Range(val from : C, val to: C) {
operator fun iterator() = It(from, to) operator fun iterator() = It(from, to)
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Range(val from : C, val to: C) { class Range(val from : C, val to: C) {
operator fun iterator() = It(from, to) operator fun iterator() = It(from, to)
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Int.component1() = this + 1 operator fun Int.component1() = this + 1
operator fun Int.component2() = this + 2 operator fun Int.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Int.component1() = this + 1 operator fun Int.component1() = this + 1
operator fun Int.component2() = this + 2 operator fun Int.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Long.component1() = this + 1 operator fun Long.component1() = this + 1
operator fun Long.component2() = this + 2 operator fun Long.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Long.component1() = this + 1 operator fun Long.component1() = this + 1
operator fun Long.component2() = this + 2 operator fun Long.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Range(val from : C, val to: C) { class Range(val from : C, val to: C) {
operator fun iterator() = It(from, to) operator fun iterator() = It(from, to)
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Range(val from : C, val to: C) { class Range(val from : C, val to: C) {
operator fun iterator() = It(from, to) operator fun iterator() = It(from, to)
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Int.component1() = this + 1 operator fun Int.component1() = this + 1
operator fun Int.component2() = this + 2 operator fun Int.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Int.component1() = this + 1 operator fun Int.component1() = this + 1
operator fun Int.component2() = this + 2 operator fun Int.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Long.component1() = this + 1 operator fun Long.component1() = this + 1
operator fun Long.component2() = this + 2 operator fun Long.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Long.component1() = this + 1 operator fun Long.component1() = this + 1
operator fun Long.component2() = this + 2 operator fun Long.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Int.component1() = this + 1 operator fun Int.component1() = this + 1
operator fun Int.component2() = this + 2 operator fun Int.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Int.component1() = this + 1 operator fun Int.component1() = this + 1
operator fun Int.component2() = this + 2 operator fun Int.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Long.component1() = this + 1 operator fun Long.component1() = this + 1
operator fun Long.component2() = this + 2 operator fun Long.component2() = this + 2
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class M { class M {
operator fun Long.component1() = this + 1 operator fun Long.component1() = this + 1
operator fun Long.component2() = this + 2 operator fun Long.component2() = this + 2
@@ -56,9 +56,9 @@ FILE fqName:<root> fileName:/destructuring1.kt
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
VAR name:x type:kotlin.Int [val] VAR name:x type:kotlin.Int [val]
CALL 'public final fun component1 (): kotlin.Int [operator] declared in <root>.B' type=kotlin.Int origin=null CALL 'public final fun component1 (): kotlin.Int [operator] declared in <root>.B' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null $this: GET_VAR '<this>: <root>.B declared in <root>.test' type=<root>.B origin=null
$receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null $receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null
VAR name:y type:kotlin.Int [val] VAR name:y type:kotlin.Int [val]
CALL 'public final fun component2 (): kotlin.Int [operator] declared in <root>.B' type=kotlin.Int origin=null CALL 'public final fun component2 (): kotlin.Int [operator] declared in <root>.B' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null $this: GET_VAR '<this>: <root>.B declared in <root>.test' type=<root>.B origin=null
$receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null $receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null
@@ -62,13 +62,13 @@ FILE fqName:<root> fileName:/destructuringWithUnderscore.kt
GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A GET_OBJECT 'CLASS OBJECT name:A modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.A
VAR name:x type:kotlin.Int [val] VAR name:x type:kotlin.Int [val]
CALL 'public final fun component1 (): kotlin.Int [operator] declared in <root>.B' type=kotlin.Int origin=null CALL 'public final fun component1 (): kotlin.Int [operator] declared in <root>.B' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null $this: GET_VAR '<this>: <root>.B declared in <root>.test' type=<root>.B origin=null
$receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null $receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null
VAR name:_ type:kotlin.Int [val] VAR name:_ type:kotlin.Int [val]
CALL 'public final fun component2 (): kotlin.Int [operator] declared in <root>.B' type=kotlin.Int origin=null CALL 'public final fun component2 (): kotlin.Int [operator] declared in <root>.B' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null $this: GET_VAR '<this>: <root>.B declared in <root>.test' type=<root>.B origin=null
$receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null $receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null
VAR name:z type:kotlin.Int [val] VAR name:z type:kotlin.Int [val]
CALL 'public final fun component3 (): kotlin.Int [operator] declared in <root>.B' type=kotlin.Int origin=null CALL 'public final fun component3 (): kotlin.Int [operator] declared in <root>.B' type=kotlin.Int origin=null
$this: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null $this: GET_VAR '<this>: <root>.B declared in <root>.test' type=<root>.B origin=null
$receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null $receiver: GET_VAR 'val tmp_0: <root>.A [val] declared in <root>.test' type=<root>.A origin=null