diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt index bdf8325cd77..cc13f8163e7 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt @@ -185,13 +185,27 @@ abstract class AbstractFirDeserializedSymbolsProvider( return packagePartsCache.getValue(packageFqName) } + protected open fun shouldLoadParentsFirst(classId: ClassId): Boolean = false + protected open fun getClass( classId: ClassId, parentContext: FirDeserializationContext? = null ): FirRegularClassSymbol? { + if (parentContext == null && shouldLoadParentsFirst(classId)) { + return getClassAfterLoadingParents(classId) + } return classCache.getValue(classId, parentContext) } + private fun getClassAfterLoadingParents(classId: ClassId): FirRegularClassSymbol? { + classId.outerClassId?.let { parentClassId -> + val alreadyLoaded = classCache.getValueIfComputed(classId) + if (alreadyLoaded != null) return alreadyLoaded + getClassAfterLoadingParents(parentClassId) + } + return classCache.getValue(classId, null) + } + private fun getTypeAlias( classId: ClassId, ): FirTypeAliasSymbol? { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 77c6c16b8fc..4fc8005c420 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -22946,6 +22946,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/javaInterop/genericSamSmartcast.kt"); } + @Test + @TestMetadata("javaOuterClassDependsOnInner.kt") + public void testJavaOuterClassDependsOnInner() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/javaOuterClassDependsOnInner.kt"); + } + @Test @TestMetadata("kt43217.kt") public void testKt43217() throws Exception { diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt index 104f4c8b3c6..67f989c8344 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt @@ -93,6 +93,9 @@ open class KotlinDeserializedJvmSymbolsProvider( private val KotlinJvmBinaryClass.isPreReleaseInvisible: Boolean get() = classHeader.isPreRelease + override fun shouldLoadParentsFirst(classId: ClassId): Boolean = + javaSymbolProvider.hasTopLevelClassOf(classId) + override fun extractClassMetadata(classId: ClassId, parentContext: FirDeserializationContext?): ClassMetadataFindResult? { if (knownNameInPackageCache.hasNoTopLevelClassOf(classId)) return null val result = try { diff --git a/compiler/testData/codegen/box/javaInterop/javaOuterClassDependsOnInner.kt b/compiler/testData/codegen/box/javaInterop/javaOuterClassDependsOnInner.kt new file mode 100644 index 00000000000..faf21e8a66a --- /dev/null +++ b/compiler/testData/codegen/box/javaInterop/javaOuterClassDependsOnInner.kt @@ -0,0 +1,21 @@ +// TARGET_BACKEND: JVM +// This is really a frontend test that checks loading of compiled Java classes. +// MODULE: lib +// FILE: I.java +public interface I {} + +// FILE: J.java +public class J implements I { + public static class X {} +} + +// FILE: Z.java +public class Z { + public T foo(J.X x) { return null; } +} + +// MODULE: main(lib) +// FILE: main.kt +class C : Z() + +fun box() = C().foo(null) ?: "OK" diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 920ebf6fb39..013a2b0ba75 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -22814,6 +22814,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/javaInterop/genericSamSmartcast.kt"); } + @Test + @TestMetadata("javaOuterClassDependsOnInner.kt") + public void testJavaOuterClassDependsOnInner() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/javaOuterClassDependsOnInner.kt"); + } + @Test @TestMetadata("kt43217.kt") public void testKt43217() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 14c845e4a4f..22c763b7435 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -22946,6 +22946,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/javaInterop/genericSamSmartcast.kt"); } + @Test + @TestMetadata("javaOuterClassDependsOnInner.kt") + public void testJavaOuterClassDependsOnInner() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/javaOuterClassDependsOnInner.kt"); + } + @Test @TestMetadata("kt43217.kt") public void testKt43217() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index e0975ba0950..8d75631b794 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -19136,6 +19136,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/javaInterop/genericSamSmartcast.kt"); } + @TestMetadata("javaOuterClassDependsOnInner.kt") + public void testJavaOuterClassDependsOnInner() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/javaOuterClassDependsOnInner.kt"); + } + @TestMetadata("kt43217.kt") public void testKt43217() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/kt43217.kt"); diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt index 15c51304466..e885b0dc4a4 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper import org.jetbrains.kotlin.fir.caches.FirCachesFactory import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider -import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.java.JavaSymbolProviderWrapper @@ -32,7 +31,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirPhaseCheckingPhaseManage import org.jetbrains.kotlin.fir.symbols.FirPhaseManager import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider import org.jetbrains.kotlin.fir.session.* -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.idea.fir.low.level.api.* import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner import org.jetbrains.kotlin.idea.fir.low.level.api.IdeFirPhaseManager @@ -232,7 +230,7 @@ internal object FirIdeSessionFactory { /** * Workaround of SOE for loading classes that loads via parent. * It is not observable in compiler but it is in IDE - * Remove this when cyclic cache request will be fixed in the compiler provider + * TODO: this is probably already unnecessary */ private class KotlinDeserializedJvmSymbolsProviderForIde( session: FirSession, @@ -246,26 +244,7 @@ internal object FirIdeSessionFactory { session, moduleDataProvider, kotlinScopeProvider, packagePartProvider, kotlinClassFinder, javaClassFinder, javaSymbolProvider ) { - override fun getClass( - classId: ClassId, - parentContext: FirDeserializationContext? - ): FirRegularClassSymbol? { - if (parentContext !== null) { - return super.getClass(classId, parentContext) - } - val computedClass = classCache.getValueIfComputed(classId) - if (computedClass != null) { - return computedClass - } - - var parentClassId = classId - while (true) { - parentClassId = parentClassId.outerClassId ?: break - } - - classCache.getValue(parentClassId, parentContext) - return classCache.getValue(classId, parentContext) - } + override fun shouldLoadParentsFirst(classId: ClassId): Boolean = true } fun createBuiltinsAndCloneableSession(