[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) } typeParameterList?.let { firTypeParameters += convertTypeParameters(it, typeConstraints, classSymbol) }
withCapturedTypeParameters(status.isInner || isLocal, firTypeParameters) { withCapturedTypeParameters(status.isInner || isLocal, firTypeParameters) {
var delegatedFieldsMap: Map<Int, FirFieldSymbol>? = null
buildRegularClass { buildRegularClass {
source = classNode.toFirSourceElement() source = classNode.toFirSourceElement()
moduleData = baseModuleData moduleData = baseModuleData
@@ -508,7 +509,8 @@ class DeclarationsConverter(
) )
val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor
firPrimaryConstructor?.let { declarations += it } 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>() val properties = mutableListOf<FirProperty>()
if (primaryConstructor != null && firPrimaryConstructor != null) { if (primaryConstructor != null && firPrimaryConstructor != null) {
@@ -561,6 +563,8 @@ class DeclarationsConverter(
) )
} }
initCompanionObjectSymbolAttr() initCompanionObjectSymbolAttr()
}.also {
it.delegateFieldsMap = delegatedFieldsMap
} }
} }
}.also { }.also {
@@ -575,6 +579,7 @@ class DeclarationsConverter(
*/ */
fun convertObjectLiteral(objectLiteral: LighterASTNode): FirElement { fun convertObjectLiteral(objectLiteral: LighterASTNode): FirElement {
return withChildClassName(SpecialNames.ANONYMOUS, isExpect = false) { return withChildClassName(SpecialNames.ANONYMOUS, isExpect = false) {
var delegatedFieldsMap: Map<Int, FirFieldSymbol>? = null
buildAnonymousObjectExpression { buildAnonymousObjectExpression {
val objectDeclaration = objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first() val objectDeclaration = objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first()
val sourceElement = objectDeclaration.toFirSourceElement() val sourceElement = objectDeclaration.toFirSourceElement()
@@ -609,7 +614,8 @@ class DeclarationsConverter(
superTypeRefs += specifiers.superTypesRef superTypeRefs += specifiers.superTypesRef
superTypeCallEntry += specifiers.delegatedConstructorArguments superTypeCallEntry += specifiers.delegatedConstructorArguments
delegatedConstructorSource = specifiers.delegatedConstructorSource delegatedConstructorSource = specifiers.delegatedConstructorSource
delegateFields = specifiers.delegateFields delegateFields = specifiers.delegateFieldsMap.values.map { it.fir }
delegatedFieldsMap = specifiers.delegateFieldsMap.takeIf { it.isNotEmpty() }
} }
CLASS_BODY -> classBody = it CLASS_BODY -> classBody = it
} }
@@ -647,6 +653,8 @@ class DeclarationsConverter(
classBody?.let { classBody?.let {
this.declarations += convertClassBody(it, classWrapper) this.declarations += convertClassBody(it, classWrapper)
} }
}.also {
it.delegateFieldsMap = delegatedFieldsMap
} }
} }
} }
@@ -1695,7 +1703,7 @@ class DeclarationsConverter(
val superTypesRef: List<FirTypeRef>, val superTypesRef: List<FirTypeRef>,
val delegatedConstructorArguments: List<FirExpression>, val delegatedConstructorArguments: List<FirExpression>,
val delegatedConstructorSource: KtLightSourceElement?, val delegatedConstructorSource: KtLightSourceElement?,
val delegateFields: List<FirField>, val delegateFieldsMap: Map<Int, FirFieldSymbol>,
) )
private fun convertDelegationSpecifiers(delegationSpecifiers: LighterASTNode): DelegationSpecifiers { private fun convertDelegationSpecifiers(delegationSpecifiers: LighterASTNode): DelegationSpecifiers {
@@ -1703,25 +1711,29 @@ class DeclarationsConverter(
val superTypeCallEntry = mutableListOf<FirExpression>() val superTypeCallEntry = mutableListOf<FirExpression>()
var delegatedSuperTypeRef: FirTypeRef? = null var delegatedSuperTypeRef: FirTypeRef? = null
var delegateConstructorSource: KtLightSourceElement? = null var delegateConstructorSource: KtLightSourceElement? = null
val delegateFields = mutableListOf<FirField>() val delegateFieldsMap = mutableMapOf<Int, FirFieldSymbol>()
var index = 0
delegationSpecifiers.forEachChildren { delegationSpecifiers.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
SUPER_TYPE_ENTRY -> { SUPER_TYPE_ENTRY -> {
superTypeRefs += convertType(it) superTypeRefs += convertType(it)
index++
} }
SUPER_TYPE_CALL_ENTRY -> convertConstructorInvocation(it).apply { SUPER_TYPE_CALL_ENTRY -> convertConstructorInvocation(it).apply {
delegatedSuperTypeRef = first delegatedSuperTypeRef = first
superTypeRefs += first superTypeRefs += first
superTypeCallEntry += second superTypeCallEntry += second
delegateConstructorSource = it.toFirSourceElement(KtFakeSourceElementKind.DelegatingConstructorCall) delegateConstructorSource = it.toFirSourceElement(KtFakeSourceElementKind.DelegatingConstructorCall)
index++
} }
DELEGATED_SUPER_TYPE_ENTRY -> { DELEGATED_SUPER_TYPE_ENTRY -> {
superTypeRefs += convertExplicitDelegation(it, delegateFields) superTypeRefs += convertExplicitDelegation(it, delegateFieldsMap, index)
index++
} }
} }
} }
return DelegationSpecifiers( return DelegationSpecifiers(
delegatedSuperTypeRef, superTypeRefs, superTypeCallEntry, delegateConstructorSource, delegateFields delegatedSuperTypeRef, superTypeRefs, superTypeCallEntry, delegateConstructorSource, delegateFieldsMap
) )
} }
@@ -1751,7 +1763,11 @@ class DeclarationsConverter(
* : userType "by" element * : 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 lateinit var firTypeRef: FirTypeRef
var firExpression: FirExpression? = null var firExpression: FirExpression? = null
explicitDelegation.forEachChildren { explicitDelegation.forEachChildren {
@@ -1765,8 +1781,9 @@ class DeclarationsConverter(
explicitDelegation.toFirSourceElement(), ConeSimpleDiagnostic("Should have delegate", DiagnosticKind.Syntax) explicitDelegation.toFirSourceElement(), ConeSimpleDiagnostic("Should have delegate", DiagnosticKind.Syntax)
) )
val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>") val delegateName = Name.special("<\$\$delegate_${delegateFieldsMap.size}>")
delegateFields.add( delegateFieldsMap.put(
index,
buildField { buildField {
source = calculatedFirExpression.source?.fakeElement(KtFakeSourceElementKind.ClassDelegationField) source = calculatedFirExpression.source?.fakeElement(KtFakeSourceElementKind.ClassDelegationField)
moduleData = baseModuleData moduleData = baseModuleData
@@ -1777,7 +1794,7 @@ class DeclarationsConverter(
isVar = false isVar = false
status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL) status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL)
initializer = calculatedFirExpression initializer = calculatedFirExpression
} }.symbol
) )
return firTypeRef return firTypeRef
} }
@@ -746,25 +746,25 @@ open class RawFirBuilder(
classKind: ClassKind, classKind: ClassKind,
containerTypeParameters: List<FirTypeParameterRef>, containerTypeParameters: List<FirTypeParameterRef>,
containingClassIsExpectClass: Boolean containingClassIsExpectClass: Boolean
): FirTypeRef { ): Pair<FirTypeRef, Map<Int, FirFieldSymbol>?> {
var superTypeCallEntry: KtSuperTypeCallEntry? = null var superTypeCallEntry: KtSuperTypeCallEntry? = null
var delegatedSuperTypeRef: FirTypeRef? = null var delegatedSuperTypeRef: FirTypeRef? = null
val delegateFields = mutableListOf<FirField>() val delegateFieldsMap = mutableMapOf<Int, FirFieldSymbol>()
for (superTypeListEntry in superTypeListEntries) { superTypeListEntries.forEachIndexed { index, superTypeListEntry ->
when (superTypeListEntry) { when (superTypeListEntry) {
is KtSuperTypeEntry -> { is KtSuperTypeEntry -> {
container.superTypeRefs += superTypeListEntry.typeReference.toFirOrErrorType() container.superTypeRefs += superTypeListEntry.typeReference.toFirOrErrorType()
} }
is KtSuperTypeCallEntry -> { is KtSuperTypeCallEntry -> {
delegatedSuperTypeRef = superTypeListEntry.calleeExpression.typeReference.toFirOrErrorType() delegatedSuperTypeRef = superTypeListEntry.calleeExpression.typeReference.toFirOrErrorType()
container.superTypeRefs += delegatedSuperTypeRef container.superTypeRefs += delegatedSuperTypeRef!!
superTypeCallEntry = superTypeListEntry superTypeCallEntry = superTypeListEntry
} }
is KtDelegatedSuperTypeEntry -> { is KtDelegatedSuperTypeEntry -> {
val type = superTypeListEntry.typeReference.toFirOrErrorType() val type = superTypeListEntry.typeReference.toFirOrErrorType()
val delegateExpression = { superTypeListEntry.delegateExpression }.toFirExpression("Should have delegate") val delegateExpression = { superTypeListEntry.delegateExpression }.toFirExpression("Should have delegate")
container.superTypeRefs += type container.superTypeRefs += type
val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>") val delegateName = Name.special("<\$\$delegate_${delegateFieldsMap.size}>")
val delegateSource = val delegateSource =
superTypeListEntry.delegateExpression?.toFirSourceElement(KtFakeSourceElementKind.ClassDelegationField) superTypeListEntry.delegateExpression?.toFirSourceElement(KtFakeSourceElementKind.ClassDelegationField)
val delegateField = buildField { val delegateField = buildField {
@@ -778,7 +778,7 @@ open class RawFirBuilder(
status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL) status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL)
initializer = delegateExpression initializer = delegateExpression
} }
delegateFields.add(delegateField) delegateFieldsMap[index] = delegateField.symbol
} }
} }
} }
@@ -798,7 +798,7 @@ open class RawFirBuilder(
isNullable = false, isNullable = false,
) )
} }
container.superTypeRefs += delegatedSuperTypeRef container.superTypeRefs += delegatedSuperTypeRef!!
} }
this is KtClass && classKind == ClassKind.ANNOTATION_CLASS -> { this is KtClass && classKind == ClassKind.ANNOTATION_CLASS -> {
container.superTypeRefs += implicitAnnotationType container.superTypeRefs += implicitAnnotationType
@@ -828,16 +828,16 @@ open class RawFirBuilder(
if ((this !is KtClass || !this.isInterface()) && (primaryConstructor != null || !shouldNotGenerateImplicitPrimaryConstructor)) { if ((this !is KtClass || !this.isInterface()) && (primaryConstructor != null || !shouldNotGenerateImplicitPrimaryConstructor)) {
val firPrimaryConstructor = primaryConstructor.toFirConstructor( val firPrimaryConstructor = primaryConstructor.toFirConstructor(
superTypeCallEntry, superTypeCallEntry,
delegatedSuperTypeRef, delegatedSuperTypeRef!!,
delegatedSelfTypeRef ?: delegatedSuperTypeRef, delegatedSelfTypeRef ?: delegatedSuperTypeRef!!,
owner = this, owner = this,
containerTypeParameters, containerTypeParameters,
body = null body = null
) )
container.declarations += firPrimaryConstructor container.declarations += firPrimaryConstructor
} }
container.declarations += delegateFields delegateFieldsMap.values.mapTo(container.declarations) { it.fir }
return delegatedSuperTypeRef return delegatedSuperTypeRef!! to delegateFieldsMap.takeIf { it.isNotEmpty() }
} }
private fun KtPrimaryConstructor?.toFirConstructor( private fun KtPrimaryConstructor?.toFirConstructor(
@@ -1045,6 +1045,7 @@ open class RawFirBuilder(
} }
withCapturedTypeParameters(status.isInner || isLocal, listOf()) { withCapturedTypeParameters(status.isInner || isLocal, listOf()) {
var delegatedFieldsMap: Map<Int, FirFieldSymbol>?
buildRegularClass { buildRegularClass {
source = classOrObject.toFirSourceElement() source = classOrObject.toFirSourceElement()
moduleData = baseModuleData moduleData = baseModuleData
@@ -1067,7 +1068,7 @@ open class RawFirBuilder(
val delegatedSelfType = classOrObject.toDelegatedSelfType(this) val delegatedSelfType = classOrObject.toDelegatedSelfType(this)
registerSelfType(delegatedSelfType) registerSelfType(delegatedSelfType)
val delegatedSuperType = classOrObject.extractSuperTypeListEntriesTo( val (delegatedSuperType, extractedDelegatedFieldsMap) = classOrObject.extractSuperTypeListEntriesTo(
this, this,
delegatedSelfType, delegatedSelfType,
null, null,
@@ -1075,6 +1076,7 @@ open class RawFirBuilder(
typeParameters, typeParameters,
containingClassIsExpectClass = classIsExpect containingClassIsExpectClass = classIsExpect
) )
delegatedFieldsMap = extractedDelegatedFieldsMap
val primaryConstructor = classOrObject.primaryConstructor val primaryConstructor = classOrObject.primaryConstructor
val firPrimaryConstructor = declarations.firstOrNull { it is FirConstructor } as? FirConstructor val firPrimaryConstructor = declarations.firstOrNull { it is FirConstructor } as? FirConstructor
@@ -1136,6 +1138,8 @@ open class RawFirBuilder(
initCompanionObjectSymbolAttr() initCompanionObjectSymbolAttr()
context.popFirTypeParameters() context.popFirTypeParameters()
}.also {
it.delegateFieldsMap = delegatedFieldsMap
} }
} }
}.also { }.also {
@@ -1147,6 +1151,7 @@ open class RawFirBuilder(
override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression, data: Unit): FirElement { override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression, data: Unit): FirElement {
val objectDeclaration = expression.objectDeclaration val objectDeclaration = expression.objectDeclaration
return withChildClassName(SpecialNames.ANONYMOUS, forceLocalContext = true, isExpect = false) { return withChildClassName(SpecialNames.ANONYMOUS, forceLocalContext = true, isExpect = false) {
var delegatedFieldsMap: Map<Int, FirFieldSymbol>?
buildAnonymousObjectExpression { buildAnonymousObjectExpression {
val sourceElement = objectDeclaration.toFirSourceElement() val sourceElement = objectDeclaration.toFirSourceElement()
source = sourceElement source = sourceElement
@@ -1162,7 +1167,7 @@ open class RawFirBuilder(
val delegatedSelfType = objectDeclaration.toDelegatedSelfType(this) val delegatedSelfType = objectDeclaration.toDelegatedSelfType(this)
registerSelfType(delegatedSelfType) registerSelfType(delegatedSelfType)
objectDeclaration.extractAnnotationsTo(this) objectDeclaration.extractAnnotationsTo(this)
val delegatedSuperType = objectDeclaration.extractSuperTypeListEntriesTo( val (delegatedSuperType, extractedDelegatedFieldsMap) = objectDeclaration.extractSuperTypeListEntriesTo(
this, this,
delegatedSelfType, delegatedSelfType,
null, null,
@@ -1170,6 +1175,7 @@ open class RawFirBuilder(
containerTypeParameters = emptyList(), containerTypeParameters = emptyList(),
containingClassIsExpectClass = false containingClassIsExpectClass = false
) )
delegatedFieldsMap = extractedDelegatedFieldsMap
for (declaration in objectDeclaration.declarations) { for (declaration in objectDeclaration.declarations) {
declarations += declaration.toFirDeclaration( declarations += declaration.toFirDeclaration(
@@ -1180,6 +1186,8 @@ open class RawFirBuilder(
ownerTypeParameters = emptyList() 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)