[FIR] Save mapping from supertype to delegated field in class attribute

This is needed to let checkers know which specific interface was
  implemented by delegation
This commit is contained in:
Dmitriy Novozhilov
2021-10-26 15:38:47 +03:00
committed by teamcityserver
parent e25fff701b
commit b0f38bd996
3 changed files with 65 additions and 23 deletions
@@ -437,6 +437,7 @@ class DeclarationsConverter(
typeParameterList?.let { firTypeParameters += convertTypeParameters(it, typeConstraints, classSymbol) }
withCapturedTypeParameters(status.isInner || isLocal, firTypeParameters) {
var delegatedFieldsMap: Map<Int, FirFieldSymbol>? = 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<FirProperty>()
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<Int, FirFieldSymbol>? = 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<FirTypeRef>,
val delegatedConstructorArguments: List<FirExpression>,
val delegatedConstructorSource: KtLightSourceElement?,
val delegateFields: List<FirField>,
val delegateFieldsMap: Map<Int, FirFieldSymbol>,
)
private fun convertDelegationSpecifiers(delegationSpecifiers: LighterASTNode): DelegationSpecifiers {
@@ -1703,25 +1711,29 @@ class DeclarationsConverter(
val superTypeCallEntry = mutableListOf<FirExpression>()
var delegatedSuperTypeRef: FirTypeRef? = null
var delegateConstructorSource: KtLightSourceElement? = null
val delegateFields = mutableListOf<FirField>()
val delegateFieldsMap = mutableMapOf<Int, FirFieldSymbol>()
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<FirField>): FirTypeRef {
private fun convertExplicitDelegation(
explicitDelegation: LighterASTNode,
delegateFieldsMap: MutableMap<Int, FirFieldSymbol>,
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
}
@@ -746,25 +746,25 @@ open class RawFirBuilder(
classKind: ClassKind,
containerTypeParameters: List<FirTypeParameterRef>,
containingClassIsExpectClass: Boolean
): FirTypeRef {
): Pair<FirTypeRef, Map<Int, FirFieldSymbol>?> {
var superTypeCallEntry: KtSuperTypeCallEntry? = null
var delegatedSuperTypeRef: FirTypeRef? = null
val delegateFields = mutableListOf<FirField>()
for (superTypeListEntry in superTypeListEntries) {
val delegateFieldsMap = mutableMapOf<Int, FirFieldSymbol>()
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<Int, FirFieldSymbol>?
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<Int, FirFieldSymbol>?
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
}
}
}
@@ -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<Int, FirFieldSymbol>? by FirDeclarationDataRegistry.data(DelegateFieldsMapKey)