[FIR] Use tower to resolve delegated constructors, set dispatch receiver

This commit is contained in:
Mikhail Glukhikh
2020-04-10 18:29:14 +03:00
parent 0b8c497d2e
commit 457fb09e3a
60 changed files with 226 additions and 106 deletions
@@ -6,7 +6,7 @@ FILE: objectInnerClass.kt
local final inner class Child : R|<anonymous>.Base| {
public[local] constructor(property: R|B|): R|<anonymous>.Child| {
super<R|<anonymous>.Base|>(R|<local>/property|)
this@R|/anonymous|.super<R|<anonymous>.Base|>(R|<local>/property|)
}
public[local] final fun R|<anonymous>.Base|.zoo(): R|kotlin/Unit| {
@@ -69,7 +69,7 @@ FILE: objectInnerClass.kt
public final val x: R|anonymous| = object : R|Case2.Base| {
private constructor(): R|anonymous| {
super<R|Case2.Base|>(R|/B.B|())
this@R|/Case2|.super<R|Case2.Base|>(R|/B.B|())
}
public[local] final fun R|Case2.Base|.zoo(): R|kotlin/Unit| {
@@ -131,7 +131,7 @@ FILE: objectInnerClass.kt
local final inner class Child : R|Case3.<anonymous>.Base| {
public[local] constructor(property: R|B|): R|Case3.<anonymous>.Child| {
super<R|Case3.<anonymous>.Base|>(R|<local>/property|)
this@R|/anonymous|.super<R|Case3.<anonymous>.Base|>(R|<local>/property|)
}
public[local] final fun R|Case3.<anonymous>.Base|.zoo(): R|kotlin/Unit| {
@@ -0,0 +1,4 @@
class Outer { inner class Inner }
fun test() {
val x = object : <!UNRESOLVED_REFERENCE!>Outer.Inner<!>() { }
}
@@ -0,0 +1,23 @@
FILE: objectDerivedFromInnerClass.kt
public final class Outer : R|kotlin/Any| {
public constructor(): R|Outer| {
super<R|kotlin/Any|>()
}
public final inner class Inner : R|kotlin/Any| {
public constructor(): R|Outer.Inner| {
super<R|kotlin/Any|>()
}
}
}
public final fun test(): R|kotlin/Unit| {
lval x: R|anonymous| = object : R|Outer.Inner| {
private constructor(): R|anonymous| {
super<R|Outer.Inner|>()
}
}
}
@@ -13,7 +13,7 @@ abstract class My<T : Some> {
abstract val z: test.My.T
class Some : T()
class Some : <!UNRESOLVED_REFERENCE!>T<!>()
}
abstract class Your<T : Some> : <!OTHER_ERROR!>T<!>
@@ -38,9 +38,9 @@ interface E {
}
class Test2 : A.APublicI, B.BInner {
<!UNRESOLVED_REFERENCE!>class Test2 : A.APublicI, B.BInner {
}
}<!>
class Test3 : C.CPublicI, <!EXPOSED_SUPER_CLASS!>C<!> {
@@ -50,9 +50,9 @@ class Test4 : E, A.AProtectedI {
}
class Test5 : C.CPublicI, B.BInner {
<!UNRESOLVED_REFERENCE!>class Test5 : C.CPublicI, B.BInner {
}
}<!>
class Test6 : E, <!EXPOSED_SUPER_CLASS!>C.CPublic<!> {
@@ -31,7 +31,7 @@ FILE: K2.kt
public final inner class K3 : R|J1.J2| {
public constructor(): R|K2.K3| {
super<R|J1.J2|>()
this@R|/K2|.super<R|J1.J2|>()
}
public final fun main(): R|kotlin/Unit| {
@@ -1664,6 +1664,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/multipleJavaClassesInOneFile.kt");
}
@TestMetadata("objectDerivedFromInnerClass.kt")
public void testObjectDerivedFromInnerClass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/objectDerivedFromInnerClass.kt");
}
@TestMetadata("safeCallInvoke.kt")
public void testSafeCallInvoke() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/safeCallInvoke.kt");
@@ -1664,6 +1664,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/problems/multipleJavaClassesInOneFile.kt");
}
@TestMetadata("objectDerivedFromInnerClass.kt")
public void testObjectDerivedFromInnerClass() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/objectDerivedFromInnerClass.kt");
}
@TestMetadata("safeCallInvoke.kt")
public void testSafeCallInvoke() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/safeCallInvoke.kt");
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.types.*
@@ -247,6 +248,7 @@ internal class ClassMemberGenerator(
startOffset, endOffset, constructedIrType, "Cannot find delegated constructor call"
)
}
val firDispatchReceiver = dispatchReceiver
return convertWithOffsets { startOffset, endOffset ->
val irConstructorSymbol = declarationStorage.getIrFunctionSymbol(constructorSymbol) as IrConstructorSymbol
if (constructorSymbol.fir.isFromEnumClass || constructorSymbol.fir.returnTypeRef.isEnum) {
@@ -268,6 +270,9 @@ internal class ClassMemberGenerator(
irConstructorSymbol
)
}.let {
if (firDispatchReceiver !is FirNoReceiverExpression) {
it.dispatchReceiver = visitor.convertToIrExpression(firDispatchReceiver)
}
with(callGenerator) {
it.applyCallArguments(this@toIrDelegatingConstructorCall)
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.isInner
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub
import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedReifiedParameterReference
@@ -20,7 +21,6 @@ import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.calls.tower.FirTowerResolver
import org.jetbrains.kotlin.fir.resolve.calls.tower.TowerGroup
import org.jetbrains.kotlin.fir.resolve.calls.tower.TowerResolveManager
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
@@ -32,14 +32,12 @@ import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.transformers.phasedFir
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
class FirCallResolver(
private val components: BodyResolveComponents,
@@ -269,14 +267,13 @@ class FirCallResolver(
fun resolveDelegatingConstructorCall(
delegatedConstructorCall: FirDelegatedConstructorCall,
symbol: FirClassSymbol<*>,
constructorClassSymbol: FirClassSymbol<*>,
typeArguments: List<FirTypeProjection>,
): FirDelegatedConstructorCall? {
val scope = symbol.fir.unsubstitutedScope(session, scopeSession)
val className = symbol.classId.shortClassName
val name = Name.special("<init>")
val callInfo = CallInfo(
CallKind.DelegatingConstructorCall,
className,
name,
explicitReceiver = null,
delegatedConstructorCall.argumentList,
isSafeCall = false,
@@ -286,22 +283,19 @@ class FirCallResolver(
file,
implicitReceiverStack,
)
val candidateFactory = CandidateFactory(this, callInfo)
val candidates = mutableListOf<Candidate>()
towerResolver.reset()
val result = towerResolver.runResolverForDelegatingConstructor(
implicitReceiverStack.receiversAsReversed(),
callInfo,
constructorClassSymbol,
)
scope.processDeclaredConstructors {
val candidate = candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER)
candidate.typeArgumentMapping = TypeArgumentMapping.Mapped(typeArguments)
candidates += candidate
}
return callResolver.selectDelegatingConstructorCall(delegatedConstructorCall, className, candidates)
return callResolver.selectDelegatingConstructorCall(delegatedConstructorCall, name, result)
}
private fun selectDelegatingConstructorCall(
call: FirDelegatedConstructorCall, name: Name, candidates: Collection<Candidate>,
call: FirDelegatedConstructorCall, name: Name, result: CandidateCollector,
): FirDelegatedConstructorCall {
val result = CandidateCollector(this, resolutionStageRunner)
candidates.forEach { result.consumeCandidate(TowerGroup.Start, it) }
val bestCandidates = result.bestCandidates()
val reducedCandidates = if (result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED) {
bestCandidates.toSet()
@@ -316,7 +310,15 @@ class FirCallResolver(
result.currentApplicability,
)
return call.transformCalleeReference(StoreNameReference, nameReference)
return call.transformCalleeReference(StoreNameReference, nameReference).apply {
val singleCandidate = reducedCandidates.singleOrNull()
if (singleCandidate != null) {
val symbol = singleCandidate.symbol
if (symbol is FirConstructorSymbol && symbol.fir.isInner) {
transformDispatchReceiver(StoreReceiver, singleCandidate.dispatchReceiverExpression())
}
}
}
}
private fun createCallableReferencesInfoForLHS(
@@ -40,6 +40,7 @@ enum class CallKind(vararg resolutionSequence: ResolutionStage) {
CheckVisibility,
MapArguments,
CheckExplicitReceiverConsistency,
MapTypeArguments,
CreateFreshTypeVariableSubstitutorStage,
CheckReceivers.Dispatch,
CheckReceivers.Extension,
@@ -28,10 +28,11 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
private operator fun <T> Pair<T, *>?.component1() = this?.first
private operator fun <T> Pair<*, T>?.component2() = this?.second
internal fun FirScope.processFunctionsAndConstructorsByName(
internal fun FirScope.processConstructorsByName(
name: Name,
session: FirSession,
bodyResolveComponents: BodyResolveComponents,
noSyntheticConstructors: Boolean,
noInnerConstructors: Boolean = false,
processor: (FirCallableSymbol<*>) -> Unit
) {
@@ -41,7 +42,6 @@ internal fun FirScope.processFunctionsAndConstructorsByName(
val (matchedClassifierSymbol, substitutor) = classifierInfo
val matchedClassSymbol = matchedClassifierSymbol as? FirClassLikeSymbol<*>
processConstructors(
matchedClassSymbol,
substitutor,
@@ -51,12 +51,31 @@ internal fun FirScope.processFunctionsAndConstructorsByName(
noInnerConstructors
)
if (noSyntheticConstructors) {
return
}
processSyntheticConstructors(
matchedClassSymbol,
processor,
bodyResolveComponents
)
}
}
internal fun FirScope.processFunctionsAndConstructorsByName(
name: Name,
session: FirSession,
bodyResolveComponents: BodyResolveComponents,
noInnerConstructors: Boolean = false,
processor: (FirCallableSymbol<*>) -> Unit
) {
processConstructorsByName(
name, session, bodyResolveComponents,
noSyntheticConstructors = false,
noInnerConstructors = noInnerConstructors,
processor = processor
)
processFunctionsByName(name) {
processor(it)
@@ -36,7 +36,7 @@ internal object MapTypeArguments : ResolutionStage() {
val owner = candidate.symbol.fir as FirTypeParameterRefsOwner
if (typeArguments.size == owner.typeParameters.size) {
if (typeArguments.size == owner.typeParameters.size || callInfo.callKind == CallKind.DelegatingConstructorCall) {
candidate.typeArgumentMapping = TypeArgumentMapping.Mapped(typeArguments)
} else {
sink.yieldApplicability(CandidateApplicability.INAPPLICABLE)
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
class FirTowerResolver(
private val components: BodyResolveComponents,
@@ -30,6 +32,20 @@ class FirTowerResolver(
return collector
}
fun runResolverForDelegatingConstructor(
implicitReceiverValues: List<ImplicitReceiverValue<*>>,
info: CallInfo,
constructorClassSymbol: FirClassSymbol<*>,
): CandidateCollector {
val candidateFactoriesAndCollectors = buildCandidateFactoriesAndCollectors(info, collector)
val towerResolverSession = FirTowerResolverSession(components, implicitReceiverValues, manager, candidateFactoriesAndCollectors)
towerResolverSession.runResolutionForDelegatingConstructor(info, constructorClassSymbol)
manager.runTasks()
return collector
}
private fun buildCandidateFactoriesAndCollectors(
info: CallInfo,
collector: CandidateCollector
@@ -26,7 +26,9 @@ import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.scopes.impl.FirStaticScope
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
@@ -65,6 +67,10 @@ class FirTowerResolverSession internal constructor(
else
components.typeParametersScopes.asReversed() + components.fileImportsScope.asReversed()
fun runResolutionForDelegatingConstructor(info: CallInfo, constructorClassSymbol: FirClassSymbol<*>) {
manager.enqueueResolverTask { runResolverForDelegatingConstructorCall(info, constructorClassSymbol) }
}
fun runResolution(info: CallInfo) {
when (val receiver = info.explicitReceiver) {
is FirResolvedQualifier -> manager.enqueueResolverTask { runResolverForQualifierReceiver(info, receiver) }
@@ -198,6 +204,25 @@ class FirTowerResolverSession internal constructor(
}
}
private suspend fun runResolverForDelegatingConstructorCall(info: CallInfo, constructorClassSymbol: FirClassSymbol<*>) {
val scope = constructorClassSymbol.fir.unsubstitutedScope(session, components.scopeSession)
// Search for non-inner constructors only
processLevel(
scope.toScopeTowerLevel(),
info, TowerGroup.Implicit(0)
)
// Search for inner constructors only
if (constructorClassSymbol is FirRegularClassSymbol) {
// 1 because we search for inner constructor in outer class
implicitReceiversUsableAsValues.getOrNull(1)?.let { (implicitReceiverValue) ->
processLevel(
implicitReceiverValue.toMemberScopeTowerLevel(),
info.copy(name = constructorClassSymbol.fir.name), TowerGroup.Implicit(1)
)
}
}
}
private suspend fun runResolverForNoReceiver(
info: CallInfo
) {
@@ -122,6 +122,9 @@ internal class TowerLevelHandler {
towerLevel.processFunctionsAndProperties(info.name, processor)
}
}
CallKind.DelegatingConstructorCall -> {
towerLevel.processConstructors(info.name, processor)
}
else -> {
throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
}
@@ -150,6 +153,12 @@ internal class TowerLevelHandler {
processProperties(name, processor)
}
private fun TowerScopeLevel.processConstructors(
name: Name, processor: TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
) {
processElementsByNameAndStoreResult(TowerScopeLevel.Token.Constructors, name, processor)
}
private fun TowerScopeLevel.processObjectsAsVariables(
name: Name, processor: TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>>
) {
@@ -37,8 +37,8 @@ interface TowerScopeLevel {
sealed class Token<out T : AbstractFirBasedSymbol<*>> {
object Properties : Token<FirVariableSymbol<*>>()
object Functions : Token<FirFunctionSymbol<*>>()
object Constructors : Token<FirConstructorSymbol>()
object Objects : Token<AbstractFirBasedSymbol<*>>()
}
@@ -82,6 +82,7 @@ class MemberScopeTowerLevel(
) : SessionBasedTowerLevel(session) {
private fun <T : AbstractFirBasedSymbol<*>> processMembers(
output: TowerScopeLevel.TowerScopeLevelProcessor<T>,
forInnerConstructors: Boolean = false,
processScopeMembers: FirScope.(processor: (T) -> Unit) -> Unit
): ProcessorAction {
var empty = true
@@ -92,7 +93,11 @@ class MemberScopeTowerLevel(
(implicitExtensionInvokeMode || candidate.hasConsistentExtensionReceiver(extensionReceiver))
) {
val fir = candidate.fir
if ((fir as? FirCallableMemberDeclaration<*>)?.isStatic == true || (fir as? FirConstructor)?.isInner == false) {
if (forInnerConstructors) {
if (candidate !is FirConstructorSymbol || !candidate.fir.isInner) {
return@processScopeMembers
}
} else if ((fir as? FirCallableMemberDeclaration<*>)?.isStatic == true || (fir as? FirConstructor)?.isInner == false) {
return@processScopeMembers
}
val dispatchReceiverValue = NotNullableReceiverValue(dispatchReceiver)
@@ -114,10 +119,12 @@ class MemberScopeTowerLevel(
}
}
val withSynthetic = FirSyntheticPropertiesScope(session, scope)
withSynthetic.processScopeMembers { symbol ->
empty = false
output.consumeCandidate(symbol, NotNullableReceiverValue(dispatchReceiver), extensionReceiver as? ImplicitReceiverValue<*>)
if (!forInnerConstructors) {
val withSynthetic = FirSyntheticPropertiesScope(session, scope)
withSynthetic.processScopeMembers { symbol ->
empty = false
output.consumeCandidate(symbol, NotNullableReceiverValue(dispatchReceiver), extensionReceiver as? ImplicitReceiverValue<*>)
}
}
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
}
@@ -157,6 +164,17 @@ class MemberScopeTowerLevel(
consumer(it as T)
}
}
TowerScopeLevel.Token.Constructors -> processMembers(processor, forInnerConstructors = true) { consumer ->
this.processConstructorsByName(
name, session, bodyResolveComponents,
noSyntheticConstructors = true,
noInnerConstructors = false,
processor = {
@Suppress("UNCHECKED_CAST")
consumer(it as T)
}
)
}
}
}
@@ -261,6 +279,15 @@ class ScopeTowerLevel(
implicitExtensionReceiverValue = null
)
}
TowerScopeLevel.Token.Constructors -> scope.processDeclaredConstructors { candidate ->
// NB: here we cannot resolve inner constructors, because they should have dispatch receiver
if (!candidate.fir.isInner) {
processor.consumeCandidate(
candidate as T, dispatchReceiverValue(scope, candidate),
implicitExtensionReceiverValue = null
)
}
}
}
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
}
@@ -644,7 +644,8 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
context.implicitReceiverStack.add(name, lastDispatchReceiver)
}
val typeArguments: List<FirTypeProjection>
val symbol: FirClassSymbol<*> = when (val reference = delegatedConstructorCall.calleeReference) {
val reference = delegatedConstructorCall.calleeReference
val symbol: FirClassSymbol<*> = when (reference) {
is FirThisReference -> {
typeArguments = emptyList()
if (reference.boundSymbol == null) {
@@ -674,7 +675,11 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
}
val resolvedCall = callResolver.resolveDelegatingConstructorCall(delegatedConstructorCall, symbol, typeArguments)
?: return delegatedConstructorCall.compose()
if (reference is FirThisReference && reference.boundSymbol == null) {
resolvedCall.dispatchReceiver.typeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.toSymbol(session)?.let {
reference.replaceBoundSymbol(it)
}
}
val completionResult = callCompleter.completeCall(resolvedCall, noExpectedType)
result = completionResult.result
@@ -22,6 +22,7 @@ abstract class FirDelegatedConstructorCall : FirPureAbstractElement(), FirResolv
abstract override val annotations: List<FirAnnotationCall>
abstract override val argumentList: FirArgumentList
abstract val constructedTypeRef: FirTypeRef
abstract val dispatchReceiver: FirExpression
abstract val isThis: Boolean
abstract val isSuper: Boolean
@@ -36,4 +37,6 @@ abstract class FirDelegatedConstructorCall : FirPureAbstractElement(), FirResolv
abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirDelegatedConstructorCall
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirDelegatedConstructorCall
abstract fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirDelegatedConstructorCall
}
@@ -13,8 +13,10 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirArgumentList
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.FirCallBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirDelegatedConstructorCallImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.impl.FirExplicitSuperReference
import org.jetbrains.kotlin.fir.references.impl.FirExplicitThisReference
@@ -32,6 +34,7 @@ class FirDelegatedConstructorCallBuilder : FirCallBuilder, FirAnnotationContaine
override val annotations: MutableList<FirAnnotationCall> = mutableListOf()
override var argumentList: FirArgumentList = FirEmptyArgumentList
lateinit var constructedTypeRef: FirTypeRef
var dispatchReceiver: FirExpression = FirNoReceiverExpression
var isThis: Boolean by kotlin.properties.Delegates.notNull<Boolean>()
override fun build(): FirDelegatedConstructorCall {
@@ -40,6 +43,7 @@ class FirDelegatedConstructorCallBuilder : FirCallBuilder, FirAnnotationContaine
annotations,
argumentList,
constructedTypeRef,
dispatchReceiver,
isThis,
)
}
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirArgumentList
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.impl.FirExplicitSuperReference
import org.jetbrains.kotlin.fir.references.impl.FirExplicitThisReference
@@ -25,6 +26,7 @@ internal class FirDelegatedConstructorCallImpl(
override val annotations: MutableList<FirAnnotationCall>,
override var argumentList: FirArgumentList,
override var constructedTypeRef: FirTypeRef,
override var dispatchReceiver: FirExpression,
override val isThis: Boolean,
) : FirDelegatedConstructorCall() {
override var calleeReference: FirReference = if (isThis) FirExplicitThisReference(source, null) else FirExplicitSuperReference(source, null, constructedTypeRef)
@@ -55,6 +57,11 @@ internal class FirDelegatedConstructorCallImpl(
return this
}
override fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirDelegatedConstructorCallImpl {
dispatchReceiver = dispatchReceiver.transformSingle(transformer, data)
return this
}
override fun replaceCalleeReference(newCalleeReference: FirReference) {
calleeReference = newCalleeReference
}
@@ -763,6 +763,11 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
}
override fun visitDelegatedConstructorCall(delegatedConstructorCall: FirDelegatedConstructorCall) {
val dispatchReceiver = delegatedConstructorCall.dispatchReceiver
if (dispatchReceiver !is FirNoReceiverExpression) {
dispatchReceiver.accept(this)
print(".")
}
if (delegatedConstructorCall.isSuper) {
print("super<")
} else if (delegatedConstructorCall.isThis) {
@@ -152,6 +152,8 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
default("argumentList") {
value = "FirEmptyArgumentList"
}
default("dispatchReceiver", "FirNoReceiverExpression")
useTypes(noReceiverExpressionType)
useTypes(emptyArgumentListType)
}
@@ -348,6 +348,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
delegatedConstructorCall.configure {
+field("constructedTypeRef", typeRef, withReplace = true)
+field("dispatchReceiver", expression).withTransform()
generateBooleanFields("this", "super")
}