tmp
diff --git a/compiler/build-tools/kotlin-build-tools-api-tests/src/testCrossModuleIncrementalChanges/kotlin/InlinedLambdaChangeTest.kt b/compiler/build-tools/kotlin-build-tools-api-tests/src/testCrossModuleIncrementalChanges/kotlin/InlinedLambdaChangeTest.kt
index f480725..e489be7 100644
--- a/compiler/build-tools/kotlin-build-tools-api-tests/src/testCrossModuleIncrementalChanges/kotlin/InlinedLambdaChangeTest.kt
+++ b/compiler/build-tools/kotlin-build-tools-api-tests/src/testCrossModuleIncrementalChanges/kotlin/InlinedLambdaChangeTest.kt
@@ -13,7 +13,6 @@
 import org.jetbrains.kotlin.buildtools.api.tests.compilation.util.execute
 import org.jetbrains.kotlin.buildtools.api.tests.compilation.util.moduleWithInlineSnapshotting
 import org.jetbrains.kotlin.test.TestMetadata
-import org.junit.jupiter.api.Disabled
 import org.junit.jupiter.api.DisplayName
 
 
diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/impl/BasicClassInfo.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/impl/BasicClassInfo.kt
index d3cdc61..103ca3a 100644
--- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/impl/BasicClassInfo.kt
+++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/impl/BasicClassInfo.kt
@@ -24,7 +24,8 @@
     val supertypes: List<JvmClassName>,
 
     private val accessFlags: Int,
-    val isAnonymous: Boolean
+    val isAnonymous: Boolean,
+    val outerClassWithMethodName: String?, // per ASM documentation, null if this is not a proper local or anonymous class
 ) {
     val isKotlinClass = kotlinClassHeader != null
     val isPrivate = flagEnabled(accessFlags, Opcodes.ACC_PRIVATE)
@@ -60,12 +61,14 @@
                 kotlinClassHeader = kotlinClassHeaderClassVisitor.getKotlinClassHeader(),
                 supertypes = basicClassInfoVisitor.getSupertypes(),
                 accessFlags = basicClassInfoVisitor.getAccessFlags(),
-                isAnonymous = innerClassesInfo[className]?.let { it.innerSimpleName == null } ?: false
+                isAnonymous = innerClassesInfo[className]?.let { it.innerSimpleName == null } == true,
+                outerClassWithMethodName = outerClassClassVisitor.getOuterClassWithMethod(),
             )
         }
     }
 }
 
+//TODO: I don't like how it looks, why not merge all classvisitors into a single one? thoughts?
 private class BasicClassInfoClassVisitor(cv: ClassVisitor) : ClassVisitor(Opcodes.API_VERSION, cv) {
     private var className: String? = null
     private var classAccess: Int? = null
@@ -96,12 +99,26 @@
     fun getInnerClassesInfo(): InnerClassesInfo = innerClassesInfo
 }
 
+/**
+ * Example inputs with just two layers of local classes:
+ *
+ * com/example/ictest/InlinedLocalClassKt calculate ()I
+ * com/example/ictest/InlinedLocalClassKt$calculate$outer$1 invoke ()Ljava/lang/Integer;
+ *
+ * If the [calc] at the end of OneClass$InnerClass$AnotherInnerClass$calc is actually an inline fun,
+ * we'd want to include into its abi snapshot every local class whose "outer class with method"
+ * has a prefix of "com/example/ictest/OneClass$InnerClass$AnotherInnerClass$calc"
+ */
 private class OuterClassClassVisitor(cv: ClassVisitor) : ClassVisitor(Opcodes.API_VERSION, cv) {
+    private var outerClassWithMethod: String? = null
 
     override fun visitOuterClass(owner: String?, name: String?, descriptor: String?) {
-        println("yo $owner $name $descriptor")
+        println("yo $owner $name")
+        outerClassWithMethod = owner?.let { owner -> name?.let { name -> "$owner\$$name" }}
         super.visitOuterClass(owner, name, descriptor)
     }
+
+    fun getOuterClassWithMethod(): String? = outerClassWithMethod
 }
 
 private class KotlinClassHeaderClassVisitor : ClassVisitor(Opcodes.API_VERSION) {
diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/impl/ClassListSnapshotter.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/impl/ClassListSnapshotter.kt
index d513708..7311a4b 100644
--- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/impl/ClassListSnapshotter.kt
+++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/impl/ClassListSnapshotter.kt
@@ -144,14 +144,24 @@
      */
 
     override fun snapshot(): List<ClassSnapshot> {
-        // expected order:
-        // InlinedLocalClassKt$calculate$foo$1, InlinedLocalClassKt$calculate$bar$1, InlinedLocalClassKt
-        // this allows us to visit inner classes before the outer class
-        val sortedClasses = classes.sortedByDescending { it.classFile.getClassName().internalName }
-        println(sortedClasses.map {it.classFile.getClassName().internalName}.joinToString(", "))
+        // Very fair assumption: it's not possible to define a top-level class inside an inline function
+        // Fair assumption #2: class names can be obfuscated,
 
-        val (inner, outer) = classes.partition { it.classFile.getClassName().internalName.contains("$") }
-        val innerSorted = inner.sortedBy { it.classFile.getClassName().internalName }
+        //TODO - critical - look at r8ed classfiles
+
+        val nonTopLevelClasses = classes.filter { it.classFile.getClassName().internalName.contains("$") }
+        //val innerSorted = inner.sortedBy { it.classFile.getClassName().internalName }
+
+        /**
+         * We assume that inner classes are relatively light-weight, so it is not a problem to load them twice.
+         * A possible optimization is adding a cache with soft references so we'd utilize the available RAM efficiently?
+         */
+
+        for (innerClass in inner) {
+            //TODO add test case - inline fun in a local class
+            //disgusting
+            makeOrReuseClassSnapshot(innerClass)
+        }
 
         for (outerClass in outer) {
             // outer class snapshotting might find accessible inline functons ->
diff --git a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfoTest.kt b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfoTest.kt
index fa02dd3..c9bb074 100644
--- a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfoTest.kt
+++ b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfoTest.kt
@@ -24,7 +24,9 @@
     @Test
     fun `compute BasicClassInfo`() {
         val compiledClasses = compileJava(className, sourceCode)
-        val classIds = compiledClasses.map { BasicClassInfo.compute(it).classId }
+        val basicInfos = compiledClasses.map { BasicClassInfo.compute(it) }
+        val classIds = basicInfos.map { it.classId }
+        val containingMethods = basicInfos.map { it.outerClassWithMethodName }
 
         assertEquals(
             listOf(
@@ -43,6 +45,21 @@
             ),
             classIds
         )
+
+        // [classId]'s definition of "local" is wider than JVM definition of local, so we don't visitOuterClass for every class
+        // with expected "local = true" state from above
+        assertEquals(
+            listOf(
+                null,
+                "com/example/TopLevelClass\$methodWithinTopLevelClass",
+                "com/example/TopLevelClass\$methodWithinTopLevelClass",
+                "com/example/TopLevelClass\$1LocalClass\$methodWithinLocalClass",
+                null, null, null,
+                "com/example/TopLevelClass\$InnerClass\$someMethod",
+                null, null, null, null,
+            ),
+            containingMethods
+        )
     }
 
     @Suppress("SameParameterValue")