FIR tree: add dispatch & extension receivers
This commit is contained in:
+4
-2
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.*
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression
|
import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirWrappedDelegateExpressionImpl
|
import org.jetbrains.kotlin.fir.expressions.impl.FirWrappedDelegateExpressionImpl
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||||
@@ -80,6 +81,7 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
|
|||||||
val childElement = property.getter.apply { isAccessible = true }.call(this)
|
val childElement = property.getter.apply { isAccessible = true }.call(this)
|
||||||
|
|
||||||
when (childElement) {
|
when (childElement) {
|
||||||
|
is FirNoReceiverExpression -> continue@propertyLoop
|
||||||
is FirElement -> childElement.traverseChildren(result)
|
is FirElement -> childElement.traverseChildren(result)
|
||||||
is List<*> -> childElement.filterIsInstance<FirElement>().forEach { it.traverseChildren(result) }
|
is List<*> -> childElement.filterIsInstance<FirElement>().forEach { it.traverseChildren(result) }
|
||||||
else -> continue@propertyLoop
|
else -> continue@propertyLoop
|
||||||
@@ -129,7 +131,7 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
|
|||||||
override fun visitElement(element: FirElement) {
|
override fun visitElement(element: FirElement) {
|
||||||
// NB: types are reused sometimes (e.g. in accessors)
|
// NB: types are reused sometimes (e.g. in accessors)
|
||||||
if (!result.add(element)) {
|
if (!result.add(element)) {
|
||||||
if (element !is FirTypeRef) {
|
if (element !is FirTypeRef && element !is FirNoReceiverExpression) {
|
||||||
val elementDump = StringBuilder().also { element.accept(FirRenderer(it)) }.toString()
|
val elementDump = StringBuilder().also { element.accept(FirRenderer(it)) }.toString()
|
||||||
throw AssertionError("FirElement ${element.javaClass} is visited twice: $elementDump")
|
throw AssertionError("FirElement ${element.javaClass} is visited twice: $elementDump")
|
||||||
}
|
}
|
||||||
@@ -146,7 +148,7 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
|
|||||||
|
|
||||||
override fun <E : FirElement> transformElement(element: E, data: Unit): CompositeTransformResult<E> {
|
override fun <E : FirElement> transformElement(element: E, data: Unit): CompositeTransformResult<E> {
|
||||||
if (!result.add(element)) {
|
if (!result.add(element)) {
|
||||||
if (element !is FirTypeRef) {
|
if (element !is FirTypeRef && element !is FirNoReceiverExpression) {
|
||||||
val elementDump = StringBuilder().also { element.accept(FirRenderer(it)) }.toString()
|
val elementDump = StringBuilder().also { element.accept(FirRenderer(it)) }.toString()
|
||||||
throw AssertionError("FirElement ${element.javaClass} is visited twice: $elementDump")
|
throw AssertionError("FirElement ${element.javaClass} is visited twice: $elementDump")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,7 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
|
import org.jetbrains.kotlin.fir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirLoopJump
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
|
|
||||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||||
import org.jetbrains.kotlin.fir.symbols.*
|
import org.jetbrains.kotlin.fir.symbols.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
@@ -827,13 +824,29 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
|
|||||||
|
|
||||||
override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess) {
|
override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess) {
|
||||||
val explicitReceiver = qualifiedAccess.explicitReceiver
|
val explicitReceiver = qualifiedAccess.explicitReceiver
|
||||||
|
val dispatchReceiver = qualifiedAccess.dispatchReceiver
|
||||||
|
val extensionReceiver = qualifiedAccess.extensionReceiver
|
||||||
|
if (dispatchReceiver !is FirNoReceiverExpression) {
|
||||||
|
print("D|")
|
||||||
|
dispatchReceiver.accept(this)
|
||||||
|
print("|")
|
||||||
|
}
|
||||||
|
if (extensionReceiver !is FirNoReceiverExpression) {
|
||||||
|
print("E|")
|
||||||
|
extensionReceiver.accept(this)
|
||||||
|
print("|")
|
||||||
|
}
|
||||||
if (explicitReceiver != null) {
|
if (explicitReceiver != null) {
|
||||||
explicitReceiver.accept(this)
|
if (explicitReceiver !== dispatchReceiver && explicitReceiver !== extensionReceiver) {
|
||||||
|
explicitReceiver.accept(this)
|
||||||
|
}
|
||||||
if (qualifiedAccess.safe) {
|
if (qualifiedAccess.safe) {
|
||||||
print("?.")
|
print("?.")
|
||||||
} else {
|
} else {
|
||||||
print(".")
|
print(".")
|
||||||
}
|
}
|
||||||
|
} else if (dispatchReceiver !is FirNoReceiverExpression || extensionReceiver !is FirNoReceiverExpression) {
|
||||||
|
print(".")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.expressions
|
package org.jetbrains.kotlin.fir.expressions
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
|
|
||||||
@@ -13,6 +14,10 @@ interface FirQualifiedAccess : FirResolvable {
|
|||||||
|
|
||||||
val explicitReceiver: FirExpression? get() = null
|
val explicitReceiver: FirExpression? get() = null
|
||||||
|
|
||||||
|
val dispatchReceiver: FirExpression get() = FirNoReceiverExpression
|
||||||
|
|
||||||
|
val extensionReceiver: FirExpression get() = FirNoReceiverExpression
|
||||||
|
|
||||||
fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirQualifiedAccess
|
fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirQualifiedAccess
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
|
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
|
||||||
@@ -21,6 +26,8 @@ interface FirQualifiedAccess : FirResolvable {
|
|||||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||||
calleeReference.accept(visitor, data)
|
calleeReference.accept(visitor, data)
|
||||||
explicitReceiver?.accept(visitor, data)
|
explicitReceiver?.accept(visitor, data)
|
||||||
|
dispatchReceiver.accept(visitor, data)
|
||||||
|
extensionReceiver.accept(visitor, data)
|
||||||
super.acceptChildren(visitor, data)
|
super.acceptChildren(visitor, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
@@ -19,6 +19,8 @@ abstract class FirQualifiedAccessExpression(
|
|||||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||||
calleeReference.accept(visitor, data)
|
calleeReference.accept(visitor, data)
|
||||||
explicitReceiver?.accept(visitor, data)
|
explicitReceiver?.accept(visitor, data)
|
||||||
|
dispatchReceiver.accept(visitor, data)
|
||||||
|
extensionReceiver.accept(visitor, data)
|
||||||
super<FirUnknownTypeExpression>.acceptChildren(visitor, data)
|
super<FirUnknownTypeExpression>.acceptChildren(visitor, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
@@ -19,9 +19,16 @@ abstract class FirAbstractQualifiedAccess(
|
|||||||
|
|
||||||
final override var explicitReceiver: FirExpression? = null
|
final override var explicitReceiver: FirExpression? = null
|
||||||
|
|
||||||
|
override var dispatchReceiver: FirExpression = FirNoReceiverExpression
|
||||||
|
|
||||||
|
override var extensionReceiver: FirExpression = FirNoReceiverExpression
|
||||||
|
|
||||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||||
calleeReference = calleeReference.transformSingle(transformer, data)
|
calleeReference = calleeReference.transformSingle(transformer, data)
|
||||||
explicitReceiver = explicitReceiver?.transformSingle(transformer, data)
|
explicitReceiver = explicitReceiver?.transformSingle(transformer, data)
|
||||||
|
dispatchReceiver = dispatchReceiver.transformSingle(transformer, data)
|
||||||
|
extensionReceiver = extensionReceiver.transformSingle(transformer, data)
|
||||||
|
|
||||||
return super<FirAnnotatedStatement>.transformChildren(transformer, data)
|
return super<FirAnnotatedStatement>.transformChildren(transformer, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,10 +23,17 @@ class FirFunctionCallImpl(
|
|||||||
|
|
||||||
override var explicitReceiver: FirExpression? = null
|
override var explicitReceiver: FirExpression? = null
|
||||||
|
|
||||||
|
override var dispatchReceiver: FirExpression = FirNoReceiverExpression
|
||||||
|
|
||||||
|
override var extensionReceiver: FirExpression = FirNoReceiverExpression
|
||||||
|
|
||||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||||
typeArguments.transformInplace(transformer, data)
|
typeArguments.transformInplace(transformer, data)
|
||||||
calleeReference = calleeReference.transformSingle(transformer, data)
|
calleeReference = calleeReference.transformSingle(transformer, data)
|
||||||
explicitReceiver = explicitReceiver?.transformSingle(transformer, data)
|
explicitReceiver = explicitReceiver?.transformSingle(transformer, data)
|
||||||
|
dispatchReceiver = dispatchReceiver.transformSingle(transformer, data)
|
||||||
|
extensionReceiver = extensionReceiver.transformSingle(transformer, data)
|
||||||
|
|
||||||
return super<FirFunctionCall>.transformChildren(transformer, data)
|
return super<FirFunctionCall>.transformChildren(transformer, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.expressions.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
|
|
||||||
|
object FirNoReceiverExpression : FirExpression(null) {
|
||||||
|
override val typeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
|
||||||
|
|
||||||
|
override fun replaceTypeRef(newTypeRef: FirTypeRef) {}
|
||||||
|
|
||||||
|
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
||||||
|
}
|
||||||
+6
@@ -21,9 +21,15 @@ class FirQualifiedAccessExpressionImpl(
|
|||||||
|
|
||||||
override var explicitReceiver: FirExpression? = null
|
override var explicitReceiver: FirExpression? = null
|
||||||
|
|
||||||
|
override var dispatchReceiver: FirExpression = FirNoReceiverExpression
|
||||||
|
|
||||||
|
override var extensionReceiver: FirExpression = FirNoReceiverExpression
|
||||||
|
|
||||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||||
calleeReference = calleeReference.transformSingle(transformer, data)
|
calleeReference = calleeReference.transformSingle(transformer, data)
|
||||||
explicitReceiver = explicitReceiver?.transformSingle(transformer, data)
|
explicitReceiver = explicitReceiver?.transformSingle(transformer, data)
|
||||||
|
dispatchReceiver = dispatchReceiver.transformSingle(transformer, data)
|
||||||
|
extensionReceiver = extensionReceiver.transformSingle(transformer, data)
|
||||||
|
|
||||||
return super<FirQualifiedAccessExpression>.transformChildren(transformer, data)
|
return super<FirQualifiedAccessExpression>.transformChildren(transformer, data)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user