[fir2ir] Generate facade stubs for external source declarations
In the IDE, it's impossible to pass classes from all modules to the backend, so symbols for 'external' source declarations need to be generated ad-hoc. Such declarations do not go through the lowering phase, including one that replaces the containing package fragment with a facade class.
This commit is contained in:
+95
-21
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.backend
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.builtins.StandardNames.BUILT_INS_PACKAGE_FQ_NAMES
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
|
||||
@@ -42,10 +43,7 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin.GeneratedByPlugin
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrScriptImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.SCRIPT_K2_ORIGIN
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind
|
||||
@@ -55,10 +53,15 @@ import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.load.kotlin.FacadeClassSource
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runUnless
|
||||
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
||||
import org.jetbrains.kotlin.utils.threadLocal
|
||||
@@ -294,23 +297,94 @@ class Fir2IrDeclarationStorage(
|
||||
firBasedSymbol: FirBasedSymbol<*>,
|
||||
firOrigin: FirDeclarationOrigin
|
||||
): IrDeclarationParent? {
|
||||
return if (parentLookupTag != null) {
|
||||
classifierStorage.findIrClass(parentLookupTag)
|
||||
} else {
|
||||
val containerFile = when (firBasedSymbol) {
|
||||
is FirCallableSymbol -> firProvider.getFirCallableContainerFile(firBasedSymbol)
|
||||
is FirClassLikeSymbol -> firProvider.getFirClassifierContainerFileIfAny(firBasedSymbol)
|
||||
else -> error("Unknown symbol: $firBasedSymbol")
|
||||
}
|
||||
if (parentLookupTag != null) {
|
||||
return classifierStorage.findIrClass(parentLookupTag)
|
||||
}
|
||||
|
||||
when {
|
||||
containerFile != null -> fileCache[containerFile]
|
||||
firBasedSymbol is FirCallableSymbol -> getIrExternalPackageFragment(packageFqName, firOrigin)
|
||||
val parentPackage = when (firBasedSymbol) {
|
||||
is FirCallableSymbol<*> -> {
|
||||
getIrExternalPackageFragment(packageFqName, firOrigin)
|
||||
}
|
||||
else -> {
|
||||
// TODO: All classes from BUILT_INS_PACKAGE_FQ_NAMES are considered built-ins now,
|
||||
// which is not exact and can lead to some problems
|
||||
else -> getIrExternalOrBuiltInsPackageFragment(packageFqName, firOrigin)
|
||||
getIrExternalOrBuiltInsPackageFragment(packageFqName, firOrigin)
|
||||
}
|
||||
}
|
||||
|
||||
val firProviderForSymbol = firBasedSymbol.moduleData.session.firProvider
|
||||
val containerFile = when (firBasedSymbol) {
|
||||
is FirCallableSymbol -> firProviderForSymbol.getFirCallableContainerFile(firBasedSymbol)
|
||||
is FirClassLikeSymbol -> firProviderForSymbol.getFirClassifierContainerFileIfAny(firBasedSymbol)
|
||||
else -> error("Unknown symbol: $firBasedSymbol")
|
||||
}
|
||||
|
||||
if (containerFile != null) {
|
||||
val existingFile = fileCache[containerFile]
|
||||
if (existingFile != null) {
|
||||
return existingFile
|
||||
}
|
||||
|
||||
// Sudden declarations do not go through IR lowering process,
|
||||
// so the parent file isn't replaced with a facade class, as in 'FileClassLowering'.
|
||||
if (configuration.allowNonCachedDeclarations && firBasedSymbol is FirCallableSymbol<*>) {
|
||||
val psiFile = containerFile.psi?.containingFile
|
||||
if (psiFile is KtFile) {
|
||||
val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(psiFile)
|
||||
val className = JvmClassName.byFqNameWithoutInnerClasses(fileClassInfo.fileClassFqName)
|
||||
|
||||
val facadeClassName: JvmClassName?
|
||||
val declarationOrigin: IrDeclarationOrigin
|
||||
|
||||
if (fileClassInfo.withJvmMultifileClass) {
|
||||
facadeClassName = JvmClassName.byFqNameWithoutInnerClasses(fileClassInfo.facadeClassFqName)
|
||||
declarationOrigin = IrDeclarationOrigin.JVM_MULTIFILE_CLASS
|
||||
} else {
|
||||
facadeClassName = null
|
||||
declarationOrigin = IrDeclarationOrigin.FILE_CLASS
|
||||
}
|
||||
|
||||
val facadeShortName = className.fqNameForClassNameWithoutDollars.shortName()
|
||||
val containerSource = NonCachedSourceFacadeContainerSource(className, facadeClassName)
|
||||
return NonCachedSourceFileFacadeClass(declarationOrigin, facadeShortName, containerSource).apply {
|
||||
parent = parentPackage
|
||||
createParameterDeclarations()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parentPackage
|
||||
}
|
||||
|
||||
private class NonCachedSourceFileFacadeClass(
|
||||
origin: IrDeclarationOrigin,
|
||||
name: Name,
|
||||
source: SourceElement,
|
||||
) : IrClassImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, IrClassSymbolImpl(), name,
|
||||
ClassKind.CLASS, DescriptorVisibilities.PUBLIC, Modality.FINAL,
|
||||
source = source
|
||||
)
|
||||
|
||||
private class NonCachedSourceFacadeContainerSource(
|
||||
override val className: JvmClassName,
|
||||
override val facadeClassName: JvmClassName?
|
||||
) : DeserializedContainerSource, FacadeClassSource {
|
||||
override val incompatibility get() = null
|
||||
override val isPreReleaseInvisible get() = false
|
||||
override val abiStability get() = DeserializedContainerAbiStability.STABLE
|
||||
override val presentableString get() = className.internalName
|
||||
|
||||
override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE
|
||||
}
|
||||
|
||||
private fun computeThisReceiverOwner(parent: IrDeclarationParent?): IrClass? {
|
||||
if (parent is IrClass && parent !is NonCachedSourceFileFacadeClass) {
|
||||
return parent
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
internal fun findIrParent(callableDeclaration: FirCallableDeclaration): IrDeclarationParent? {
|
||||
@@ -462,7 +536,7 @@ class Fir2IrDeclarationStorage(
|
||||
private fun <T : IrFunction> T.bindAndDeclareParameters(
|
||||
function: FirFunction?,
|
||||
irParent: IrDeclarationParent?,
|
||||
thisReceiverOwner: IrClass? = irParent as? IrClass,
|
||||
thisReceiverOwner: IrClass?,
|
||||
isStatic: Boolean,
|
||||
forSetter: Boolean,
|
||||
parentPropertyReceiver: FirReceiverParameter? = null
|
||||
@@ -540,7 +614,7 @@ class Fir2IrDeclarationStorage(
|
||||
fun createIrFunction(
|
||||
function: FirFunction,
|
||||
irParent: IrDeclarationParent?,
|
||||
thisReceiverOwner: IrClass? = irParent as? IrClass,
|
||||
thisReceiverOwner: IrClass? = computeThisReceiverOwner(irParent),
|
||||
predefinedOrigin: IrDeclarationOrigin? = null,
|
||||
isLocal: Boolean = false,
|
||||
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
|
||||
@@ -707,7 +781,7 @@ class Fir2IrDeclarationStorage(
|
||||
// with the annotation itself.
|
||||
constructorCache[constructor] = this
|
||||
enterScope(this)
|
||||
bindAndDeclareParameters(constructor, irParent, isStatic = false, forSetter = false)
|
||||
bindAndDeclareParameters(constructor, irParent, irParent, isStatic = false, forSetter = false)
|
||||
leaveScope(this)
|
||||
}
|
||||
}
|
||||
@@ -739,7 +813,7 @@ class Fir2IrDeclarationStorage(
|
||||
correspondingProperty: IrDeclarationWithName,
|
||||
propertyType: IrType,
|
||||
irParent: IrDeclarationParent?,
|
||||
thisReceiverOwner: IrClass? = irParent as? IrClass,
|
||||
thisReceiverOwner: IrClass? = computeThisReceiverOwner(irParent),
|
||||
isSetter: Boolean,
|
||||
origin: IrDeclarationOrigin,
|
||||
startOffset: Int,
|
||||
@@ -924,7 +998,7 @@ class Fir2IrDeclarationStorage(
|
||||
fun createIrProperty(
|
||||
property: FirProperty,
|
||||
irParent: IrDeclarationParent?,
|
||||
thisReceiverOwner: IrClass? = irParent as? IrClass,
|
||||
thisReceiverOwner: IrClass? = computeThisReceiverOwner(irParent),
|
||||
predefinedOrigin: IrDeclarationOrigin? = null,
|
||||
isLocal: Boolean = false,
|
||||
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = (irParent as? IrClass)?.classId?.toLookupTag(),
|
||||
|
||||
Reference in New Issue
Block a user