AA: add analyzeWithKtModule API for analyzing without KtElement
diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10CliAnalysisSessionProvider.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10CliAnalysisSessionProvider.kt
index 1eec54a..9009fde 100644
--- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10CliAnalysisSessionProvider.kt
+++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10CliAnalysisSessionProvider.kt
@@ -11,6 +11,7 @@
 import org.jetbrains.kotlin.analysis.api.descriptors.symbols.base.KtFe10Symbol
 import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
 import org.jetbrains.kotlin.analysis.api.tokens.ValidityTokenFactory
+import org.jetbrains.kotlin.analysis.project.structure.KtModule
 import org.jetbrains.kotlin.analysis.project.structure.getKtModule
 import org.jetbrains.kotlin.psi.KtElement
 import java.lang.UnsupportedOperationException
@@ -36,5 +37,9 @@
         throw UnsupportedOperationException("getAnalysisSessionBySymbol() should not be used on KtFe10AnalysisSession")
     }
 
+    override fun getAnalysisSessionByModule(ktModule: KtModule, factory: ValidityTokenFactory): KtAnalysisSession {
+        throw UnsupportedOperationException("getAnalysisSessionByModule() should not be used on KtFe10AnalysisSession")
+    }
+
     override fun clearCaches() {}
 }
\ No newline at end of file
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtFirAnalysisSessionProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtFirAnalysisSessionProvider.kt
index 1d34492..1098fe1 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtFirAnalysisSessionProvider.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtFirAnalysisSessionProvider.kt
@@ -14,6 +14,7 @@
 import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
 import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
 import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession
+import org.jetbrains.kotlin.analysis.project.structure.KtModule
 import org.jetbrains.kotlin.psi.KtElement
 
 @OptIn(InvalidWayOfUsingAnalysisSession::class)
@@ -29,6 +30,11 @@
         }
     }
 
+    override fun getFirResolveSession(contextModule: KtModule): LLFirResolveSession {
+        checkNotNull(contextModule.project)
+        return contextModule.getFirResolveSession(contextModule.project!!)
+    }
+
     override fun createAnalysisSession(
         firResolveSession: LLFirResolveSession,
         validityToken: ValidityToken,
diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/CachingKtAnalysisSessionProvider.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/CachingKtAnalysisSessionProvider.kt
index 99867cf..d12f624 100644
--- a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/CachingKtAnalysisSessionProvider.kt
+++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/CachingKtAnalysisSessionProvider.kt
@@ -19,6 +19,7 @@
 import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
 import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
 import org.jetbrains.kotlin.analysis.api.tokens.ValidityTokenFactory
+import org.jetbrains.kotlin.analysis.project.structure.KtModule
 import org.jetbrains.kotlin.psi.KtElement
 import java.util.concurrent.ConcurrentHashMap
 import kotlin.reflect.KClass
@@ -30,6 +31,8 @@
     protected abstract fun getFirResolveSession(contextElement: KtElement): State
     protected abstract fun getFirResolveSession(contextSymbol: KtSymbol): State
 
+    protected abstract fun getFirResolveSession(contextModule: KtModule): State
+
     protected abstract fun createAnalysisSession(
         firResolveSession: State,
         validityToken: ValidityToken,
@@ -44,6 +47,14 @@
         }
     }
 
+    final override fun getAnalysisSessionByModule(ktModule: KtModule, factory: ValidityTokenFactory): KtAnalysisSession {
+        val firResolveSession = getFirResolveSession(ktModule)
+        return cache.getAnalysisSession(firResolveSession to factory.identifier) {
+            val validityToken = factory.create(project)
+            createAnalysisSession(firResolveSession, validityToken)
+        }
+    }
+
     final override fun getAnalysisSessionBySymbol(contextSymbol: KtSymbol): KtAnalysisSession {
         val firResolveSession = getFirResolveSession(contextSymbol)
         val token = contextSymbol.token
diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/KtAnalysisSessionProvider.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/KtAnalysisSessionProvider.kt
index 28791a0..c35c564 100644
--- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/KtAnalysisSessionProvider.kt
+++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/KtAnalysisSessionProvider.kt
@@ -17,6 +17,7 @@
 import org.jetbrains.kotlin.analysis.api.tokens.AlwaysAccessibleValidityTokenFactory
 import org.jetbrains.kotlin.analysis.api.tokens.ReadActionConfinementValidityTokenFactory
 import org.jetbrains.kotlin.analysis.api.tokens.ValidityTokenFactory
+import org.jetbrains.kotlin.analysis.project.structure.KtModule
 import org.jetbrains.kotlin.psi.KtElement
 import org.jetbrains.kotlin.psi.KtFile
 
@@ -43,6 +44,9 @@
     public abstract fun getAnalysisSessionBySymbol(contextSymbol: KtSymbol): KtAnalysisSession
 
     @InvalidWayOfUsingAnalysisSession
+    public abstract fun getAnalysisSessionByModule(ktModule: KtModule, factory: ValidityTokenFactory): KtAnalysisSession
+
+    @InvalidWayOfUsingAnalysisSession
     public inline fun <R> analyzeWithSymbolAsContext(
         contextSymbol: KtSymbol,
         action: KtAnalysisSession.() -> R
@@ -173,3 +177,14 @@
     task.queue()
     return task.result
 }
+
+@OptIn(InvalidWayOfUsingAnalysisSession::class)
+public inline fun <R> analyzeWithKtModule(
+    ktModule: KtModule,
+    tokenFactory: ValidityTokenFactory,
+    crossinline action: KtAnalysisSession.() -> R
+): R {
+    checkNotNull(ktModule.project)
+    val sessionProvider = KtAnalysisSessionProvider.getInstance(ktModule.project!!)
+    return sessionProvider.getAnalysisSessionByModule(ktModule, tokenFactory).action()
+}
\ No newline at end of file