in compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt [472:707]
fun convertClass(classNode: LighterASTNode): FirRegularClass {
var modifiers: ModifierList? = null
var classKind: ClassKind = ClassKind.CLASS
var identifier: String? = null
val firTypeParameters = mutableListOf<FirTypeParameter>()
var primaryConstructor: LighterASTNode? = null
val typeConstraints = mutableListOf<TypeConstraint>()
var classBody: LighterASTNode? = null
var superTypeList: LighterASTNode? = null
var typeParameterList: LighterASTNode? = null
classNode.forEachChildren {
when (it.tokenType) {
MODIFIER_LIST -> modifiers = convertModifierList(it, isInClass = true)
IDENTIFIER -> identifier = it.asText
}
}
val calculatedModifiers = modifiers ?: ModifierList()
val className = identifier.nameAsSafeName(if (calculatedModifiers.isCompanion()) "Companion" else "")
val isLocalWithinParent = classNode.getParent()?.elementType != CLASS_BODY && isClassLocal(classNode) { getParent() }
val classIsExpect = calculatedModifiers.hasExpect() || context.containerIsExpect
return withChildClassName(className, isExpect = classIsExpect, isLocalWithinParent) {
val classSymbol = FirRegularClassSymbol(context.currentClassId)
withContainerSymbol(classSymbol) {
classNode.forEachChildren {
when (it.tokenType) {
CLASS_KEYWORD -> classKind = ClassKind.CLASS
INTERFACE_KEYWORD -> classKind = ClassKind.INTERFACE
OBJECT_KEYWORD -> classKind = ClassKind.OBJECT
TYPE_PARAMETER_LIST -> typeParameterList = it
PRIMARY_CONSTRUCTOR -> primaryConstructor = it
SUPER_TYPE_LIST -> superTypeList = it
TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it)
CLASS_BODY -> classBody = it
}
}
if (classKind == ClassKind.CLASS) {
classKind = when {
calculatedModifiers.isEnum() -> ClassKind.ENUM_CLASS
calculatedModifiers.isAnnotation() -> ClassKind.ANNOTATION_CLASS
else -> classKind
}
}
val isLocal = context.inLocalContext
val status = FirDeclarationStatusImpl(
if (isLocal) Visibilities.Local else calculatedModifiers.getVisibility(publicByDefault = true),
calculatedModifiers.getModality(isClassOrObject = true)
).apply {
isExpect = classIsExpect
isActual = calculatedModifiers.hasActual()
isInner = calculatedModifiers.isInner()
isCompanion = calculatedModifiers.isCompanion() && classKind == ClassKind.OBJECT
isData = calculatedModifiers.isDataClass()
isInline = calculatedModifiers.isInlineClass()
isValue = calculatedModifiers.isValueClass()
isFun = calculatedModifiers.isFunctionalInterface()
isExternal = calculatedModifiers.hasExternal()
}
typeParameterList?.let { firTypeParameters += convertTypeParameters(it, typeConstraints, classSymbol) }
withCapturedTypeParameters(
status = status.isInner || isLocal,
declarationSource = classNode.toFirSourceElement(),
currentFirTypeParameters = firTypeParameters,
) {
var delegatedFieldsMap: Map<Int, FirFieldSymbol>? = null
buildRegularClass {
source = classNode.toFirSourceElement()
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
name = className
this.status = status
this.classKind = classKind
scopeProvider = baseScopeProvider
symbol = classSymbol
modifiers?.convertAnnotationsTo(annotations)
typeParameters += firTypeParameters
context.appendOuterTypeParameters(ignoreLastLevel = true, typeParameters)
val selfType = classNode.toDelegatedSelfType(this)
registerSelfType(selfType)
val delegationSpecifiers = superTypeList?.let { convertDelegationSpecifiers(it) }
var delegatedSuperTypeRef: FirTypeRef? = delegationSpecifiers?.superTypeCalls?.lastOrNull()?.delegatedSuperTypeRef
val delegatedConstructorSource: KtLightSourceElement? = delegationSpecifiers?.superTypeCalls?.lastOrNull()?.source
val superTypeRefs = mutableListOf<FirTypeRef>()
delegationSpecifiers?.let { superTypeRefs += it.superTypesRef }
when {
calculatedModifiers.isEnum() && (classKind == ClassKind.ENUM_CLASS) && delegatedConstructorSource == null -> {
delegatedSuperTypeRef = buildResolvedTypeRef {
coneType = ConeClassLikeTypeImpl(
implicitEnumType.coneType.lookupTag,
arrayOf(selfType.coneType),
isMarkedNullable = false
)
source = classNode.toFirSourceElement(KtFakeSourceElementKind.EnumSuperTypeRef)
}
superTypeRefs += delegatedSuperTypeRef
}
calculatedModifiers.isAnnotation() && (classKind == ClassKind.ANNOTATION_CLASS) -> {
superTypeRefs += implicitAnnotationType
delegatedSuperTypeRef = implicitAnyType
}
}
val classIsKotlinAny = symbol.classId == StandardClassIds.Any
if (superTypeRefs.isEmpty() && !classIsKotlinAny) {
val classIsKotlinNothing = symbol.classId == StandardClassIds.Nothing
// kotlin.Nothing doesn't have `Any` supertype, but does have delegating constructor call to Any
if (!classIsKotlinNothing) {
superTypeRefs += implicitAnyType
}
delegatedSuperTypeRef = implicitAnyType
}
this.superTypeRefs += superTypeRefs
val secondaryConstructors = classBody.getChildNodesByType(SECONDARY_CONSTRUCTOR)
val classWrapper = ClassWrapper(
calculatedModifiers, classKind, this, hasSecondaryConstructor = secondaryConstructors.isNotEmpty(),
hasDefaultConstructor = if (primaryConstructor != null) !primaryConstructor.hasValueParameters()
else secondaryConstructors.isEmpty() || secondaryConstructors.any { !it.hasValueParameters() },
delegatedSelfTypeRef = selfType,
delegatedSuperTypeRef = delegatedSuperTypeRef ?: FirImplicitTypeRefImplWithoutSource,
delegatedSuperCalls = delegationSpecifiers?.superTypeCalls ?: emptyList()
)
//parse primary constructor
val primaryConstructorWrapper = convertPrimaryConstructor(
primaryConstructor,
selfType.source,
classWrapper,
delegatedConstructorSource,
containingClassIsExpectClass = status.isExpect,
isImplicitlyActual = isImplicitlyActual(status, classKind),
isKotlinAny = classIsKotlinAny,
)
val firPrimaryConstructor = primaryConstructorWrapper?.firConstructor
firPrimaryConstructor?.let { declarations += it }
delegationSpecifiers?.delegateFieldsMap?.values?.mapTo(declarations) { it.fir }
delegatedFieldsMap = delegationSpecifiers?.delegateFieldsMap?.takeIf { it.isNotEmpty() }
val properties = mutableListOf<FirProperty>()
if (primaryConstructor != null && firPrimaryConstructor != null) {
//parse properties
properties += primaryConstructorWrapper.valueParameters
.filter { it.hasValOrVar() }
.map {
it.toFirPropertyFromPrimaryConstructor(
baseModuleData,
callableIdForName(it.firValueParameter.name),
classIsExpect,
currentDispatchReceiverType(),
context
)
}
addDeclarations(properties)
}
//parse declarations
classBody?.let {
addDeclarations(convertClassBody(it, classWrapper))
}
//parse data class
if (calculatedModifiers.isDataClass() && firPrimaryConstructor != null) {
val zippedParameters = properties.map { it.source!!.lighterASTNode to it }
DataClassMembersGenerator(
primaryConstructor ?: classNode,
this,
firPrimaryConstructor,
zippedParameters,
context.packageFqName,
context.className,
addValueParameterAnnotations = { valueParam ->
withContainerSymbol(symbol) {
valueParam.forEachChildren { node ->
if (node.tokenType == MODIFIER_LIST) {
buildList {
convertAnnotationsOnlyTo(node, this)
}.filterTo(annotations) {
it.useSiteTarget.appliesToPrimaryConstructorParameter()
}
}
}
}
},
).generate()
}
if (calculatedModifiers.isEnum()) {
generateValuesFunction(
baseModuleData,
context.packageFqName,
context.className,
classIsExpect
)
generateValueOfFunction(
baseModuleData,
context.packageFqName,
context.className,
classIsExpect
)
generateEntriesGetter(
baseModuleData,
context.packageFqName,
context.className,
classIsExpect
)
}
initCompanionObjectSymbolAttr()
contextParameters.addContextParameters(modifiers?.contextLists, classSymbol)
}.also {
it.delegateFieldsMap = delegatedFieldsMap
}
}.also {
fillDanglingConstraintsTo(firTypeParameters, typeConstraints, it)
}
}
}.also {
if (classNode.getParent()?.elementType == KtStubElementTypes.CLASS_BODY) {
it.initContainingClassForLocalAttr()
}
it.initContainingScriptOrReplAttr()
}
}