org.jetbrains.kotlin.fir.plugin.ClassBuildingContext.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2022 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.plugin
import org.jetbrains.kotlin.GeneratedDeclarationKey
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.containingClassForLocalAttr
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRef
import org.jetbrains.kotlin.fir.declarations.builder.buildOuterClassTypeParameterRef
import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass
import org.jetbrains.kotlin.fir.declarations.origin
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.extensions.ExperimentalTopLevelDeclarationsGenerationApi
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
import org.jetbrains.kotlin.fir.extensions.FirExtension
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
public class ClassBuildingContext(
session: FirSession,
key: GeneratedDeclarationKey,
owner: FirClassSymbol<*>?,
private val classId: ClassId,
private val classKind: ClassKind,
) : DeclarationBuildingContext(session, key, owner) {
private val superTypeProviders = mutableListOf<(List) -> ConeKotlinType>()
/**
* Adds [type] as supertype for constructed class
*
* If no supertypes are declared [kotlin.Any] supertype will be
* added automatically
*/
public fun superType(type: ConeKotlinType) {
superTypeProviders += { type }
}
/**
* Adds type created by [typeProvider] as supertype for constructed class
* Use this overload when supertype uses type parameters of constructed class
*
* If no supertypes are declared [kotlin.Any] supertype will be
* added automatically
*/
public fun superType(typeProvider: (List) -> ConeKotlinType) {
superTypeProviders += typeProvider
}
override fun build(): FirRegularClass {
return buildRegularClass {
resolvePhase = FirResolvePhase.BODY_RESOLVE
moduleData = session.moduleData
origin = key.origin
classKind = [email protected]
scopeProvider = session.kotlinScopeProvider
status = generateStatus()
source = owner?.source?.fakeElement(KtFakeSourceElementKind.PluginGenerated)
name = classId.shortClassName
symbol = FirRegularClassSymbol(classId)
if (status.isInner) {
requireNotNull(owner) { "Inner class must have owner" }
owner.typeParameterSymbols.mapTo(typeParameters) { buildOuterClassTypeParameterRef { symbol = it } }
}
val ownParameters = [email protected] {
generateTypeParameter(it, symbol)
}
typeParameters += ownParameters
initTypeParameterBounds(typeParameters, ownParameters)
if (superTypeProviders.isEmpty()) {
superTypeRefs += session.builtinTypes.anyType
} else {
superTypeProviders.mapTo(this.superTypeRefs) {
buildResolvedTypeRef { type = it([email protected]) }
}
}
}.apply {
if (owner?.isLocal == true) {
containingClassForLocalAttr = owner.toLookupTag()
}
}
}
}
// ---------------------------------------------------------------------------------------------------------------------
/**
* Creates top-level class with given [classId]
* All declarations in class should be generated using methods from [FirDeclarationGenerationExtension]
* Generation of top-level classes with [FirDeclarationsForMetadataProviderExtension] is prohibited
*
* If no supertypes added then [kotlin.Any] supertype will be added automatically
*
* Created class won't have a constructor; constructor can be added separately with [createConstructor] function
*/
@ExperimentalTopLevelDeclarationsGenerationApi
public fun FirExtension.createTopLevelClass(
classId: ClassId,
key: GeneratedDeclarationKey,
classKind: ClassKind = ClassKind.CLASS,
config: ClassBuildingContext.() -> Unit = {}
): FirRegularClass {
return ClassBuildingContext(session, key, owner = null, classId, classKind).apply(config).build()
}
/**
* Creates nested class for [owner] class with name [name]
* If class is generated in [FirDeclarationGenerationExtension], all its declarations should be generated
* using methods from [FirDeclarationGenerationExtension]
* If class is generated in [FirDeclarationsForMetadataProviderExtension] all its declarations should be manually added right to
* FIR node of created class
*
* If no supertypes added then [kotlin.Any] supertype will be added automatically
*
* Created class won't have a constructor; constructor can be added separately with [createConstructor] function
*
* By default, the class is only nested; to create an inner class, create nested class and add inner status via status()
*/
public fun FirExtension.createNestedClass(
owner: FirClassSymbol<*>,
name: Name,
key: GeneratedDeclarationKey,
classKind: ClassKind = ClassKind.CLASS,
config: ClassBuildingContext.() -> Unit = {}
): FirRegularClass {
return ClassBuildingContext(session, key, owner, owner.classId.createNestedClassId(name), classKind).apply(config).apply {
status {
isExpect = owner.isExpect
}
}.build()
}
/**
* Creates companion object for [owner] class
* If class is generated in [FirDeclarationGenerationExtension], all its declarations should be generated
* using methods from [FirDeclarationGenerationExtension]
* If class is generated in [FirDeclarationsForMetadataProviderExtension] all its declarations should be manually added right to
* FIR node of created class
*
* If no supertypes added then [kotlin.Any] supertype will be added automatically
*
* Created class won't have a constructor; constructor can be added separately with [createDefaultPrivateConstructor] function
*/
public fun FirExtension.createCompanionObject(
owner: FirClassSymbol<*>,
key: GeneratedDeclarationKey,
config: ClassBuildingContext.() -> Unit = {}
): FirRegularClass {
val classId = owner.classId.createNestedClassId(SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT)
return ClassBuildingContext(session, key, owner, classId, ClassKind.OBJECT).apply(config).apply {
modality = Modality.FINAL
status {
isCompanion = true
isExpect = owner.isExpect
}
}.build()
}