diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 3fe0dcce027..43586b15196 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -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.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(),