[FIR2IR] Extract logic of IR declarations generation into separate component. Part 12
This commit just moves methods which create IR callable declarations from Fir2IrClassifierStorage to newly created Fir2IrClassifiersGenerator Code in generators contains some errors (mostly because it refers to the logic of caching created declaration), and those errors will be fixed in the following commits
This commit is contained in:
committed by
Space Team
parent
e2e8a9eb8f
commit
26211a0277
@@ -11,8 +11,6 @@ import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.*
|
||||
import org.jetbrains.kotlin.backend.common.actualizer.IrActualizedResult
|
||||
import org.jetbrains.kotlin.builtins.StandardNames.DATA_CLASS_COMPONENT_PREFIX
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.ValueClassRepresentation
|
||||
import org.jetbrains.kotlin.diagnostics.startOffsetSkippingComments
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
@@ -32,7 +30,6 @@ import org.jetbrains.kotlin.fir.extensions.extensionService
|
||||
import org.jetbrains.kotlin.fir.extensions.generatedDeclarationsSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirThisReference
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirPropertyFromParameterResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
@@ -153,7 +150,7 @@ fun FirClassifierSymbol<*>.toSymbol(
|
||||
val coneClassLikeType = fir.expandedTypeRef.coneType as ConeClassLikeType
|
||||
coneClassLikeType.lookupTag.toSymbol(session)
|
||||
?.toSymbol(typeOrigin, handleAnnotations)
|
||||
?: classifierStorage.getIrClassSymbolForNotFoundClass(coneClassLikeType.lookupTag)
|
||||
?: classifiersGenerator.createIrClassSymbolForNotFoundClass(coneClassLikeType.lookupTag)
|
||||
}
|
||||
|
||||
is FirClassSymbol -> {
|
||||
|
||||
+19
-518
@@ -6,38 +6,26 @@
|
||||
package org.jetbrains.kotlin.fir.backend
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.fir.containingClassForLocalAttr
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
|
||||
import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrTypeAliasSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.toLookupTag
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runUnless
|
||||
|
||||
class Fir2IrClassifierStorage(
|
||||
private val components: Fir2IrComponents,
|
||||
@@ -45,10 +33,6 @@ class Fir2IrClassifierStorage(
|
||||
) : Fir2IrComponents by components {
|
||||
private val classCache: MutableMap<FirRegularClass, IrClass> = commonMemberStorage.classCache
|
||||
|
||||
private val localClassesCreatedOnTheFly: MutableMap<FirClass, IrClass> = mutableMapOf()
|
||||
|
||||
private var processMembersOfClassesOnTheFlyImmediately = false
|
||||
|
||||
private val typeAliasCache: MutableMap<FirTypeAlias, IrTypeAlias> = mutableMapOf()
|
||||
|
||||
private val typeParameterCache: MutableMap<FirTypeParameter, IrTypeParameter> = commonMemberStorage.typeParameterCache
|
||||
@@ -76,7 +60,7 @@ class Fir2IrClassifierStorage(
|
||||
val firClass = classId.toSymbol(session)?.fir as FirRegularClass? ?: continue
|
||||
val irClass = irBuiltinSymbol.owner
|
||||
classCache[firClass] = irClass
|
||||
processClassHeader(firClass, irClass)
|
||||
classifiersGenerator.processClassHeader(firClass, irClass)
|
||||
declarationStorage.preCacheBuiltinClassMembers(firClass, irClass)
|
||||
}
|
||||
for ((primitiveClassId, primitiveArrayId) in StandardClassIds.primitiveArrayTypeByElementType) {
|
||||
@@ -85,59 +69,32 @@ class Fir2IrClassifierStorage(
|
||||
val irType = typeConverter.classIdToTypeMap[primitiveClassId]
|
||||
val irClass = irBuiltIns.primitiveArrayForType[irType]!!.owner
|
||||
classCache[firClass] = irClass
|
||||
processClassHeader(firClass, irClass)
|
||||
classifiersGenerator.processClassHeader(firClass, irClass)
|
||||
declarationStorage.preCacheBuiltinClassMembers(firClass, irClass)
|
||||
}
|
||||
}
|
||||
|
||||
// Note: declareTypeParameters should be called before!
|
||||
private fun IrClass.setThisReceiver(typeParameters: List<FirTypeParameterRef>) {
|
||||
symbolTable.enterScope(this)
|
||||
val typeArguments = typeParameters.map {
|
||||
IrSimpleTypeImpl(getIrTypeParameterSymbol(it.symbol, ConversionTypeOrigin.DEFAULT), false, emptyList(), emptyList())
|
||||
}
|
||||
thisReceiver = declareThisReceiverParameter(
|
||||
thisType = IrSimpleTypeImpl(symbol, false, typeArguments, emptyList()),
|
||||
thisOrigin = IrDeclarationOrigin.INSTANCE_RECEIVER
|
||||
)
|
||||
symbolTable.leaveScope(this)
|
||||
}
|
||||
|
||||
internal fun preCacheTypeParameters(owner: FirTypeParameterRefsOwner, irOwnerSymbol: IrSymbol) {
|
||||
for ((index, typeParameter) in owner.typeParameters.withIndex()) {
|
||||
val original = typeParameter.symbol.fir
|
||||
getCachedIrTypeParameter(original)
|
||||
?: createIrTypeParameterWithoutBounds(original, index, irOwnerSymbol)
|
||||
?: classifiersGenerator.createIrTypeParameterWithoutBounds(original, index, irOwnerSymbol)
|
||||
if (owner is FirProperty && owner.isVar) {
|
||||
val context = ConversionTypeOrigin.SETTER
|
||||
getCachedIrTypeParameter(original, context)
|
||||
?: createIrTypeParameterWithoutBounds(original, index, irOwnerSymbol, context)
|
||||
?: classifiersGenerator.createIrTypeParameterWithoutBounds(original, index, irOwnerSymbol, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrTypeParametersContainer.setTypeParameters(
|
||||
internal fun setTypeParameters(
|
||||
irOwner: IrTypeParametersContainer,
|
||||
owner: FirTypeParameterRefsOwner,
|
||||
typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT
|
||||
) {
|
||||
typeParameters = owner.typeParameters.mapIndexedNotNull { index, typeParameter ->
|
||||
if (typeParameter !is FirTypeParameter) return@mapIndexedNotNull null
|
||||
getIrTypeParameter(typeParameter, index, symbol, typeOrigin).apply {
|
||||
parent = this@setTypeParameters
|
||||
if (superTypes.isEmpty()) {
|
||||
superTypes = typeParameter.bounds.map { it.toIrType(typeOrigin) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.declareTypeParameters(klass: FirClass) {
|
||||
preCacheTypeParameters(klass, symbol)
|
||||
setTypeParameters(klass)
|
||||
if (klass is FirRegularClass) {
|
||||
val fieldsForContextReceiversOfCurrentClass = getFieldsWithContextReceiversForClass(this, klass)
|
||||
declarations.addAll(fieldsForContextReceiversOfCurrentClass)
|
||||
}
|
||||
classifiersGenerator.setTypeParameters(irOwner, owner, typeOrigin)
|
||||
}
|
||||
|
||||
fun getFieldsWithContextReceiversForClass(irClass: IrClass, klass: FirClass): List<IrField> {
|
||||
@@ -163,16 +120,6 @@ class Fir2IrClassifierStorage(
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.declareSupertypes(klass: FirClass) {
|
||||
superTypes = klass.superTypeRefs.map { superTypeRef -> superTypeRef.toIrType() }
|
||||
}
|
||||
|
||||
private fun IrClass.declareValueClassRepresentation(klass: FirRegularClass) {
|
||||
if (this !is Fir2IrLazyClass) {
|
||||
valueClassRepresentation = computeValueClassRepresentation(klass)
|
||||
}
|
||||
}
|
||||
|
||||
fun getCachedIrClass(klass: FirClass): IrClass? {
|
||||
return if (klass is FirAnonymousObject || klass is FirRegularClass && klass.visibility == Visibilities.Local) {
|
||||
localStorage[klass]
|
||||
@@ -189,337 +136,34 @@ class Fir2IrClassifierStorage(
|
||||
return codeFragmentCache[codeFragment]
|
||||
}
|
||||
|
||||
private fun FirRegularClass.enumClassModality(): Modality {
|
||||
return when {
|
||||
declarations.any { it is FirCallableDeclaration && it.modality == Modality.ABSTRACT } -> {
|
||||
Modality.ABSTRACT
|
||||
}
|
||||
declarations.none {
|
||||
it is FirEnumEntry && isEnumEntryWhichRequiresSubclass(it)
|
||||
} -> {
|
||||
Modality.FINAL
|
||||
}
|
||||
hasAbstractMembersInScope() -> {
|
||||
Modality.ABSTRACT
|
||||
}
|
||||
else -> {
|
||||
Modality.OPEN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirRegularClass.hasAbstractMembersInScope(): Boolean {
|
||||
val scope = unsubstitutedScope()
|
||||
val names = scope.getCallableNames()
|
||||
var hasAbstract = false
|
||||
for (name in names) {
|
||||
scope.processFunctionsByName(name) {
|
||||
if (it.isAbstract) {
|
||||
hasAbstract = true
|
||||
}
|
||||
}
|
||||
if (hasAbstract) return true
|
||||
scope.processPropertiesByName(name) {
|
||||
if (it.isAbstract) {
|
||||
hasAbstract = true
|
||||
}
|
||||
}
|
||||
if (hasAbstract) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// This function is called when we refer local class earlier than we reach its declaration
|
||||
// This can happen e.g. when implicit return type has a local class constructor
|
||||
private fun createLocalIrClassOnTheFly(klass: FirClass): IrClass {
|
||||
// finding the parent class that actually contains the [klass] in the tree - it is the root one that should be created on the fly
|
||||
val classOrLocalParent = generateSequence(klass) { c ->
|
||||
(c as? FirRegularClass)?.containingClassForLocalAttr?.let { lookupTag ->
|
||||
(session.firProvider.symbolProvider.getSymbolByLookupTag(lookupTag)?.fir as? FirClass)?.takeIf {
|
||||
it.declarations.contains(c)
|
||||
}
|
||||
}
|
||||
}.last()
|
||||
val result = converter.processLocalClassAndNestedClassesOnTheFly(classOrLocalParent, temporaryParent)
|
||||
// Note: usually member creation and f/o binding is delayed till non-local classes are processed in Fir2IrConverter
|
||||
// If non-local classes are already created (this means we are in body translation) we do everything immediately
|
||||
// The last variant is possible for local variables like 'val a = object : Any() { ... }'
|
||||
if (processMembersOfClassesOnTheFlyImmediately) {
|
||||
converter.processClassMembers(classOrLocalParent, result)
|
||||
converter.bindFakeOverridesInClass(result)
|
||||
} else {
|
||||
localClassesCreatedOnTheFly[classOrLocalParent] = result
|
||||
}
|
||||
return if (classOrLocalParent === klass) result
|
||||
else (getCachedIrClass(klass)
|
||||
?: error("Assuming that all nested classes of ${classOrLocalParent.classId.asString()} should already be cached"))
|
||||
}
|
||||
|
||||
// Note: this function is called exactly once, right after Fir2IrConverter finished f/o binding for regular classes
|
||||
fun processMembersOfClassesCreatedOnTheFly() {
|
||||
// After the call of this function, members of local classes may be processed immediately
|
||||
// Before the call it's not possible, because f/o binding for regular classes isn't done yet
|
||||
processMembersOfClassesOnTheFlyImmediately = true
|
||||
for ((klass, irClass) in localClassesCreatedOnTheFly) {
|
||||
converter.processClassMembers(klass, irClass)
|
||||
// See the problem from KT-57441
|
||||
// class Wrapper {
|
||||
// private val dummy = object: Bar {}
|
||||
// private val bar = object: Bar by dummy {}
|
||||
// }
|
||||
// interface Bar {
|
||||
// val foo: String
|
||||
// get() = ""
|
||||
// }
|
||||
// When we are building bar.foo fake override, we should call dummy.foo,
|
||||
// so we should have object : Bar.foo fake override to be built and bound.
|
||||
converter.bindFakeOverridesInClass(irClass)
|
||||
}
|
||||
localClassesCreatedOnTheFly.clear()
|
||||
}
|
||||
|
||||
fun processClassHeader(klass: FirClass, irClass: IrClass = getCachedIrClass(klass)!!): IrClass {
|
||||
irClass.declareTypeParameters(klass)
|
||||
irClass.setThisReceiver(klass.typeParameters)
|
||||
irClass.declareSupertypes(klass)
|
||||
if (klass is FirRegularClass) {
|
||||
irClass.declareValueClassRepresentation(klass)
|
||||
}
|
||||
return irClass
|
||||
}
|
||||
|
||||
private fun declareIrTypeAlias(signature: IdSignature?, factory: (IrTypeAliasSymbol) -> IrTypeAlias): IrTypeAlias =
|
||||
if (signature == null)
|
||||
factory(IrTypeAliasSymbolImpl())
|
||||
else
|
||||
symbolTable.declareTypeAlias(signature, { Fir2IrTypeAliasSymbol(signature) }, factory)
|
||||
|
||||
fun registerTypeAlias(
|
||||
fun createAndCacheIrTypeAlias(
|
||||
typeAlias: FirTypeAlias,
|
||||
parent: IrDeclarationParent
|
||||
): IrTypeAlias {
|
||||
val signature = signatureComposer.composeSignature(typeAlias)
|
||||
return typeAlias.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrTypeAlias(signature) { symbol ->
|
||||
preCacheTypeParameters(typeAlias, symbol)
|
||||
val irTypeAlias = irFactory.createTypeAlias(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = IrDeclarationOrigin.DEFINED,
|
||||
name = typeAlias.name,
|
||||
visibility = components.visibilityConverter.convertToDescriptorVisibility(typeAlias.visibility),
|
||||
symbol = symbol,
|
||||
isActual = typeAlias.isActual,
|
||||
expandedType = typeAlias.expandedTypeRef.toIrType(),
|
||||
).apply {
|
||||
this.parent = parent
|
||||
setTypeParameters(typeAlias)
|
||||
if (parent is IrFile) {
|
||||
parent.declarations += this
|
||||
}
|
||||
}
|
||||
typeAliasCache[typeAlias] = irTypeAlias
|
||||
irTypeAlias
|
||||
}
|
||||
}
|
||||
return classifiersGenerator.createIrTypeAlias(typeAlias, parent)
|
||||
}
|
||||
|
||||
internal fun getCachedTypeAlias(firTypeAlias: FirTypeAlias): IrTypeAlias? = typeAliasCache[firTypeAlias]
|
||||
|
||||
private fun declareIrClass(signature: IdSignature?, factory: (IrClassSymbol) -> IrClass): IrClass =
|
||||
if (signature == null)
|
||||
factory(IrClassSymbolImpl())
|
||||
else
|
||||
symbolTable.declareClass(signature, { Fir2IrClassSymbol(signature) }, factory)
|
||||
|
||||
fun registerIrClass(
|
||||
fun createAndCacheIrClass(
|
||||
regularClass: FirRegularClass,
|
||||
parent: IrDeclarationParent,
|
||||
predefinedOrigin: IrDeclarationOrigin? = null
|
||||
): IrClass {
|
||||
val visibility = regularClass.visibility
|
||||
val modality = when (regularClass.classKind) {
|
||||
ClassKind.ENUM_CLASS -> regularClass.enumClassModality()
|
||||
ClassKind.ANNOTATION_CLASS -> Modality.OPEN
|
||||
else -> regularClass.modality ?: Modality.FINAL
|
||||
}
|
||||
val signature = runUnless(regularClass.isLocal || !configuration.linkViaSignatures) {
|
||||
signatureComposer.composeSignature(regularClass)
|
||||
}
|
||||
val irClass = regularClass.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrClass(signature) { symbol ->
|
||||
irFactory.createClass(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = regularClass.computeIrOrigin(predefinedOrigin),
|
||||
name = regularClass.name,
|
||||
visibility = components.visibilityConverter.convertToDescriptorVisibility(visibility),
|
||||
symbol = symbol,
|
||||
kind = regularClass.classKind,
|
||||
modality = modality,
|
||||
isExternal = regularClass.isExternal,
|
||||
isCompanion = regularClass.isCompanion,
|
||||
isInner = regularClass.isInner,
|
||||
isData = regularClass.isData,
|
||||
isValue = regularClass.isInline,
|
||||
isExpect = regularClass.isExpect,
|
||||
isFun = regularClass.isFun
|
||||
).apply {
|
||||
metadata = FirMetadataSource.Class(regularClass)
|
||||
}
|
||||
}
|
||||
}
|
||||
irClass.parent = parent
|
||||
if (regularClass.visibility == Visibilities.Local) {
|
||||
localStorage[regularClass] = irClass
|
||||
} else {
|
||||
classCache[regularClass] = irClass
|
||||
}
|
||||
return irClass
|
||||
return classifiersGenerator.createIrClass(regularClass, parent, predefinedOrigin)
|
||||
}
|
||||
|
||||
fun registerIrAnonymousObject(
|
||||
fun createAndCacheAnonymousObject(
|
||||
anonymousObject: FirAnonymousObject,
|
||||
visibility: Visibility = Visibilities.Local,
|
||||
name: Name = SpecialNames.NO_NAME_PROVIDED,
|
||||
irParent: IrDeclarationParent? = null
|
||||
): IrClass {
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val modality = Modality.FINAL
|
||||
val irAnonymousObject = anonymousObject.convertWithOffsets { startOffset, endOffset ->
|
||||
irFactory.createClass(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = origin,
|
||||
name = name,
|
||||
visibility = components.visibilityConverter.convertToDescriptorVisibility(visibility),
|
||||
symbol = IrClassSymbolImpl(),
|
||||
kind = anonymousObject.classKind,
|
||||
modality = modality,
|
||||
).apply {
|
||||
metadata = FirMetadataSource.Class(anonymousObject)
|
||||
}
|
||||
}
|
||||
if (irParent != null) {
|
||||
irAnonymousObject.parent = irParent
|
||||
}
|
||||
localStorage[anonymousObject] = irAnonymousObject
|
||||
return irAnonymousObject
|
||||
return classifiersGenerator.createAnonymousObject(anonymousObject, visibility, name, irParent)
|
||||
}
|
||||
|
||||
fun registerCodeFragmentClass(codeFragment: FirCodeFragment, containingFile: IrFile): IrClass {
|
||||
val conversionData = codeFragment.conversionData
|
||||
val signature = signatureComposer.composeSignature(codeFragment)
|
||||
|
||||
val irClass = codeFragment.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrClass(signature) { symbol ->
|
||||
irFactory.createClass(
|
||||
startOffset,
|
||||
endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
conversionData.classId.shortClassName,
|
||||
DescriptorVisibilities.PUBLIC,
|
||||
symbol,
|
||||
ClassKind.CLASS,
|
||||
Modality.FINAL,
|
||||
isExternal = false,
|
||||
isCompanion = false,
|
||||
isInner = false,
|
||||
isData = false,
|
||||
isValue = false,
|
||||
isExpect = false,
|
||||
isFun = false
|
||||
).apply {
|
||||
metadata = FirMetadataSource.CodeFragment(codeFragment)
|
||||
parent = containingFile
|
||||
typeParameters = emptyList()
|
||||
thisReceiver = declareThisReceiverParameter(
|
||||
thisType = IrSimpleTypeImpl(symbol, false, emptyList(), emptyList()),
|
||||
thisOrigin = IrDeclarationOrigin.INSTANCE_RECEIVER
|
||||
)
|
||||
superTypes = listOf(irBuiltIns.anyType)
|
||||
}
|
||||
}
|
||||
}
|
||||
codeFragmentCache[codeFragment] = irClass
|
||||
return irClass
|
||||
}
|
||||
|
||||
private fun getIrAnonymousObjectForEnumEntry(anonymousObject: FirAnonymousObject, name: Name, irParent: IrClass?): IrClass {
|
||||
localStorage[anonymousObject]?.let { return it }
|
||||
val irAnonymousObject = registerIrAnonymousObject(anonymousObject, Visibilities.Private, name, irParent)
|
||||
processClassHeader(anonymousObject, irAnonymousObject)
|
||||
return irAnonymousObject
|
||||
}
|
||||
|
||||
private fun createIrTypeParameterWithoutBounds(
|
||||
typeParameter: FirTypeParameter,
|
||||
index: Int,
|
||||
ownerSymbol: IrSymbol,
|
||||
typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT,
|
||||
): IrTypeParameter {
|
||||
require(index >= 0)
|
||||
val origin = typeParameter.computeIrOrigin()
|
||||
val irTypeParameter = with(typeParameter) {
|
||||
convertWithOffsets { startOffset, endOffset ->
|
||||
signatureComposer.composeTypeParameterSignature(
|
||||
index, ownerSymbol.signature
|
||||
)?.let { signature ->
|
||||
if (ownerSymbol is IrClassifierSymbol) {
|
||||
symbolTable.declareGlobalTypeParameter(
|
||||
signature,
|
||||
symbolFactory = { IrTypeParameterPublicSymbolImpl(signature) }
|
||||
) { symbol ->
|
||||
irFactory.createTypeParameter(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = origin,
|
||||
name = name,
|
||||
symbol = symbol,
|
||||
variance = variance,
|
||||
index = if (index < 0) 0 else index,
|
||||
isReified = isReified,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
symbolTable.declareScopedTypeParameter(
|
||||
signature,
|
||||
symbolFactory = { IrTypeParameterPublicSymbolImpl(signature) }
|
||||
) { symbol ->
|
||||
irFactory.createTypeParameter(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = origin,
|
||||
name = name,
|
||||
symbol = symbol,
|
||||
variance = variance,
|
||||
index = if (index < 0) 0 else index,
|
||||
isReified = isReified,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
} ?: irFactory.createTypeParameter(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = origin,
|
||||
name = name,
|
||||
symbol = IrTypeParameterSymbolImpl(),
|
||||
variance = variance,
|
||||
index = if (index < 0) 0 else index,
|
||||
isReified = isReified,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the type parameter BEFORE processing its bounds/supertypes, to properly handle recursive type bounds.
|
||||
if (typeOrigin.forSetter) {
|
||||
typeParameterCacheForSetter[typeParameter] = irTypeParameter
|
||||
} else {
|
||||
typeParameterCache[typeParameter] = irTypeParameter
|
||||
}
|
||||
annotationGenerator.generate(irTypeParameter, typeParameter)
|
||||
return irTypeParameter
|
||||
fun createAndCacheCodeFragmentClass(codeFragment: FirCodeFragment, containingFile: IrFile): IrClass {
|
||||
return classifiersGenerator.createCodeFragmentClass(codeFragment, containingFile)
|
||||
}
|
||||
|
||||
internal fun getCachedIrTypeParameter(
|
||||
@@ -539,11 +183,7 @@ class Fir2IrClassifierStorage(
|
||||
typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT
|
||||
): IrTypeParameter {
|
||||
getCachedIrTypeParameter(typeParameter, typeOrigin)?.let { return it }
|
||||
return typeParameter.run {
|
||||
val irTypeParameter = createIrTypeParameterWithoutBounds(typeParameter, index, ownerSymbol, typeOrigin)
|
||||
irTypeParameter.superTypes = bounds.map { it.toIrType() }
|
||||
irTypeParameter
|
||||
}
|
||||
return classifiersGenerator.createIrTypeParameterWithBounds(typeParameter, index, ownerSymbol, typeOrigin)
|
||||
}
|
||||
|
||||
fun putEnumEntryClassInScope(enumEntry: FirEnumEntry, correspondingClass: IrClass) {
|
||||
@@ -552,12 +192,6 @@ class Fir2IrClassifierStorage(
|
||||
|
||||
internal fun getCachedIrEnumEntry(enumEntry: FirEnumEntry): IrEnumEntry? = enumEntryCache[enumEntry]
|
||||
|
||||
private fun declareIrEnumEntry(signature: IdSignature?, factory: (IrEnumEntrySymbol) -> IrEnumEntry): IrEnumEntry =
|
||||
if (signature == null)
|
||||
factory(IrEnumEntrySymbolImpl())
|
||||
else
|
||||
symbolTable.declareEnumEntry(signature, { Fir2IrEnumEntrySymbol(signature) }, factory)
|
||||
|
||||
fun getIrEnumEntry(
|
||||
enumEntry: FirEnumEntry,
|
||||
irParent: IrClass,
|
||||
@@ -574,7 +208,7 @@ class Fir2IrClassifierStorage(
|
||||
} else {
|
||||
irParent.origin
|
||||
}
|
||||
return createIrEnumEntry(
|
||||
return classifiersGenerator.createIrEnumEntry(
|
||||
enumEntry,
|
||||
irParent = irParent,
|
||||
predefinedOrigin = predefinedOrigin
|
||||
@@ -595,110 +229,8 @@ class Fir2IrClassifierStorage(
|
||||
}
|
||||
}
|
||||
|
||||
fun createIrEnumEntry(
|
||||
enumEntry: FirEnumEntry,
|
||||
irParent: IrClass?,
|
||||
predefinedOrigin: IrDeclarationOrigin? = null,
|
||||
): IrEnumEntry {
|
||||
return enumEntry.convertWithOffsets { startOffset, endOffset ->
|
||||
val signature = signatureComposer.composeSignature(enumEntry)
|
||||
val result = declareIrEnumEntry(signature) { symbol ->
|
||||
val origin = enumEntry.computeIrOrigin(predefinedOrigin)
|
||||
irFactory.createEnumEntry(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = origin,
|
||||
name = enumEntry.name,
|
||||
symbol = symbol,
|
||||
).apply {
|
||||
declarationStorage.enterScope(this.symbol)
|
||||
if (irParent != null) {
|
||||
this.parent = irParent
|
||||
}
|
||||
if (isEnumEntryWhichRequiresSubclass(enumEntry)) {
|
||||
// An enum entry with its own members requires an anonymous object generated.
|
||||
// Otherwise, this is a default-ish enum entry whose initializer would be a delegating constructor call,
|
||||
// which will be translated via visitor later.
|
||||
val klass = getIrAnonymousObjectForEnumEntry(
|
||||
(enumEntry.initializer as FirAnonymousObjectExpression).anonymousObject, enumEntry.name, irParent
|
||||
)
|
||||
this.correspondingClass = klass
|
||||
}
|
||||
declarationStorage.leaveScope(this.symbol)
|
||||
}
|
||||
}
|
||||
enumEntryCache[enumEntry] = result
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
private fun isEnumEntryWhichRequiresSubclass(enumEntry: FirEnumEntry): Boolean {
|
||||
val initializer = enumEntry.initializer
|
||||
return initializer is FirAnonymousObjectExpression && initializer.anonymousObject.declarations.any { it !is FirConstructor }
|
||||
}
|
||||
|
||||
fun getIrClassSymbol(firClassSymbol: FirClassSymbol<*>): IrClassSymbol {
|
||||
val firClass = firClassSymbol.fir
|
||||
getCachedIrClass(firClass)?.let { return it.symbol }
|
||||
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.visibility == Visibilities.Local) {
|
||||
return createLocalIrClassOnTheFly(firClass).symbol
|
||||
}
|
||||
firClass as FirRegularClass
|
||||
val classId = firClassSymbol.classId
|
||||
val parentId = classId.outerClassId
|
||||
val parentClass = parentId?.let { session.symbolProvider.getClassLikeSymbolByClassId(it) }
|
||||
val irParent = declarationStorage.findIrParent(classId.packageFqName, parentClass?.toLookupTag(), firClassSymbol, firClass.origin)!!
|
||||
|
||||
// firClass may be referenced by some parent's type parameters as a bound. In that case, getIrClassSymbol will be called recursively.
|
||||
getCachedIrClass(firClass)?.let { return it.symbol }
|
||||
|
||||
val signature = runIf(configuration.linkViaSignatures) {
|
||||
signatureComposer.composeSignature(firClass)
|
||||
}
|
||||
val irClass = firClass.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrClass(signature) { irClassSymbol ->
|
||||
val firClassOrigin = firClass.irOrigin(session.firProvider)
|
||||
Fir2IrLazyClass(components, startOffset, endOffset, firClassOrigin, firClass, irClassSymbol).apply {
|
||||
parent = irParent
|
||||
}
|
||||
}
|
||||
}
|
||||
classCache[firClass] = irClass
|
||||
// NB: this is needed to prevent recursions in case of self bounds
|
||||
(irClass as Fir2IrLazyClass).prepareTypeParameters()
|
||||
|
||||
return irClass.symbol
|
||||
}
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
fun getIrClassSymbolForNotFoundClass(classLikeLookupTag: ConeClassLikeLookupTag): IrClassSymbol {
|
||||
val classId = classLikeLookupTag.classId
|
||||
val signature = IdSignature.CommonSignature(
|
||||
packageFqName = classId.packageFqName.asString(),
|
||||
declarationFqName = classId.relativeClassName.asString(),
|
||||
id = 0,
|
||||
mask = 0,
|
||||
description = null,
|
||||
)
|
||||
|
||||
val parentId = classId.outerClassId
|
||||
val parentClass = parentId?.let { getIrClassSymbolForNotFoundClass(it.toLookupTag()) }
|
||||
val irParent = parentClass?.owner ?: declarationStorage.getIrExternalPackageFragment(classId.packageFqName)
|
||||
|
||||
return symbolTable.referenceClass(signature, { Fir2IrClassSymbol(signature) }) {
|
||||
irFactory.createClass(
|
||||
startOffset = UNDEFINED_OFFSET,
|
||||
endOffset = UNDEFINED_OFFSET,
|
||||
origin = IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
|
||||
name = classId.shortClassName,
|
||||
visibility = DescriptorVisibilities.DEFAULT_VISIBILITY,
|
||||
symbol = it,
|
||||
kind = ClassKind.CLASS,
|
||||
modality = Modality.FINAL,
|
||||
).apply {
|
||||
parent = irParent
|
||||
}
|
||||
}
|
||||
return classifiersGenerator.createIrClassSymbolByFirSymbol(firClassSymbol)
|
||||
}
|
||||
|
||||
fun getIrTypeParameterSymbol(
|
||||
@@ -715,40 +247,9 @@ class Fir2IrClassifierStorage(
|
||||
}
|
||||
|
||||
if (components.configuration.allowNonCachedDeclarations) {
|
||||
val firTypeParameterOwnerSymbol = firTypeParameter.containingDeclarationSymbol
|
||||
val firTypeParameterOwner = firTypeParameterOwnerSymbol.fir as FirTypeParameterRefsOwner
|
||||
val index = firTypeParameterOwner.typeParameters.indexOf(firTypeParameter).also { check(it >= 0) }
|
||||
|
||||
val isSetter = firTypeParameterOwner is FirPropertyAccessor && firTypeParameterOwner.isSetter
|
||||
val conversionTypeOrigin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
|
||||
|
||||
return createIrTypeParameterWithoutBounds(firTypeParameter, index, IrTypeParameterSymbolImpl(), conversionTypeOrigin).apply {
|
||||
superTypes = firTypeParameter.bounds.map { it.toIrType(typeConverter) }
|
||||
}.symbol
|
||||
return classifiersGenerator.createIrTypeParameterForNonCachedDeclaration(firTypeParameter)
|
||||
}
|
||||
|
||||
error("Cannot find cached type parameter by FIR symbol: ${firTypeParameterSymbol.name} of the owner: ${firTypeParameter.containingDeclarationSymbol}")
|
||||
}
|
||||
|
||||
private val temporaryParent by lazy {
|
||||
irFactory.createSimpleFunction(
|
||||
startOffset = UNDEFINED_OFFSET,
|
||||
endOffset = UNDEFINED_OFFSET,
|
||||
origin = IrDeclarationOrigin.DEFINED,
|
||||
name = Name.special("<stub>"),
|
||||
visibility = DescriptorVisibilities.PRIVATE,
|
||||
isInline = false,
|
||||
isExpect = false,
|
||||
returnType = irBuiltIns.unitType,
|
||||
modality = Modality.FINAL,
|
||||
symbol = IrSimpleFunctionSymbolImpl(),
|
||||
isTailrec = false,
|
||||
isSuspend = false,
|
||||
isOperator = false,
|
||||
isInfix = false,
|
||||
isExternal = false,
|
||||
).apply {
|
||||
parent = IrExternalPackageFragmentImpl(IrExternalPackageFragmentSymbolImpl(), FqName.ROOT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ interface Fir2IrComponents {
|
||||
val visibilityConverter: Fir2IrVisibilityConverter
|
||||
|
||||
val callablesGenerator: Fir2IrCallableDeclarationsGenerator
|
||||
val classifiersGenerator: Fir2IrClassifiersGenerator
|
||||
val lazyDeclarationsGenerator: Fir2IrLazyDeclarationsGenerator
|
||||
|
||||
val annotationGenerator: AnnotationGenerator
|
||||
|
||||
@@ -38,6 +38,7 @@ class Fir2IrComponentsStorage(
|
||||
override val declarationStorage: Fir2IrDeclarationStorage = Fir2IrDeclarationStorage(this, moduleDescriptor, commonMemberStorage)
|
||||
|
||||
override val callablesGenerator: Fir2IrCallableDeclarationsGenerator = Fir2IrCallableDeclarationsGenerator(this)
|
||||
override val classifiersGenerator: Fir2IrClassifiersGenerator = Fir2IrClassifiersGenerator(this)
|
||||
override val lazyDeclarationsGenerator: Fir2IrLazyDeclarationsGenerator = Fir2IrLazyDeclarationsGenerator(this)
|
||||
|
||||
// builtins should go after storages and generators, because they use them during initialization
|
||||
|
||||
@@ -92,7 +92,7 @@ class Fir2IrConverter(
|
||||
postponedDeclarationsForFakeOverridesBinding.clear()
|
||||
|
||||
// Do (3) and (4) for local classes encountered during (3)
|
||||
classifierStorage.processMembersOfClassesCreatedOnTheFly()
|
||||
classifiersGenerator.processMembersOfClassesCreatedOnTheFly()
|
||||
|
||||
// 5. Body processing
|
||||
// If we encounter local class / anonymous object here, then we perform all (1)-(5) stages immediately
|
||||
@@ -156,7 +156,7 @@ class Fir2IrConverter(
|
||||
for (declaration in file.declarations) {
|
||||
when (declaration) {
|
||||
is FirRegularClass -> registerClassAndNestedClasses(declaration, irFile)
|
||||
is FirCodeFragment -> classifierStorage.registerCodeFragmentClass(declaration, irFile)
|
||||
is FirCodeFragment -> classifierStorage.createAndCacheCodeFragmentClass(declaration, irFile)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@ class Fir2IrConverter(
|
||||
file.declarations.forEach {
|
||||
when (it) {
|
||||
is FirRegularClass -> processClassAndNestedClassHeaders(it)
|
||||
is FirTypeAlias -> classifierStorage.registerTypeAlias(it, declarationStorage.getIrFile(file))
|
||||
is FirTypeAlias -> classifierStorage.createAndCacheIrTypeAlias(it, declarationStorage.getIrFile(file))
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -373,8 +373,8 @@ class Fir2IrConverter(
|
||||
classifierStorage.getCachedIrClass(klass)?.apply {
|
||||
this.parent = parent
|
||||
} ?: when (klass) {
|
||||
is FirRegularClass -> classifierStorage.registerIrClass(klass, parent)
|
||||
is FirAnonymousObject -> classifierStorage.registerIrAnonymousObject(klass, irParent = parent)
|
||||
is FirRegularClass -> classifierStorage.createAndCacheIrClass(klass, parent)
|
||||
is FirAnonymousObject -> classifierStorage.createAndCacheAnonymousObject(klass, irParent = parent)
|
||||
}
|
||||
registerNestedClasses(klass, irClass)
|
||||
return irClass
|
||||
@@ -396,7 +396,7 @@ class Fir2IrConverter(
|
||||
}
|
||||
|
||||
private fun processClassAndNestedClassHeaders(klass: FirClass) {
|
||||
classifierStorage.processClassHeader(klass)
|
||||
classifiersGenerator.processClassHeader(klass)
|
||||
processNestedClassHeaders(klass)
|
||||
}
|
||||
|
||||
@@ -437,7 +437,7 @@ class Fir2IrConverter(
|
||||
registerClassAndNestedClasses(scriptStatement, irScript)
|
||||
processClassAndNestedClassHeaders(scriptStatement)
|
||||
}
|
||||
is FirTypeAlias -> classifierStorage.registerTypeAlias(scriptStatement, irScript)
|
||||
is FirTypeAlias -> classifierStorage.createAndCacheIrTypeAlias(scriptStatement, irScript)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ class Fir2IrTypeConverter(
|
||||
?: lookupTag.toSymbol(session)?.toSymbol(typeOrigin) {
|
||||
typeAnnotations += with(annotationGenerator) { it.toIrAnnotations() }
|
||||
}
|
||||
?: (lookupTag as? ConeClassLikeLookupTag)?.let(classifierStorage::getIrClassSymbolForNotFoundClass)
|
||||
?: (lookupTag as? ConeClassLikeLookupTag)?.let(classifiersGenerator::createIrClassSymbolForNotFoundClass)
|
||||
?: return createErrorType()
|
||||
|
||||
when {
|
||||
|
||||
+4
-8
@@ -452,11 +452,9 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
|
||||
if (propertyAccessorForAnnotations != null) {
|
||||
convertAnnotationsForNonDeclaredMembers(propertyAccessorForAnnotations, origin)
|
||||
}
|
||||
with(classifierStorage) {
|
||||
setTypeParameters(
|
||||
property, if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
|
||||
)
|
||||
}
|
||||
classifiersGenerator.setTypeParameters(
|
||||
this, property, if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
|
||||
)
|
||||
val dispatchReceiverType = computeDispatchReceiverType(this, property, irParent)
|
||||
// NB: we should enter accessor' scope before declaring its parameters
|
||||
// (both setter default and receiver ones, if any)
|
||||
@@ -686,9 +684,7 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
|
||||
val containingClass = computeContainingClass(irParent)
|
||||
val parent = this
|
||||
if (function is FirSimpleFunction || function is FirConstructor) {
|
||||
with(classifierStorage) {
|
||||
setTypeParameters(function)
|
||||
}
|
||||
classifiersGenerator.setTypeParameters(this, function)
|
||||
}
|
||||
val typeOrigin = if (forSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
|
||||
if (function is FirDefaultPropertySetter) {
|
||||
|
||||
+570
@@ -0,0 +1,570 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.backend.generators
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.fir.backend.*
|
||||
import org.jetbrains.kotlin.fir.containingClassForLocalAttr
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
|
||||
import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrTypeAliasSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.toLookupTag
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runUnless
|
||||
|
||||
class Fir2IrClassifiersGenerator(val components: Fir2IrComponents) : Fir2IrComponents by components {
|
||||
private val localClassesCreatedOnTheFly: MutableMap<FirClass, IrClass> = mutableMapOf()
|
||||
|
||||
private var processMembersOfClassesOnTheFlyImmediately = false
|
||||
|
||||
internal fun setTypeParameters(
|
||||
irOwner: IrTypeParametersContainer,
|
||||
owner: FirTypeParameterRefsOwner,
|
||||
typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT
|
||||
) {
|
||||
irOwner.typeParameters = owner.typeParameters.mapIndexedNotNull { index, typeParameter ->
|
||||
if (typeParameter !is FirTypeParameter) return@mapIndexedNotNull null
|
||||
classifierStorage.getIrTypeParameter(typeParameter, index, irOwner.symbol, typeOrigin).apply {
|
||||
parent = irOwner
|
||||
if (superTypes.isEmpty()) {
|
||||
superTypes = typeParameter.bounds.map { it.toIrType(typeOrigin) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.declareTypeParameters(klass: FirClass) {
|
||||
classifierStorage.preCacheTypeParameters(klass, symbol)
|
||||
setTypeParameters(this, klass)
|
||||
if (klass is FirRegularClass) {
|
||||
val fieldsForContextReceiversOfCurrentClass = classifierStorage.getFieldsWithContextReceiversForClass(this, klass)
|
||||
declarations.addAll(fieldsForContextReceiversOfCurrentClass)
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.declareSupertypes(klass: FirClass) {
|
||||
superTypes = klass.superTypeRefs.map { superTypeRef -> superTypeRef.toIrType() }
|
||||
}
|
||||
|
||||
private fun IrClass.declareValueClassRepresentation(klass: FirRegularClass) {
|
||||
if (this !is Fir2IrLazyClass) {
|
||||
valueClassRepresentation = computeValueClassRepresentation(klass)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirRegularClass.enumClassModality(): Modality {
|
||||
return when {
|
||||
declarations.any { it is FirCallableDeclaration && it.modality == Modality.ABSTRACT } -> {
|
||||
Modality.ABSTRACT
|
||||
}
|
||||
declarations.none {
|
||||
it is FirEnumEntry && isEnumEntryWhichRequiresSubclass(it)
|
||||
} -> {
|
||||
Modality.FINAL
|
||||
}
|
||||
hasAbstractMembersInScope() -> {
|
||||
Modality.ABSTRACT
|
||||
}
|
||||
else -> {
|
||||
Modality.OPEN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirRegularClass.hasAbstractMembersInScope(): Boolean {
|
||||
val scope = unsubstitutedScope()
|
||||
val names = scope.getCallableNames()
|
||||
var hasAbstract = false
|
||||
for (name in names) {
|
||||
scope.processFunctionsByName(name) {
|
||||
if (it.isAbstract) {
|
||||
hasAbstract = true
|
||||
}
|
||||
}
|
||||
if (hasAbstract) return true
|
||||
scope.processPropertiesByName(name) {
|
||||
if (it.isAbstract) {
|
||||
hasAbstract = true
|
||||
}
|
||||
}
|
||||
if (hasAbstract) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: it's worth to move this onTheFly stuff back to classifier storage
|
||||
// This function is called when we refer local class earlier than we reach its declaration
|
||||
// This can happen e.g. when implicit return type has a local class constructor
|
||||
private fun createLocalIrClassOnTheFly(klass: FirClass): IrClass {
|
||||
// finding the parent class that actually contains the [klass] in the tree - it is the root one that should be created on the fly
|
||||
val classOrLocalParent = generateSequence(klass) { c ->
|
||||
(c as? FirRegularClass)?.containingClassForLocalAttr?.let { lookupTag ->
|
||||
(session.firProvider.symbolProvider.getSymbolByLookupTag(lookupTag)?.fir as? FirClass)?.takeIf {
|
||||
it.declarations.contains(c)
|
||||
}
|
||||
}
|
||||
}.last()
|
||||
val result = converter.processLocalClassAndNestedClassesOnTheFly(classOrLocalParent, temporaryParent)
|
||||
// Note: usually member creation and f/o binding is delayed till non-local classes are processed in Fir2IrConverter
|
||||
// If non-local classes are already created (this means we are in body translation) we do everything immediately
|
||||
// The last variant is possible for local variables like 'val a = object : Any() { ... }'
|
||||
if (processMembersOfClassesOnTheFlyImmediately) {
|
||||
converter.processClassMembers(classOrLocalParent, result)
|
||||
converter.bindFakeOverridesInClass(result)
|
||||
} else {
|
||||
localClassesCreatedOnTheFly[classOrLocalParent] = result
|
||||
}
|
||||
return if (classOrLocalParent === klass) result
|
||||
else (classifierStorage.getCachedIrClass(klass)
|
||||
?: error("Assuming that all nested classes of ${classOrLocalParent.classId.asString()} should already be cached"))
|
||||
}
|
||||
|
||||
// Note: this function is called exactly once, right after Fir2IrConverter finished f/o binding for regular classes
|
||||
fun processMembersOfClassesCreatedOnTheFly() {
|
||||
// After the call of this function, members of local classes may be processed immediately
|
||||
// Before the call it's not possible, because f/o binding for regular classes isn't done yet
|
||||
processMembersOfClassesOnTheFlyImmediately = true
|
||||
for ((klass, irClass) in localClassesCreatedOnTheFly) {
|
||||
converter.processClassMembers(klass, irClass)
|
||||
// See the problem from KT-57441
|
||||
// class Wrapper {
|
||||
// private val dummy = object: Bar {}
|
||||
// private val bar = object: Bar by dummy {}
|
||||
// }
|
||||
// interface Bar {
|
||||
// val foo: String
|
||||
// get() = ""
|
||||
// }
|
||||
// When we are building bar.foo fake override, we should call dummy.foo,
|
||||
// so we should have object : Bar.foo fake override to be built and bound.
|
||||
converter.bindFakeOverridesInClass(irClass)
|
||||
}
|
||||
localClassesCreatedOnTheFly.clear()
|
||||
}
|
||||
|
||||
fun processClassHeader(klass: FirClass, irClass: IrClass = classifierStorage.getCachedIrClass(klass)!!): IrClass {
|
||||
irClass.declareTypeParameters(klass)
|
||||
irClass.setThisReceiver(klass.typeParameters)
|
||||
irClass.declareSupertypes(klass)
|
||||
if (klass is FirRegularClass) {
|
||||
irClass.declareValueClassRepresentation(klass)
|
||||
}
|
||||
return irClass
|
||||
}
|
||||
|
||||
private fun IrClass.setThisReceiver(typeParameters: List<FirTypeParameterRef>) {
|
||||
symbolTable.enterScope(this)
|
||||
val typeArguments = typeParameters.map {
|
||||
IrSimpleTypeImpl(classifierStorage.getIrTypeParameterSymbol(it.symbol, ConversionTypeOrigin.DEFAULT), false, emptyList(), emptyList())
|
||||
}
|
||||
thisReceiver = declareThisReceiverParameter(
|
||||
thisType = IrSimpleTypeImpl(symbol, false, typeArguments, emptyList()),
|
||||
thisOrigin = IrDeclarationOrigin.INSTANCE_RECEIVER
|
||||
)
|
||||
symbolTable.leaveScope(this)
|
||||
}
|
||||
|
||||
|
||||
private fun declareIrTypeAlias(signature: IdSignature?, factory: (IrTypeAliasSymbol) -> IrTypeAlias): IrTypeAlias =
|
||||
if (signature == null)
|
||||
factory(IrTypeAliasSymbolImpl())
|
||||
else
|
||||
symbolTable.declareTypeAlias(signature, { Fir2IrTypeAliasSymbol(signature) }, factory)
|
||||
|
||||
fun createIrTypeAlias(
|
||||
typeAlias: FirTypeAlias,
|
||||
parent: IrDeclarationParent
|
||||
): IrTypeAlias = typeAlias.convertWithOffsets { startOffset, endOffset ->
|
||||
val signature = signatureComposer.composeSignature(typeAlias)
|
||||
declareIrTypeAlias(signature) { symbol ->
|
||||
classifierStorage.preCacheTypeParameters(typeAlias, symbol)
|
||||
val irTypeAlias = irFactory.createTypeAlias(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = IrDeclarationOrigin.DEFINED,
|
||||
name = typeAlias.name,
|
||||
visibility = components.visibilityConverter.convertToDescriptorVisibility(typeAlias.visibility),
|
||||
symbol = symbol,
|
||||
isActual = typeAlias.isActual,
|
||||
expandedType = typeAlias.expandedTypeRef.toIrType(),
|
||||
).apply {
|
||||
this.parent = parent
|
||||
setTypeParameters(this, typeAlias)
|
||||
if (parent is IrFile) {
|
||||
parent.declarations += this
|
||||
}
|
||||
}
|
||||
typeAliasCache[typeAlias] = irTypeAlias
|
||||
irTypeAlias
|
||||
}
|
||||
}
|
||||
|
||||
fun declareIrClass(signature: IdSignature?, factory: (IrClassSymbol) -> IrClass): IrClass {
|
||||
return if (signature == null)
|
||||
factory(IrClassSymbolImpl())
|
||||
else
|
||||
symbolTable.declareClass(signature, { Fir2IrClassSymbol(signature) }, factory)
|
||||
}
|
||||
|
||||
fun createIrClass(
|
||||
regularClass: FirRegularClass,
|
||||
parent: IrDeclarationParent,
|
||||
predefinedOrigin: IrDeclarationOrigin? = null
|
||||
): IrClass {
|
||||
val visibility = regularClass.visibility
|
||||
val modality = when (regularClass.classKind) {
|
||||
ClassKind.ENUM_CLASS -> regularClass.enumClassModality()
|
||||
ClassKind.ANNOTATION_CLASS -> Modality.OPEN
|
||||
else -> regularClass.modality ?: Modality.FINAL
|
||||
}
|
||||
val signature = runUnless(regularClass.isLocal || !configuration.linkViaSignatures) {
|
||||
signatureComposer.composeSignature(regularClass)
|
||||
}
|
||||
val irClass = regularClass.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrClass(signature) { symbol ->
|
||||
irFactory.createClass(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = regularClass.computeIrOrigin(predefinedOrigin),
|
||||
name = regularClass.name,
|
||||
visibility = components.visibilityConverter.convertToDescriptorVisibility(visibility),
|
||||
symbol = symbol,
|
||||
kind = regularClass.classKind,
|
||||
modality = modality,
|
||||
isExternal = regularClass.isExternal,
|
||||
isCompanion = regularClass.isCompanion,
|
||||
isInner = regularClass.isInner,
|
||||
isData = regularClass.isData,
|
||||
isValue = regularClass.isInline,
|
||||
isExpect = regularClass.isExpect,
|
||||
isFun = regularClass.isFun
|
||||
).apply {
|
||||
metadata = FirMetadataSource.Class(regularClass)
|
||||
}
|
||||
}
|
||||
}
|
||||
irClass.parent = parent
|
||||
if (regularClass.visibility == Visibilities.Local) {
|
||||
localStorage[regularClass] = irClass
|
||||
} else {
|
||||
classCache[regularClass] = irClass
|
||||
}
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun createAnonymousObject(
|
||||
anonymousObject: FirAnonymousObject,
|
||||
visibility: Visibility = Visibilities.Local,
|
||||
name: Name = SpecialNames.NO_NAME_PROVIDED,
|
||||
irParent: IrDeclarationParent? = null
|
||||
): IrClass {
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val modality = Modality.FINAL
|
||||
val irAnonymousObject = anonymousObject.convertWithOffsets { startOffset, endOffset ->
|
||||
irFactory.createClass(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = origin,
|
||||
name = name,
|
||||
visibility = components.visibilityConverter.convertToDescriptorVisibility(visibility),
|
||||
symbol = IrClassSymbolImpl(),
|
||||
kind = anonymousObject.classKind,
|
||||
modality = modality,
|
||||
).apply {
|
||||
metadata = FirMetadataSource.Class(anonymousObject)
|
||||
}
|
||||
}
|
||||
if (irParent != null) {
|
||||
irAnonymousObject.parent = irParent
|
||||
}
|
||||
localStorage[anonymousObject] = irAnonymousObject
|
||||
return irAnonymousObject
|
||||
}
|
||||
|
||||
fun createCodeFragmentClass(codeFragment: FirCodeFragment, containingFile: IrFile): IrClass {
|
||||
val conversionData = codeFragment.conversionData
|
||||
val signature = signatureComposer.composeSignature(codeFragment)
|
||||
|
||||
val irClass = codeFragment.convertWithOffsets { startOffset, endOffset ->
|
||||
declareIrClass(signature) { symbol ->
|
||||
irFactory.createClass(
|
||||
startOffset,
|
||||
endOffset,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
conversionData.classId.shortClassName,
|
||||
DescriptorVisibilities.PUBLIC,
|
||||
symbol,
|
||||
ClassKind.CLASS,
|
||||
Modality.FINAL,
|
||||
isExternal = false,
|
||||
isCompanion = false,
|
||||
isInner = false,
|
||||
isData = false,
|
||||
isValue = false,
|
||||
isExpect = false,
|
||||
isFun = false
|
||||
).apply {
|
||||
metadata = FirMetadataSource.CodeFragment(codeFragment)
|
||||
parent = containingFile
|
||||
typeParameters = emptyList()
|
||||
thisReceiver = declareThisReceiverParameter(
|
||||
thisType = IrSimpleTypeImpl(symbol, false, emptyList(), emptyList()),
|
||||
thisOrigin = IrDeclarationOrigin.INSTANCE_RECEIVER
|
||||
)
|
||||
superTypes = listOf(irBuiltIns.anyType)
|
||||
}
|
||||
}
|
||||
}
|
||||
codeFragmentCache[codeFragment] = irClass
|
||||
return irClass
|
||||
}
|
||||
|
||||
private fun getIrAnonymousObjectForEnumEntry(anonymousObject: FirAnonymousObject, name: Name, irParent: IrClass?): IrClass {
|
||||
localStorage[anonymousObject]?.let { return it }
|
||||
val irAnonymousObject = classifierStorage.createAndCacheAnonymousObject(anonymousObject, Visibilities.Private, name, irParent)
|
||||
processClassHeader(anonymousObject, irAnonymousObject)
|
||||
return irAnonymousObject
|
||||
}
|
||||
|
||||
fun createIrTypeParameterWithBounds(
|
||||
typeParameter: FirTypeParameter,
|
||||
index: Int,
|
||||
ownerSymbol: IrSymbol,
|
||||
typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT,
|
||||
): IrTypeParameter {
|
||||
val irTypeParameter = createIrTypeParameterWithoutBounds(typeParameter, index, ownerSymbol, typeOrigin)
|
||||
irTypeParameter.superTypes = typeParameter.bounds.map { it.toIrType() }
|
||||
return irTypeParameter
|
||||
}
|
||||
|
||||
fun createIrTypeParameterWithoutBounds(
|
||||
typeParameter: FirTypeParameter,
|
||||
index: Int,
|
||||
ownerSymbol: IrSymbol,
|
||||
typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT,
|
||||
): IrTypeParameter {
|
||||
require(index >= 0)
|
||||
val origin = typeParameter.computeIrOrigin()
|
||||
val irTypeParameter = with(typeParameter) {
|
||||
convertWithOffsets { startOffset, endOffset ->
|
||||
signatureComposer.composeTypeParameterSignature(
|
||||
index, ownerSymbol.signature
|
||||
)?.let { signature ->
|
||||
if (ownerSymbol is IrClassifierSymbol) {
|
||||
symbolTable.declareGlobalTypeParameter(
|
||||
signature,
|
||||
symbolFactory = { IrTypeParameterPublicSymbolImpl(signature) }
|
||||
) { symbol ->
|
||||
irFactory.createTypeParameter(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = origin,
|
||||
name = name,
|
||||
symbol = symbol,
|
||||
variance = variance,
|
||||
index = if (index < 0) 0 else index,
|
||||
isReified = isReified,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
symbolTable.declareScopedTypeParameter(
|
||||
signature,
|
||||
symbolFactory = { IrTypeParameterPublicSymbolImpl(signature) }
|
||||
) { symbol ->
|
||||
irFactory.createTypeParameter(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = origin,
|
||||
name = name,
|
||||
symbol = symbol,
|
||||
variance = variance,
|
||||
index = if (index < 0) 0 else index,
|
||||
isReified = isReified,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
} ?: irFactory.createTypeParameter(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = origin,
|
||||
name = name,
|
||||
symbol = IrTypeParameterSymbolImpl(),
|
||||
variance = variance,
|
||||
index = if (index < 0) 0 else index,
|
||||
isReified = isReified,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the type parameter BEFORE processing its bounds/supertypes, to properly handle recursive type bounds.
|
||||
if (typeOrigin.forSetter) {
|
||||
typeParameterCacheForSetter[typeParameter] = irTypeParameter
|
||||
} else {
|
||||
typeParameterCache[typeParameter] = irTypeParameter
|
||||
}
|
||||
annotationGenerator.generate(irTypeParameter, typeParameter)
|
||||
return irTypeParameter
|
||||
}
|
||||
|
||||
private fun declareIrEnumEntry(signature: IdSignature?, factory: (IrEnumEntrySymbol) -> IrEnumEntry): IrEnumEntry {
|
||||
return if (signature == null)
|
||||
factory(IrEnumEntrySymbolImpl())
|
||||
else
|
||||
symbolTable.declareEnumEntry(signature, { Fir2IrEnumEntrySymbol(signature) }, factory)
|
||||
}
|
||||
|
||||
fun createIrEnumEntry(
|
||||
enumEntry: FirEnumEntry,
|
||||
irParent: IrClass?,
|
||||
predefinedOrigin: IrDeclarationOrigin? = null,
|
||||
): IrEnumEntry {
|
||||
return enumEntry.convertWithOffsets { startOffset, endOffset ->
|
||||
val signature = signatureComposer.composeSignature(enumEntry)
|
||||
val result = declareIrEnumEntry(signature) { symbol ->
|
||||
val origin = enumEntry.computeIrOrigin(predefinedOrigin)
|
||||
irFactory.createEnumEntry(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
origin = origin,
|
||||
name = enumEntry.name,
|
||||
symbol = symbol,
|
||||
).apply {
|
||||
declarationStorage.enterScope(this.symbol)
|
||||
if (irParent != null) {
|
||||
this.parent = irParent
|
||||
}
|
||||
if (isEnumEntryWhichRequiresSubclass(enumEntry)) {
|
||||
// An enum entry with its own members requires an anonymous object generated.
|
||||
// Otherwise, this is a default-ish enum entry whose initializer would be a delegating constructor call,
|
||||
// which will be translated via visitor later.
|
||||
val klass = getIrAnonymousObjectForEnumEntry(
|
||||
(enumEntry.initializer as FirAnonymousObjectExpression).anonymousObject, enumEntry.name, irParent
|
||||
)
|
||||
this.correspondingClass = klass
|
||||
}
|
||||
declarationStorage.leaveScope(this.symbol)
|
||||
}
|
||||
}
|
||||
enumEntryCache[enumEntry] = result
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
private fun isEnumEntryWhichRequiresSubclass(enumEntry: FirEnumEntry): Boolean {
|
||||
val initializer = enumEntry.initializer
|
||||
return initializer is FirAnonymousObjectExpression && initializer.anonymousObject.declarations.any { it !is FirConstructor }
|
||||
}
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
fun createIrClassSymbolForNotFoundClass(classLikeLookupTag: ConeClassLikeLookupTag): IrClassSymbol {
|
||||
val classId = classLikeLookupTag.classId
|
||||
val signature = IdSignature.CommonSignature(
|
||||
packageFqName = classId.packageFqName.asString(),
|
||||
declarationFqName = classId.relativeClassName.asString(),
|
||||
id = 0,
|
||||
mask = 0,
|
||||
description = null,
|
||||
)
|
||||
|
||||
val parentId = classId.outerClassId
|
||||
val parentClass = parentId?.let { createIrClassSymbolForNotFoundClass(it.toLookupTag()) }
|
||||
val irParent = parentClass?.owner ?: declarationStorage.getIrExternalPackageFragment(classId.packageFqName)
|
||||
|
||||
return symbolTable.referenceClass(signature, { Fir2IrClassSymbol(signature) }) {
|
||||
irFactory.createClass(
|
||||
startOffset = UNDEFINED_OFFSET,
|
||||
endOffset = UNDEFINED_OFFSET,
|
||||
origin = IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
|
||||
name = classId.shortClassName,
|
||||
visibility = DescriptorVisibilities.DEFAULT_VISIBILITY,
|
||||
symbol = it,
|
||||
kind = ClassKind.CLASS,
|
||||
modality = Modality.FINAL,
|
||||
).apply {
|
||||
parent = irParent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: should be decomposed
|
||||
fun createIrClassSymbolByFirSymbol(firClassSymbol: FirClassSymbol<*>): IrClassSymbol {
|
||||
val firClass = firClassSymbol.fir
|
||||
classifierStorage.getCachedIrClass(firClass)?.let { return it.symbol }
|
||||
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.visibility == Visibilities.Local) {
|
||||
return createLocalIrClassOnTheFly(firClass).symbol
|
||||
}
|
||||
firClass as FirRegularClass
|
||||
val classId = firClassSymbol.classId
|
||||
val parentId = classId.outerClassId
|
||||
val parentClass = parentId?.let { session.symbolProvider.getClassLikeSymbolByClassId(it) }
|
||||
val irParent = declarationStorage.findIrParent(classId.packageFqName, parentClass?.toLookupTag(), firClassSymbol, firClass.origin)!!
|
||||
|
||||
// firClass may be referenced by some parent's type parameters as a bound. In that case, getIrClassSymbol will be called recursively.
|
||||
classifierStorage.getCachedIrClass(firClass)?.let { return it.symbol }
|
||||
|
||||
val irClass = lazyDeclarationsGenerator.createIrLazyClass(firClass, irParent)
|
||||
classCache[firClass] = irClass
|
||||
// NB: this is needed to prevent recursions in case of self bounds
|
||||
(irClass as Fir2IrLazyClass).prepareTypeParameters()
|
||||
|
||||
return irClass.symbol
|
||||
}
|
||||
|
||||
|
||||
fun createIrTypeParameterForNonCachedDeclaration(firTypeParameter: FirTypeParameter): IrTypeParameterSymbol {
|
||||
val firTypeParameterOwnerSymbol = firTypeParameter.containingDeclarationSymbol
|
||||
val firTypeParameterOwner = firTypeParameterOwnerSymbol.fir as FirTypeParameterRefsOwner
|
||||
val index = firTypeParameterOwner.typeParameters.indexOf(firTypeParameter).also { check(it >= 0) }
|
||||
|
||||
val isSetter = firTypeParameterOwner is FirPropertyAccessor && firTypeParameterOwner.isSetter
|
||||
val conversionTypeOrigin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
|
||||
|
||||
return createIrTypeParameterWithoutBounds(firTypeParameter, index, IrTypeParameterSymbolImpl(), conversionTypeOrigin).apply {
|
||||
superTypes = firTypeParameter.bounds.map { it.toIrType(typeConverter) }
|
||||
}.symbol
|
||||
}
|
||||
|
||||
private val temporaryParent by lazy {
|
||||
irFactory.createSimpleFunction(
|
||||
startOffset = UNDEFINED_OFFSET,
|
||||
endOffset = UNDEFINED_OFFSET,
|
||||
origin = IrDeclarationOrigin.DEFINED,
|
||||
name = Name.special("<stub>"),
|
||||
visibility = DescriptorVisibilities.PRIVATE,
|
||||
isInline = false,
|
||||
isExpect = false,
|
||||
returnType = irBuiltIns.unitType,
|
||||
modality = Modality.FINAL,
|
||||
symbol = IrSimpleFunctionSymbolImpl(),
|
||||
isTailrec = false,
|
||||
isSuspend = false,
|
||||
isOperator = false,
|
||||
isInfix = false,
|
||||
isExternal = false,
|
||||
).apply {
|
||||
parent = IrExternalPackageFragmentImpl(IrExternalPackageFragmentSymbolImpl(), FqName.ROOT)
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-4
@@ -7,8 +7,11 @@ package org.jetbrains.kotlin.fir.backend.generators
|
||||
|
||||
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
|
||||
import org.jetbrains.kotlin.fir.backend.convertWithOffsets
|
||||
import org.jetbrains.kotlin.fir.backend.irOrigin
|
||||
import org.jetbrains.kotlin.fir.backend.isStubPropertyForPureField
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.dispatchReceiverClassLookupTagOrNull
|
||||
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
||||
@@ -16,13 +19,13 @@ import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction
|
||||
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.Fir2IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbolInternals
|
||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
|
||||
class Fir2IrLazyDeclarationsGenerator(val components: Fir2IrComponents) : Fir2IrComponents by components {
|
||||
internal fun createIrLazyFunction(
|
||||
@@ -87,4 +90,18 @@ class Fir2IrLazyDeclarationsGenerator(val components: Fir2IrComponents) : Fir2Ir
|
||||
return irProperty
|
||||
}
|
||||
|
||||
fun createIrLazyClass(
|
||||
firClass: FirRegularClass,
|
||||
irParent: IrDeclarationParent,
|
||||
): IrClass = firClass.convertWithOffsets { startOffset, endOffset ->
|
||||
val firClassOrigin = firClass.irOrigin(session.firProvider)
|
||||
val signature = runIf(configuration.linkViaSignatures) {
|
||||
signatureComposer.composeSignature(firClass)
|
||||
}
|
||||
classifiersGenerator.declareIrClass(signature) { symbol ->
|
||||
Fir2IrLazyClass(components, startOffset, endOffset, firClassOrigin, firClass, symbol).apply {
|
||||
parent = irParent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,11 +191,7 @@ class Fir2IrLazyProperty(
|
||||
}.apply {
|
||||
parent = this@Fir2IrLazyProperty.parent
|
||||
correspondingPropertySymbol = this@Fir2IrLazyProperty.symbol
|
||||
with(classifierStorage) {
|
||||
setTypeParameters(
|
||||
this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.DEFAULT
|
||||
)
|
||||
}
|
||||
classifiersGenerator.setTypeParameters(this, this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.DEFAULT)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,11 +218,7 @@ class Fir2IrLazyProperty(
|
||||
).apply {
|
||||
parent = this@Fir2IrLazyProperty.parent
|
||||
correspondingPropertySymbol = this@Fir2IrLazyProperty.symbol
|
||||
with(classifierStorage) {
|
||||
setTypeParameters(
|
||||
this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.SETTER
|
||||
)
|
||||
}
|
||||
classifiersGenerator.setTypeParameters(this, this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.SETTER)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user