diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index 079f54562a2..8737183a5f5 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -437,6 +437,7 @@ class DeclarationsConverter( typeParameterList?.let { firTypeParameters += convertTypeParameters(it, typeConstraints, classSymbol) } withCapturedTypeParameters(status.isInner || isLocal, firTypeParameters) { + var delegatedFieldsMap: Map? = null buildRegularClass { source = classNode.toFirSourceElement() moduleData = baseModuleData @@ -508,7 +509,8 @@ class DeclarationsConverter( ) val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor firPrimaryConstructor?.let { declarations += it } - delegationSpecifiers?.delegateFields?.map { declarations += it } + delegationSpecifiers?.delegateFieldsMap?.values?.mapTo(declarations) { it.fir } + delegatedFieldsMap = delegationSpecifiers?.delegateFieldsMap?.takeIf { it.isNotEmpty() } val properties = mutableListOf() if (primaryConstructor != null && firPrimaryConstructor != null) { @@ -561,6 +563,8 @@ class DeclarationsConverter( ) } initCompanionObjectSymbolAttr() + }.also { + it.delegateFieldsMap = delegatedFieldsMap } } }.also { @@ -575,6 +579,7 @@ class DeclarationsConverter( */ fun convertObjectLiteral(objectLiteral: LighterASTNode): FirElement { return withChildClassName(SpecialNames.ANONYMOUS, isExpect = false) { + var delegatedFieldsMap: Map? = null buildAnonymousObjectExpression { val objectDeclaration = objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first() val sourceElement = objectDeclaration.toFirSourceElement() @@ -609,7 +614,8 @@ class DeclarationsConverter( superTypeRefs += specifiers.superTypesRef superTypeCallEntry += specifiers.delegatedConstructorArguments delegatedConstructorSource = specifiers.delegatedConstructorSource - delegateFields = specifiers.delegateFields + delegateFields = specifiers.delegateFieldsMap.values.map { it.fir } + delegatedFieldsMap = specifiers.delegateFieldsMap.takeIf { it.isNotEmpty() } } CLASS_BODY -> classBody = it } @@ -647,6 +653,8 @@ class DeclarationsConverter( classBody?.let { this.declarations += convertClassBody(it, classWrapper) } + }.also { + it.delegateFieldsMap = delegatedFieldsMap } } } @@ -1695,7 +1703,7 @@ class DeclarationsConverter( val superTypesRef: List, val delegatedConstructorArguments: List, val delegatedConstructorSource: KtLightSourceElement?, - val delegateFields: List, + val delegateFieldsMap: Map, ) private fun convertDelegationSpecifiers(delegationSpecifiers: LighterASTNode): DelegationSpecifiers { @@ -1703,25 +1711,29 @@ class DeclarationsConverter( val superTypeCallEntry = mutableListOf() var delegatedSuperTypeRef: FirTypeRef? = null var delegateConstructorSource: KtLightSourceElement? = null - val delegateFields = mutableListOf() + val delegateFieldsMap = mutableMapOf() + var index = 0 delegationSpecifiers.forEachChildren { when (it.tokenType) { SUPER_TYPE_ENTRY -> { superTypeRefs += convertType(it) + index++ } SUPER_TYPE_CALL_ENTRY -> convertConstructorInvocation(it).apply { delegatedSuperTypeRef = first superTypeRefs += first superTypeCallEntry += second delegateConstructorSource = it.toFirSourceElement(KtFakeSourceElementKind.DelegatingConstructorCall) + index++ } DELEGATED_SUPER_TYPE_ENTRY -> { - superTypeRefs += convertExplicitDelegation(it, delegateFields) + superTypeRefs += convertExplicitDelegation(it, delegateFieldsMap, index) + index++ } } } return DelegationSpecifiers( - delegatedSuperTypeRef, superTypeRefs, superTypeCallEntry, delegateConstructorSource, delegateFields + delegatedSuperTypeRef, superTypeRefs, superTypeCallEntry, delegateConstructorSource, delegateFieldsMap ) } @@ -1751,7 +1763,11 @@ class DeclarationsConverter( * : userType "by" element * ; */ - private fun convertExplicitDelegation(explicitDelegation: LighterASTNode, delegateFields: MutableList): FirTypeRef { + private fun convertExplicitDelegation( + explicitDelegation: LighterASTNode, + delegateFieldsMap: MutableMap, + index: Int + ): FirTypeRef { lateinit var firTypeRef: FirTypeRef var firExpression: FirExpression? = null explicitDelegation.forEachChildren { @@ -1765,8 +1781,9 @@ class DeclarationsConverter( explicitDelegation.toFirSourceElement(), ConeSimpleDiagnostic("Should have delegate", DiagnosticKind.Syntax) ) - val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>") - delegateFields.add( + val delegateName = Name.special("<\$\$delegate_${delegateFieldsMap.size}>") + delegateFieldsMap.put( + index, buildField { source = calculatedFirExpression.source?.fakeElement(KtFakeSourceElementKind.ClassDelegationField) moduleData = baseModuleData @@ -1777,7 +1794,7 @@ class DeclarationsConverter( isVar = false status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL) initializer = calculatedFirExpression - } + }.symbol ) return firTypeRef } diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 07c37a01510..76261fc6047 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -746,25 +746,25 @@ open class RawFirBuilder( classKind: ClassKind, containerTypeParameters: List, containingClassIsExpectClass: Boolean - ): FirTypeRef { + ): Pair?> { var superTypeCallEntry: KtSuperTypeCallEntry? = null var delegatedSuperTypeRef: FirTypeRef? = null - val delegateFields = mutableListOf() - for (superTypeListEntry in superTypeListEntries) { + val delegateFieldsMap = mutableMapOf() + superTypeListEntries.forEachIndexed { index, superTypeListEntry -> when (superTypeListEntry) { is KtSuperTypeEntry -> { container.superTypeRefs += superTypeListEntry.typeReference.toFirOrErrorType() } is KtSuperTypeCallEntry -> { delegatedSuperTypeRef = superTypeListEntry.calleeExpression.typeReference.toFirOrErrorType() - container.superTypeRefs += delegatedSuperTypeRef + container.superTypeRefs += delegatedSuperTypeRef!! superTypeCallEntry = superTypeListEntry } is KtDelegatedSuperTypeEntry -> { val type = superTypeListEntry.typeReference.toFirOrErrorType() val delegateExpression = { superTypeListEntry.delegateExpression }.toFirExpression("Should have delegate") container.superTypeRefs += type - val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>") + val delegateName = Name.special("<\$\$delegate_${delegateFieldsMap.size}>") val delegateSource = superTypeListEntry.delegateExpression?.toFirSourceElement(KtFakeSourceElementKind.ClassDelegationField) val delegateField = buildField { @@ -778,7 +778,7 @@ open class RawFirBuilder( status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL) initializer = delegateExpression } - delegateFields.add(delegateField) + delegateFieldsMap[index] = delegateField.symbol } } } @@ -798,7 +798,7 @@ open class RawFirBuilder( isNullable = false, ) } - container.superTypeRefs += delegatedSuperTypeRef + container.superTypeRefs += delegatedSuperTypeRef!! } this is KtClass && classKind == ClassKind.ANNOTATION_CLASS -> { container.superTypeRefs += implicitAnnotationType @@ -828,16 +828,16 @@ open class RawFirBuilder( if ((this !is KtClass || !this.isInterface()) && (primaryConstructor != null || !shouldNotGenerateImplicitPrimaryConstructor)) { val firPrimaryConstructor = primaryConstructor.toFirConstructor( superTypeCallEntry, - delegatedSuperTypeRef, - delegatedSelfTypeRef ?: delegatedSuperTypeRef, + delegatedSuperTypeRef!!, + delegatedSelfTypeRef ?: delegatedSuperTypeRef!!, owner = this, containerTypeParameters, body = null ) container.declarations += firPrimaryConstructor } - container.declarations += delegateFields - return delegatedSuperTypeRef + delegateFieldsMap.values.mapTo(container.declarations) { it.fir } + return delegatedSuperTypeRef!! to delegateFieldsMap.takeIf { it.isNotEmpty() } } private fun KtPrimaryConstructor?.toFirConstructor( @@ -1045,6 +1045,7 @@ open class RawFirBuilder( } withCapturedTypeParameters(status.isInner || isLocal, listOf()) { + var delegatedFieldsMap: Map? buildRegularClass { source = classOrObject.toFirSourceElement() moduleData = baseModuleData @@ -1067,7 +1068,7 @@ open class RawFirBuilder( val delegatedSelfType = classOrObject.toDelegatedSelfType(this) registerSelfType(delegatedSelfType) - val delegatedSuperType = classOrObject.extractSuperTypeListEntriesTo( + val (delegatedSuperType, extractedDelegatedFieldsMap) = classOrObject.extractSuperTypeListEntriesTo( this, delegatedSelfType, null, @@ -1075,6 +1076,7 @@ open class RawFirBuilder( typeParameters, containingClassIsExpectClass = classIsExpect ) + delegatedFieldsMap = extractedDelegatedFieldsMap val primaryConstructor = classOrObject.primaryConstructor val firPrimaryConstructor = declarations.firstOrNull { it is FirConstructor } as? FirConstructor @@ -1136,6 +1138,8 @@ open class RawFirBuilder( initCompanionObjectSymbolAttr() context.popFirTypeParameters() + }.also { + it.delegateFieldsMap = delegatedFieldsMap } } }.also { @@ -1147,6 +1151,7 @@ open class RawFirBuilder( override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression, data: Unit): FirElement { val objectDeclaration = expression.objectDeclaration return withChildClassName(SpecialNames.ANONYMOUS, forceLocalContext = true, isExpect = false) { + var delegatedFieldsMap: Map? buildAnonymousObjectExpression { val sourceElement = objectDeclaration.toFirSourceElement() source = sourceElement @@ -1162,7 +1167,7 @@ open class RawFirBuilder( val delegatedSelfType = objectDeclaration.toDelegatedSelfType(this) registerSelfType(delegatedSelfType) objectDeclaration.extractAnnotationsTo(this) - val delegatedSuperType = objectDeclaration.extractSuperTypeListEntriesTo( + val (delegatedSuperType, extractedDelegatedFieldsMap) = objectDeclaration.extractSuperTypeListEntriesTo( this, delegatedSelfType, null, @@ -1170,6 +1175,7 @@ open class RawFirBuilder( containerTypeParameters = emptyList(), containingClassIsExpectClass = false ) + delegatedFieldsMap = extractedDelegatedFieldsMap for (declaration in objectDeclaration.declarations) { declarations += declaration.toFirDeclaration( @@ -1180,6 +1186,8 @@ open class RawFirBuilder( ownerTypeParameters = emptyList() ) } + }.also { + it.delegateFieldsMap = delegatedFieldsMap } } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/DelegateFieldsMap.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/DelegateFieldsMap.kt new file mode 100644 index 00000000000..92bdc37eff8 --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/DelegateFieldsMap.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2021 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.declarations + +import org.jetbrains.kotlin.fir.symbols.impl.FirFieldSymbol + +private object DelegateFieldsMapKey : FirDeclarationDataKey() + +/* + * If class implements some interfaces using delegation then this attribute contains mapping + * from index of supertype to symbol of deelgated field + */ +var FirClass.delegateFieldsMap: Map? by FirDeclarationDataRegistry.data(DelegateFieldsMapKey) +