[FIR] make FirJavaClass.superTypes to be lazily enhanced

This should solve the problem with deadlocks/performance in the K2 IDE

This is a temporary solution until the ^KT-55387 is properly fixed

^KT-55387
^KT-54890
diff --git a/.idea/dictionaries/darthorimar.xml b/.idea/dictionaries/darthorimar.xml
new file mode 100644
index 0000000..1cfd3d9
--- /dev/null
+++ b/.idea/dictionaries/darthorimar.xml
@@ -0,0 +1,7 @@
+<component name="ProjectDictionaryState">
+  <dictionary name="darthorimar">
+    <words>
+      <w>unenhnanced</w>
+    </words>
+  </dictionary>
+</component>
\ No newline at end of file
diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt
index ff2ebaf..cf0026e 100644
--- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt
+++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt
@@ -12,7 +12,6 @@
 import org.jetbrains.kotlin.descriptors.Modality
 import org.jetbrains.kotlin.descriptors.Visibilities
 import org.jetbrains.kotlin.fir.*
-import org.jetbrains.kotlin.fir.analysis.checkers.typeParameterSymbols
 import org.jetbrains.kotlin.fir.caches.createCache
 import org.jetbrains.kotlin.fir.caches.firCachesFactory
 import org.jetbrains.kotlin.fir.caches.getValue
@@ -24,21 +23,15 @@
 import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
 import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
 import org.jetbrains.kotlin.fir.declarations.utils.modality
-import org.jetbrains.kotlin.fir.expressions.FirConstExpression
-import org.jetbrains.kotlin.fir.expressions.classId
 import org.jetbrains.kotlin.fir.java.declarations.*
 import org.jetbrains.kotlin.fir.java.enhancement.FirSignatureEnhancement
 import org.jetbrains.kotlin.fir.resolve.constructType
 import org.jetbrains.kotlin.fir.resolve.defaultType
-import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
-import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
 import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
 import org.jetbrains.kotlin.fir.symbols.impl.*
 import org.jetbrains.kotlin.fir.types.*
 import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
-import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
 import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
-import org.jetbrains.kotlin.load.java.FakePureImplementationsProvider
 import org.jetbrains.kotlin.load.java.JavaClassFinder
 import org.jetbrains.kotlin.load.java.JvmAnnotationNames
 import org.jetbrains.kotlin.load.java.structure.*
@@ -181,57 +174,13 @@
 
         // 1. Resolve annotations
         // 2. Enhance type parameter bounds - may refer to each other, take default nullability from annotations
-        // 3. Enhance super types - may refer to type parameter bounds, take default nullability from annotations
+        // 3. (will happen lazily in FirJavaClass.superTypeRefs) Enhance super types - may refer to type parameter bounds, take default nullability from annotations
+
         firJavaClass.setAnnotationsFromJava(session, javaClass, javaTypeParameterStack)
-
         enhancement.enhanceTypeParameterBoundsAfterFirstRound(firJavaClass.typeParameters, initialBounds)
-
-        val enhancedSuperTypes = buildList {
-            val purelyImplementedSupertype = firJavaClass.getPurelyImplementedSupertype()
-            val purelyImplementedSupertypeClassId = purelyImplementedSupertype?.classId
-            firJavaClass.superTypeRefs.mapNotNullTo(this) { superType ->
-                enhancement.enhanceSuperType(superType).takeUnless {
-                    purelyImplementedSupertypeClassId != null && it.coneType.classId == purelyImplementedSupertypeClassId
-                }
-            }
-            purelyImplementedSupertype?.let {
-                add(buildResolvedTypeRef { type = it })
-            }
-        }
-        firJavaClass.replaceSuperTypeRefs(enhancedSuperTypes)
         firJavaClass.replaceDeprecationsProvider(firJavaClass.getDeprecationsProvider(session.firCachesFactory))
-        return firJavaClass
-    }
 
-    private fun FirJavaClass.getPurelyImplementedSupertype(): ConeKotlinType? {
-        val purelyImplementedClassIdFromAnnotation = annotations
-            .firstOrNull { it.classId?.asSingleFqName() == JvmAnnotationNames.PURELY_IMPLEMENTS_ANNOTATION }
-            ?.let { (it.argumentMapping.mapping.values.firstOrNull() as? FirConstExpression<*>) }
-            ?.let { it.value as? String }
-            ?.takeIf { it.isNotBlank() && isValidJavaFqName(it) }
-            ?.let { ClassId.topLevel(FqName(it)) }
-        val purelyImplementedClassId = purelyImplementedClassIdFromAnnotation
-            ?: FakePureImplementationsProvider.getPurelyImplementedInterface(symbol.classId)
-            ?: return null
-        val superTypeSymbol = session.symbolProvider.getClassLikeSymbolByClassId(purelyImplementedClassId) ?: return null
-        val superTypeParameterSymbols = superTypeSymbol.typeParameterSymbols ?: return null
-        val typeParameters = this.typeParameters
-        val supertypeParameterCount = superTypeParameterSymbols.size
-        val typeParameterCount = typeParameters.size
-        val parametersAsTypeProjections = when {
-            typeParameterCount == supertypeParameterCount ->
-                typeParameters.map { ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(it.symbol), isNullable = false) }
-            typeParameterCount == 1 && supertypeParameterCount > 1 && purelyImplementedClassIdFromAnnotation == null -> {
-                val projection = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(typeParameters.first().symbol), isNullable = false)
-                (1..supertypeParameterCount).map { projection }
-            }
-            else -> return null
-        }
-        return ConeClassLikeTypeImpl(
-            ConeClassLikeLookupTagImpl(purelyImplementedClassId),
-            parametersAsTypeProjections.toTypedArray(),
-            isNullable = false
-        )
+        return firJavaClass
     }
 
     private fun createFirJavaClass(
diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt
index ca3cfb8..baa08ca 100644
--- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt
+++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt
@@ -19,6 +19,7 @@
 import org.jetbrains.kotlin.fir.declarations.builder.FirRegularClassBuilder
 import org.jetbrains.kotlin.fir.expressions.FirAnnotation
 import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
+import org.jetbrains.kotlin.fir.java.enhancement.FirSignatureEnhancement
 import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
 import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
 import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
@@ -44,7 +45,7 @@
     override val declarations: MutableList<FirDeclaration>,
     override val scopeProvider: FirScopeProvider,
     override val symbol: FirRegularClassSymbol,
-    override val superTypeRefs: MutableList<FirTypeRef>,
+    private val unenhnancedSuperTypes: List<FirTypeRef>,
     override val typeParameters: MutableList<FirTypeParameterRef>,
     internal val javaPackage: JavaPackage?,
     val javaTypeParameterStack: JavaTypeParameterStack,
@@ -63,9 +64,14 @@
 
     override val attributes: FirDeclarationAttributes = FirDeclarationAttributes()
 
+    // TODO: the lazy superTypeRefs is a workaround for KT-55387, some non-lazy solution should probably be used instead
+    override val superTypeRefs: List<FirTypeRef> by lazy {
+        val enhancement = FirSignatureEnhancement(this@FirJavaClass, moduleData.session, overridden = { emptyList() })
+        enhancement.enhanceSuperTypes(unenhnancedSuperTypes)
+    }
+
     override fun replaceSuperTypeRefs(newSuperTypeRefs: List<FirTypeRef>) {
-        superTypeRefs.clear()
-        superTypeRefs.addAll(newSuperTypeRefs)
+        error("${::replaceSuperTypeRefs.name} should not be called for ${this::class.simpleName}, ${superTypeRefs::class.simpleName} is lazily calulated")
     }
 
     override fun replaceResolvePhase(newResolvePhase: FirResolvePhase) {
@@ -101,7 +107,6 @@
     }
 
     override fun <D> transformSuperTypeRefs(transformer: FirTransformer<D>, data: D): FirRegularClass {
-        superTypeRefs.transformInplace(transformer, data)
         return this
     }
 
@@ -152,6 +157,7 @@
 
     @OptIn(FirImplementationDetail::class)
     override fun build(): FirJavaClass {
+        @Suppress("UNCHECKED_CAST")
         return FirJavaClass(
             source,
             moduleData,
diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt
index a9e95f8..6860e62 100644
--- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt
+++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt
@@ -10,6 +10,7 @@
 import org.jetbrains.kotlin.descriptors.Modality
 import org.jetbrains.kotlin.fakeElement
 import org.jetbrains.kotlin.fir.*
+import org.jetbrains.kotlin.fir.analysis.checkers.typeParameterSymbols
 import org.jetbrains.kotlin.fir.caches.FirCache
 import org.jetbrains.kotlin.fir.caches.FirCachesFactory
 import org.jetbrains.kotlin.fir.caches.createCache
@@ -25,26 +26,31 @@
 import org.jetbrains.kotlin.fir.declarations.utils.modality
 import org.jetbrains.kotlin.fir.declarations.utils.visibility
 import org.jetbrains.kotlin.fir.expressions.FirAnnotation
+import org.jetbrains.kotlin.fir.expressions.FirConstExpression
+import org.jetbrains.kotlin.fir.expressions.classId
 import org.jetbrains.kotlin.fir.java.FirJavaTypeConversionMode
 import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
 import org.jetbrains.kotlin.fir.java.declarations.*
 import org.jetbrains.kotlin.fir.java.resolveIfJavaType
 import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol
 import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible
+import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
 import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor
 import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
 import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
 import org.jetbrains.kotlin.fir.symbols.impl.*
 import org.jetbrains.kotlin.fir.types.*
 import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
+import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
+import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
 import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
 import org.jetbrains.kotlin.load.java.AnnotationQualifierApplicabilityType
+import org.jetbrains.kotlin.load.java.FakePureImplementationsProvider
 import org.jetbrains.kotlin.load.java.JavaTypeQualifiersByElementType
+import org.jetbrains.kotlin.load.java.JvmAnnotationNames
 import org.jetbrains.kotlin.load.java.typeEnhancement.*
 import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
-import org.jetbrains.kotlin.name.CallableId
-import org.jetbrains.kotlin.name.FqNameUnsafe
-import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.name.*
 import org.jetbrains.kotlin.types.AbstractTypeChecker
 import org.jetbrains.kotlin.types.model.KotlinTypeMarker
 import org.jetbrains.kotlin.types.model.TypeParameterMarker
@@ -442,7 +448,55 @@
             AnnotationQualifierApplicabilityType.TYPE_PARAMETER_BOUNDS, contextQualifiers
         ).enhance(bound, emptyList(), FirJavaTypeConversionMode.TYPE_PARAMETER_BOUND_AFTER_FIRST_ROUND)
 
-    fun enhanceSuperType(type: FirTypeRef): FirTypeRef =
+
+    fun enhanceSuperTypes(unenhnancedSuperTypes: List<FirTypeRef>): List<FirTypeRef> {
+        val purelyImplementedSupertype = getPurelyImplementedSupertype(moduleData.session)
+        val purelyImplementedSupertypeClassId = purelyImplementedSupertype?.classId
+        return buildList {
+            unenhnancedSuperTypes.mapNotNullTo(this) { superType ->
+                enhanceSuperType(superType).takeUnless {
+                    purelyImplementedSupertypeClassId != null && it.coneType.classId == purelyImplementedSupertypeClassId
+                }
+            }
+            purelyImplementedSupertype?.let {
+                add(buildResolvedTypeRef { type = it })
+            }
+        }
+    }
+
+    private fun getPurelyImplementedSupertype(session: FirSession): ConeKotlinType? {
+        val purelyImplementedClassIdFromAnnotation = owner.annotations
+            .firstOrNull { it.classId?.asSingleFqName() == JvmAnnotationNames.PURELY_IMPLEMENTS_ANNOTATION }
+            ?.let { (it.argumentMapping.mapping.values.firstOrNull() as? FirConstExpression<*>) }
+            ?.let { it.value as? String }
+            ?.takeIf { it.isNotBlank() && isValidJavaFqName(it) }
+            ?.let { ClassId.topLevel(FqName(it)) }
+        val purelyImplementedClassId = purelyImplementedClassIdFromAnnotation
+            ?: FakePureImplementationsProvider.getPurelyImplementedInterface(owner.symbol.classId)
+            ?: return null
+        val superTypeSymbol = session.symbolProvider.getClassLikeSymbolByClassId(purelyImplementedClassId) ?: return null
+        val superTypeParameterSymbols = superTypeSymbol.typeParameterSymbols ?: return null
+        val typeParameters = owner.typeParameters
+        val supertypeParameterCount = superTypeParameterSymbols.size
+        val typeParameterCount = typeParameters.size
+        val parametersAsTypeProjections = when {
+            typeParameterCount == supertypeParameterCount ->
+                typeParameters.map { ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(it.symbol), isNullable = false) }
+            typeParameterCount == 1 && supertypeParameterCount > 1 && purelyImplementedClassIdFromAnnotation == null -> {
+                val projection = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(typeParameters.first().symbol), isNullable = false)
+                (1..supertypeParameterCount).map { projection }
+            }
+            else -> return null
+        }
+        return ConeClassLikeTypeImpl(
+            ConeClassLikeLookupTagImpl(purelyImplementedClassId),
+            parametersAsTypeProjections.toTypedArray(),
+            isNullable = false
+        )
+    }
+
+
+        private fun enhanceSuperType(type: FirTypeRef): FirTypeRef =
         EnhancementSignatureParts(
             session, typeQualifierResolver, null, isCovariant = false, forceOnlyHeadTypeConstructor = false,
             AnnotationQualifierApplicabilityType.TYPE_USE, contextQualifiers
diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/kt47459.kt b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/kt47459.kt
index 0b2ce15..f31435a 100644
--- a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/kt47459.kt
+++ b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/kt47459.kt
@@ -1,4 +1,3 @@
-// FIR_DISABLE_LAZY_RESOLVE_CHECKS
 // FIR_IDENTICAL
 // FILE: MapObjectManager.java
 abstract class MapObjectManager<C extends MapObjectManager.Collection> {
diff --git a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt
index 2afe731..b5f72f9 100644
--- a/compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt
+++ b/compiler/testData/diagnostics/tests/platformTypes/rawTypes/smartCastToClassWithRawSupertype.kt
@@ -1,4 +1,3 @@
-// FIR_DISABLE_LAZY_RESOLVE_CHECKS
 // FIR_IDENTICAL
 // SKIP_TXT
 // !DIAGNOSTICS: -UNUSED_VARIABLE