[Analysis API] Include files generated by `KaResolveExtension` directly in `KaModule.contentScope`

Before that change, `KaModule.contentScope` didn't have any support for such files.
The only provided support of generated files was contained in `KaBaseResolutionScope`.
Now every module that has at least one `KaResolveExtension` provided will contain a special `KaResolveExtensionGeneratedFilesScope` directly in its content scope.

^KT-74541 fixed
diff --git a/analysis/analysis-api-impl-base/resources/META-INF/analysis-api/analysis-api-impl-base.xml b/analysis/analysis-api-impl-base/resources/META-INF/analysis-api/analysis-api-impl-base.xml
index b8e1280..a1ff03a 100644
--- a/analysis/analysis-api-impl-base/resources/META-INF/analysis-api/analysis-api-impl-base.xml
+++ b/analysis/analysis-api-impl-base/resources/META-INF/analysis-api/analysis-api-impl-base.xml
@@ -93,5 +93,6 @@
 
   <extensions defaultExtensionNs="org.jetbrains.kotlin">
     <kotlinContentScopeRefiner implementation="org.jetbrains.kotlin.analysis.api.impl.base.projectStructure.KaResolveExtensionToContentScopeRefinerBridge"/>
+    <kotlinGlobalSearchScopeMergeStrategy implementation="org.jetbrains.kotlin.analysis.api.impl.base.projectStructure.KotlinResolveExtensionGeneratedFileScopeMergeStrategy"/>
   </extensions>
 </idea-plugin>
\ No newline at end of file
diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaBaseResolutionScope.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaBaseResolutionScope.kt
index b4c5802..41bd679 100644
--- a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaBaseResolutionScope.kt
+++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaBaseResolutionScope.kt
@@ -16,10 +16,6 @@
 import org.jetbrains.kotlin.psi.psiUtil.contains
 
 /**
- * [KaBaseResolutionScope] encapsulates special handling required for
- * generated and shadowed scopes provided by [org.jetbrains.kotlin.analysis.api.resolve.extensions.KaResolveExtensionProvider].
- * After KT-74541 is fixed, these scopes will be contained directly in [org.jetbrains.kotlin.analysis.api.projectStructure.KaModule.contentScope].
- *
  * [KaBaseResolutionScope] is not intended to be created manually,
  * it's a responsibility of [org.jetbrains.kotlin.analysis.api.platform.projectStructure.KaResolutionScopeProvider]
  * Please, use [Companion.forModule]
@@ -41,35 +37,36 @@
     }
 
     override fun contains(file: VirtualFile): Boolean {
-        return resolutionScope.contains(file) || isFromGeneratedModule(file)
+        return resolutionScope.contains(file) || isAccessibleDanglingFile(file)
     }
 
     override fun contains(element: PsiElement): Boolean {
-        return resolutionScope.contains(element) || isFromGeneratedModule(element)
+        return resolutionScope.contains(element) || isAccessibleDanglingFile(element)
     }
 
-    private fun isFromGeneratedModule(element: PsiElement): Boolean {
+    private fun isAccessibleDanglingFile(element: PsiElement): Boolean {
         val ktFile = element.containingFile as? KtFile ?: return false
-        if (ktFile.isDangling) {
-            val module = KaModuleProvider.getModule(useSiteModule.project, ktFile, useSiteModule)
-            return module.isAccessibleFromUseSiteModule()
+        if (!ktFile.isDangling) {
+            return false
         }
-
-        val virtualFile = ktFile.virtualFile ?: return false
-        return isFromGeneratedModule(virtualFile)
+        val module = ktFile.contextModule ?: KaModuleProvider.getModule(useSiteModule.project, ktFile, useSiteModule)
+        return module.isAccessibleFromUseSiteModule()
     }
 
-    /**
-     * To support files from [org.jetbrains.kotlin.analysis.api.resolve.extensions.KaResolveExtensionProvider]
-     * which are not dangling files
-     */
-    private fun isFromGeneratedModule(virtualFile: VirtualFile): Boolean {
-        val analysisContextModule = virtualFile.analysisContextModule ?: return false
-        return analysisContextModule.isAccessibleFromUseSiteModule()
+    private fun isAccessibleDanglingFile(virtualFile: VirtualFile): Boolean {
+        return virtualFile.analysisContextModule?.isAccessibleFromUseSiteModule() == true
     }
 
     private fun KaModule.isAccessibleFromUseSiteModule(): Boolean {
-        return this == useSiteModule || this in useSiteModule.allDirectDependencies()
+        return this in buildSet {
+            add(useSiteModule)
+            addAll(useSiteModule.directRegularDependencies)
+            addAll(useSiteModule.directFriendDependencies)
+            addAll(useSiteModule.transitiveDependsOnDependencies)
+            if (useSiteModule is KaLibrarySourceModule) {
+                add(useSiteModule.binaryLibrary)
+            }
+        }
     }
 
     override fun toString(): String {
diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaBaseResolveExtensionGeneratedFilesScope.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaBaseResolveExtensionGeneratedFilesScope.kt
new file mode 100644
index 0000000..af779c7
--- /dev/null
+++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaBaseResolveExtensionGeneratedFilesScope.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.analysis.api.impl.base.projectStructure
+
+import com.intellij.openapi.module.Module
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vfs.VirtualFile
+import org.jetbrains.kotlin.analysis.api.KaImplementationDetail
+import org.jetbrains.kotlin.analysis.api.platform.projectStructure.isGeneratedByResolveExtensions
+import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
+import org.jetbrains.kotlin.analysis.api.projectStructure.analysisContextModule
+
+@KaImplementationDetail
+class KaBaseResolveExtensionGeneratedFilesScope(val useSiteModules: List<KaModule>) : KaResolveExtensionGeneratedFilesScope() {
+    override fun isSearchInModuleContent(aModule: Module): Boolean = false
+
+    override fun isSearchInLibraries(): Boolean = false
+
+    override fun getProject(): Project? = useSiteModules.firstOrNull()?.project
+
+    override fun contains(file: VirtualFile): Boolean {
+        return file.isGeneratedByResolveExtensions == true && file.analysisContextModule in useSiteModules
+    }
+
+    override fun toString(): String {
+        return "Resolve Extensions Generated File Scope for [" + useSiteModules.joinToString(", ") { it.moduleDescription } + "]"
+    }
+}
\ No newline at end of file
diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaResolveExtensionGeneratedFilesScope.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaResolveExtensionGeneratedFilesScope.kt
new file mode 100644
index 0000000..7e42086
--- /dev/null
+++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaResolveExtensionGeneratedFilesScope.kt
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.analysis.api.impl.base.projectStructure
+
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.analysis.api.KaImplementationDetail
+
+/**
+ * Used to include files generated by [KaResolveExtension][org.jetbrains.kotlin.analysis.api.resolve.extensions.KaResolveExtension] in [org.jetbrains.kotlin.analysis.api.platform.projectStructure.KaResolutionScope].
+ */
+@KaImplementationDetail
+abstract class KaResolveExtensionGeneratedFilesScope : GlobalSearchScope()
\ No newline at end of file
diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaResolveExtensionToContentScopeRefinerBridge.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaResolveExtensionToContentScopeRefinerBridge.kt
index 61216ec..3a08876 100644
--- a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaResolveExtensionToContentScopeRefinerBridge.kt
+++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KaResolveExtensionToContentScopeRefinerBridge.kt
@@ -13,6 +13,13 @@
 
 @KaImplementationDetail
 class KaResolveExtensionToContentScopeRefinerBridge : KotlinContentScopeRefiner {
+    override fun getEnlargementScopes(module: KaModule): List<GlobalSearchScope> =
+        buildList {
+            if (KaResolveExtensionProvider.provideExtensionsFor(module).isNotEmpty()) {
+                add(KaBaseResolveExtensionGeneratedFilesScope(listOf(module)))
+            }
+        }
+
     override fun getRestrictionScopes(module: KaModule): List<GlobalSearchScope> =
         KaResolveExtensionProvider.provideExtensionsFor(module).map { resolveExtension ->
             GlobalSearchScope.notScope(resolveExtension.getShadowedScope())
diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KotlinResolveExtensionGeneratedFileScopeMergeStrategy.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KotlinResolveExtensionGeneratedFileScopeMergeStrategy.kt
new file mode 100644
index 0000000..f94afb5
--- /dev/null
+++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/projectStructure/KotlinResolveExtensionGeneratedFileScopeMergeStrategy.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.analysis.api.impl.base.projectStructure
+
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinGlobalSearchScopeMergeStrategy
+import kotlin.reflect.KClass
+
+class KotlinResolveExtensionGeneratedFileScopeMergeStrategy : KotlinGlobalSearchScopeMergeStrategy<KaBaseResolveExtensionGeneratedFilesScope> {
+    override val targetType: KClass<KaBaseResolveExtensionGeneratedFilesScope> = KaBaseResolveExtensionGeneratedFilesScope::class
+
+    override fun uniteScopes(scopes: List<KaBaseResolveExtensionGeneratedFilesScope>): List<GlobalSearchScope> {
+        val useSiteModules =
+            scopes.flatMap { scope ->
+                scope.useSiteModules
+            }
+        return listOf(KaBaseResolveExtensionGeneratedFilesScope(useSiteModules))
+    }
+}
\ No newline at end of file
diff --git a/analysis/analysis-api-platform-interface/src/org/jetbrains/kotlin/analysis/api/platform/projectStructure/utils.kt b/analysis/analysis-api-platform-interface/src/org/jetbrains/kotlin/analysis/api/platform/projectStructure/utils.kt
index 08888c2..b1e26d1 100644
--- a/analysis/analysis-api-platform-interface/src/org/jetbrains/kotlin/analysis/api/platform/projectStructure/utils.kt
+++ b/analysis/analysis-api-platform-interface/src/org/jetbrains/kotlin/analysis/api/platform/projectStructure/utils.kt
@@ -5,8 +5,13 @@
 
 package org.jetbrains.kotlin.analysis.api.platform.projectStructure
 
+import com.intellij.openapi.util.Key
+import com.intellij.openapi.vfs.VirtualFile
 import org.jetbrains.kotlin.analysis.api.KaExperimentalApi
+import org.jetbrains.kotlin.analysis.api.KaImplementationDetail
 import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
+import org.jetbrains.kotlin.analysis.api.projectStructure.analysisContextModule
+import org.jetbrains.kotlin.psi.UserDataProperty
 import org.jetbrains.kotlin.utils.topologicalSort
 
 /**
@@ -34,3 +39,13 @@
         }
         append("}")
     }.prependIndent("  ".repeat(indent))
+
+/**
+ * Used by the Analysis API engine
+ * to mark [VirtualFile] generated from [KaResolveExtension][org.jetbrains.kotlin.analysis.api.resolve.extensions.KaResolveExtension].
+ *
+ * This property is used to define whether [analysisContextModule] of a [VirtualFile]
+ * was set by [KaResolveExtensionProvider][org.jetbrains.kotlin.analysis.api.resolve.extensions.KaResolveExtensionProvider] or not.
+ */
+@KaImplementationDetail
+public var VirtualFile.isGeneratedByResolveExtensions: Boolean? by UserDataProperty(Key.create("IS_GENERATED_BY_RESOLVE_EXTENSIONS"))
diff --git a/analysis/analysis-api-standalone/analysis-api-fir-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/projectStructure/FirStandaloneServiceRegistrar.kt b/analysis/analysis-api-standalone/analysis-api-fir-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/projectStructure/FirStandaloneServiceRegistrar.kt
index 897a6a4..008cc3c 100644
--- a/analysis/analysis-api-standalone/analysis-api-fir-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/projectStructure/FirStandaloneServiceRegistrar.kt
+++ b/analysis/analysis-api-standalone/analysis-api-fir-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/projectStructure/FirStandaloneServiceRegistrar.kt
@@ -14,6 +14,8 @@
 import org.jetbrains.kotlin.analysis.api.KaImplementationDetail
 import org.jetbrains.kotlin.analysis.api.impl.base.projectStructure.KaResolveExtensionToContentScopeRefinerBridge
 import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinContentScopeRefiner
+import org.jetbrains.kotlin.analysis.api.impl.base.projectStructure.KotlinResolveExtensionGeneratedFileScopeMergeStrategy
+import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinGlobalSearchScopeMergeStrategy
 import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
 
 @OptIn(KaImplementationDetail::class)
@@ -44,5 +46,9 @@
         with(project.extensionArea.getExtensionPoint(KotlinContentScopeRefiner.EP_NAME)) {
             registerExtension(KaResolveExtensionToContentScopeRefinerBridge(), disposable)
         }
+
+        with(project.extensionArea.getExtensionPoint(KotlinGlobalSearchScopeMergeStrategy.EP_NAME)) {
+            registerExtension(KotlinResolveExtensionGeneratedFileScopeMergeStrategy(), disposable)
+        }
     }
 }
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLFirResolveExtensionTool.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLFirResolveExtensionTool.kt
index 17d274b..312778a 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLFirResolveExtensionTool.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLFirResolveExtensionTool.kt
@@ -19,6 +19,7 @@
 import org.jetbrains.kotlin.analysis.api.projectStructure.analysisContextModule
 import org.jetbrains.kotlin.analysis.api.platform.declarations.KotlinDeclarationProvider
 import org.jetbrains.kotlin.analysis.api.platform.packages.KotlinPackageProvider
+import org.jetbrains.kotlin.analysis.api.platform.projectStructure.isGeneratedByResolveExtensions
 import org.jetbrains.kotlin.fir.FirSession
 import org.jetbrains.kotlin.fir.FirSessionComponent
 import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolNamesProvider
@@ -301,6 +302,7 @@
         val ktFile = factory.createFile(fileName, fileText)
         val virtualFile = ktFile.virtualFile
         virtualFile.analysisContextModule = ktModule
+        virtualFile.isGeneratedByResolveExtensions = true
         virtualFile.navigationTargetsProvider = navigationTargetsProvider
         return ktFile
     }