[Analysis API] Add source shadowing for resolve extensions.
KtResolveExtensions are designed to handle IDE analysis use cases where
source might not be available at analysis time, because that source is
generated by an external source generator, such as an annotation
processor or resource compiler. The sources generated by those external
generators can appear in the analysis scope, and cause issues with
source clash - resolution may find the virtual source from the
KtResolveExtension, the on-disk generated source from the external
generator, or both. This can cause issues, because that on-disk
generated source may be stale, and may not have symbols that will exist
the next time the generator is run (or, conversely, may have symbols
that will disappear on the next build).
To solve this, add a `getShadowedScope(): GlobalSearchScope` to
`KtResolveExtension`. Any files in the module that are included in that
scope will be hidden from resolution, allowing the resolve extension to
cleanly replace those files.
^KT-58834 fixed
diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10AnalysisSession.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10AnalysisSession.kt
index 1054002..902a0b4 100644
--- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10AnalysisSession.kt
+++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10AnalysisSession.kt
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.api.descriptors
import com.intellij.openapi.project.Project
+import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.components.*
@@ -61,7 +62,8 @@
override val importOptimizerImpl: KtImportOptimizer = KtFe10ImportOptimizer(this)
override val jvmTypeMapperImpl: KtJvmTypeMapper = KtFe10JvmTypeMapper(this)
override val symbolInfoProviderImpl: KtSymbolInfoProvider = KtFe10SymbolInfoProvider(this)
- override val analysisScopeProviderImpl: KtAnalysisScopeProvider = KtAnalysisScopeProviderImpl(this, token)
+ override val analysisScopeProviderImpl: KtAnalysisScopeProvider =
+ KtAnalysisScopeProviderImpl(this, token, shadowedScope = GlobalSearchScope.EMPTY_SCOPE)
override val referenceResolveProviderImpl: KtReferenceResolveProvider = KtFe10ReferenceResolveProvider(this)
override val signatureSubstitutorImpl: KtSignatureSubstitutor = KtFe10SignatureSubstitutor(this)
override val scopeSubstitutionImpl: KtScopeSubstitution = KtFe10ScopeSubstitution(this)
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtFirAnalysisSession.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtFirAnalysisSession.kt
index 4704c7b..9dcf00c 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtFirAnalysisSession.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtFirAnalysisSession.kt
@@ -114,7 +114,7 @@
override val typesCreatorImpl: KtTypeCreator = KtFirTypeCreator(this, token)
- override val analysisScopeProviderImpl: KtAnalysisScopeProvider = KtAnalysisScopeProviderImpl(this, token)
+ override val analysisScopeProviderImpl: KtAnalysisScopeProvider
override val referenceResolveProviderImpl: KtReferenceResolveProvider = KtFirReferenceResolveProvider(this)
@@ -153,9 +153,10 @@
internal val firSymbolProvider: FirSymbolProvider get() = useSiteSession.symbolProvider
internal val targetPlatform: TargetPlatform get() = useSiteSession.moduleData.platform
- val useSiteAnalysisScope: GlobalSearchScope = analysisScopeProviderImpl.getAnalysisScope()
-
val extensionTools: List<LLFirResolveExtensionTool>
+
+ val useSiteAnalysisScope: GlobalSearchScope
+
val useSiteScopeDeclarationProvider: KotlinDeclarationProvider
val useSitePackageProvider: KotlinPackageProvider
@@ -167,6 +168,20 @@
firResolveSession.getSessionFor(dependency).llResolveExtensionTool
}
}
+
+ val shadowedScope = GlobalSearchScope.union(
+ buildSet {
+ // Add an empty scope to the shadowed set to give GlobalSearchScope.union something
+ // to work with if there are no extension tools.
+ // If there are extension tools, any empty scopes, whether from shadowedSearchScope
+ // on the extension tools or from this add() call, will be ignored.
+ add(GlobalSearchScope.EMPTY_SCOPE)
+ extensionTools.mapTo(this) { it.shadowedSearchScope }
+ }
+ )
+ analysisScopeProviderImpl = KtAnalysisScopeProviderImpl(this, token, shadowedScope)
+ useSiteAnalysisScope = analysisScopeProviderImpl.getAnalysisScope()
+
useSiteScopeDeclarationProvider = CompositeKotlinDeclarationProvider.create(
buildList {
add(project.createDeclarationProvider(useSiteAnalysisScope, useSiteModule))
diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleMultiModuleReferenceResolveWithResolveExtensionTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleMultiModuleReferenceResolveWithResolveExtensionTestGenerated.java
index b4ea9b9..e5786dc 100644
--- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleMultiModuleReferenceResolveWithResolveExtensionTestGenerated.java
+++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleMultiModuleReferenceResolveWithResolveExtensionTestGenerated.java
@@ -68,6 +68,24 @@
}
@Test
+ @TestMetadata("shadowedDeclaration.kt")
+ public void testShadowedDeclaration() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedDeclaration.kt");
+ }
+
+ @Test
+ @TestMetadata("shadowedJava.kt")
+ public void testShadowedJava() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedJava.kt");
+ }
+
+ @Test
+ @TestMetadata("shadowedOverload.kt")
+ public void testShadowedOverload() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedOverload.kt");
+ }
+
+ @Test
@TestMetadata("topLevelFunction.kt")
public void testTopLevelFunction() throws Exception {
runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/topLevelFunction.kt");
diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleSingleModuleReferenceResolveWithResolveExtensionTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleSingleModuleReferenceResolveWithResolveExtensionTestGenerated.java
index 8fa1fd2..9074af9 100644
--- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleSingleModuleReferenceResolveWithResolveExtensionTestGenerated.java
+++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleSingleModuleReferenceResolveWithResolveExtensionTestGenerated.java
@@ -59,6 +59,24 @@
}
@Test
+ @TestMetadata("shadowedDeclaration.kt")
+ public void testShadowedDeclaration() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedDeclaration.kt");
+ }
+
+ @Test
+ @TestMetadata("shadowedJava.kt")
+ public void testShadowedJava() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedJava.kt");
+ }
+
+ @Test
+ @TestMetadata("shadowedOverload.kt")
+ public void testShadowedOverload() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedOverload.kt");
+ }
+
+ @Test
@TestMetadata("topLevelFunction.kt")
public void testTopLevelFunction() throws Exception {
runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/topLevelFunction.kt");
diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/KtAnalysisScopeProviderImpl.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/KtAnalysisScopeProviderImpl.kt
index 24c4136..715e40d 100644
--- a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/KtAnalysisScopeProviderImpl.kt
+++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/KtAnalysisScopeProviderImpl.kt
@@ -23,7 +23,8 @@
class KtAnalysisScopeProviderImpl(
override val analysisSession: KtAnalysisSession,
- override val token: KtLifetimeToken
+ override val token: KtLifetimeToken,
+ private val shadowedScope: GlobalSearchScope
) : KtAnalysisScopeProvider() {
private val baseResolveScope by lazy(LazyThreadSafetyMode.PUBLICATION) {
@@ -31,13 +32,13 @@
}
private val resolveScope by lazy(LazyThreadSafetyMode.PUBLICATION) {
- KtAnalysisScopeProviderResolveScope(baseResolveScope, analysisSession.useSiteModule)
+ KtAnalysisScopeProviderResolveScope(baseResolveScope, analysisSession.useSiteModule, shadowedScope)
}
override fun getAnalysisScope(): GlobalSearchScope = resolveScope
override fun canBeAnalysed(psi: PsiElement): Boolean {
- return baseResolveScope.contains(psi)
+ return (baseResolveScope.contains(psi) && !shadowedScope.contains(psi))
|| psi.isFromGeneratedModule()
}
@@ -49,12 +50,17 @@
private class KtAnalysisScopeProviderResolveScope(
private val base: GlobalSearchScope,
- private val useSiteModule: KtModule
+ private val useSiteModule: KtModule,
+ private val shadowed: GlobalSearchScope,
) : GlobalSearchScope() {
override fun getProject(): Project? = base.project
override fun isSearchInModuleContent(aModule: Module): Boolean = base.isSearchInModuleContent(aModule)
override fun isSearchInLibraries(): Boolean = base.isSearchInLibraries
- override fun contains(file: VirtualFile): Boolean = base.contains(file) || file.isFromGeneratedModule(useSiteModule)
+ override fun contains(file: VirtualFile): Boolean =
+ (base.contains(file) && !shadowed.contains(file)) || file.isFromGeneratedModule(useSiteModule)
+
+ override fun toString() =
+ "Analysis scope for $useSiteModule (base: $base, shadowed: $shadowed)"
}
@OptIn(KtModuleStructureInternals::class)
diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractMultiModuleReferenceResolveWithResolveExtensionTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractMultiModuleReferenceResolveWithResolveExtensionTest.kt
index e94af32..4f58b7b 100644
--- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractMultiModuleReferenceResolveWithResolveExtensionTest.kt
+++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractMultiModuleReferenceResolveWithResolveExtensionTest.kt
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.references
+import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.impl.base.test.util.KtMultiModuleResolveExtensionProviderForTest
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionFile
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionProvider
@@ -12,6 +13,12 @@
import org.jetbrains.kotlin.name.FqName
abstract class AbstractMultiModuleReferenceResolveWithResolveExtensionTest : AbstractReferenceResolveWithResolveExtensionTest() {
- override fun createResolveExtensionProvider(files: List<KtResolveExtensionFile>, packages: Set<FqName>): KtResolveExtensionProvider =
- KtMultiModuleResolveExtensionProviderForTest(files, packages) { it is KtSourceModule && it.moduleName == "extendedModule" }
+ override fun createResolveExtensionProvider(
+ files: List<KtResolveExtensionFile>,
+ packages: Set<FqName>,
+ shadowedScope: GlobalSearchScope,
+ ): KtResolveExtensionProvider =
+ KtMultiModuleResolveExtensionProviderForTest(files, packages, shadowedScope) { module ->
+ module is KtSourceModule && module.moduleName == "extendedModule"
+ }
}
diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractReferenceResolveWithResolveExtensionTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractReferenceResolveWithResolveExtensionTest.kt
index 08df27a..9253a97 100644
--- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractReferenceResolveWithResolveExtensionTest.kt
+++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractReferenceResolveWithResolveExtensionTest.kt
@@ -5,6 +5,9 @@
package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.references
+import com.intellij.openapi.module.Module
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.impl.base.test.util.KtResolveExtensionFileForTests
import org.jetbrains.kotlin.analysis.api.impl.base.test.util.KtResolveExtensionProviderForTestPreAnalysisHandler
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionFile
@@ -17,17 +20,22 @@
abstract fun createResolveExtensionProvider(
files: List<KtResolveExtensionFile>,
packages: Set<FqName>,
+ shadowedScope: GlobalSearchScope,
): KtResolveExtensionProvider
override fun configureTest(builder: TestConfigurationBuilder) {
super.configureTest(builder)
val provider = createResolveExtensionProvider(
- listOf(
+ files = listOf(
KtResolveExtensionFileForTests(
"extension1.kt",
packageName = FqName("generated"),
topLevelClassifiersNames = setOf("GeneratedClass1"),
- topLevelCallableNames = setOf("generatedTopLevelFunction1", "generatedTopLevelExtensionFunction1"),
+ topLevelCallableNames = setOf(
+ "generatedTopLevelFunction1",
+ "generatedTopLevelExtensionFunction1",
+ "generatedOverloadedExtensionFunction",
+ ),
fileText = """|package generated
|
|class GeneratedClass1 {
@@ -37,6 +45,8 @@
|fun generatedTopLevelFunction1(): GeneratedClass2
|
|fun String.generatedTopLevelExtensionFunction1(boolean: Boolean): Int
+ |
+ |fun Any.generatedOverloadedExtensionFunction(): Int
""".trimMargin()
),
KtResolveExtensionFileForTests(
@@ -52,7 +62,14 @@
""".trimMargin(),
)
),
- setOf(FqName("generated"))
+ packages = setOf(FqName("generated")),
+ shadowedScope = object : GlobalSearchScope() {
+ override fun contains(file: VirtualFile): Boolean = ".hidden." in file.name
+
+ override fun isSearchInModuleContent(aModule: Module): Boolean = false
+
+ override fun isSearchInLibraries(): Boolean = false
+ }
)
with(builder) {
usePreAnalysisHandlers(::KtResolveExtensionProviderForTestPreAnalysisHandler.bind(listOf(provider)))
diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractSingleModuleReferenceResolveWithResolveExtensionTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractSingleModuleReferenceResolveWithResolveExtensionTest.kt
index fa88458..4b5b3e3 100644
--- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractSingleModuleReferenceResolveWithResolveExtensionTest.kt
+++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractSingleModuleReferenceResolveWithResolveExtensionTest.kt
@@ -5,12 +5,17 @@
package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.references
+import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.impl.base.test.util.KtSingleModuleResolveExtensionProviderForTest
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionFile
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionProvider
import org.jetbrains.kotlin.name.FqName
abstract class AbstractSingleModuleReferenceResolveWithResolveExtensionTest : AbstractReferenceResolveWithResolveExtensionTest() {
- override fun createResolveExtensionProvider(files: List<KtResolveExtensionFile>, packages: Set<FqName>): KtResolveExtensionProvider =
- KtSingleModuleResolveExtensionProviderForTest(files, packages)
+ override fun createResolveExtensionProvider(
+ files: List<KtResolveExtensionFile>,
+ packages: Set<FqName>,
+ shadowedScope: GlobalSearchScope,
+ ): KtResolveExtensionProvider =
+ KtSingleModuleResolveExtensionProviderForTest(files, packages, shadowedScope)
}
diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/util/KtResolveExtensionForTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/util/KtResolveExtensionForTest.kt
index 183e9e1..ce0ae39 100644
--- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/util/KtResolveExtensionForTest.kt
+++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/util/KtResolveExtensionForTest.kt
@@ -8,6 +8,7 @@
import com.intellij.mock.MockProject
import com.intellij.openapi.util.ModificationTracker
import com.intellij.psi.PsiElement
+import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtension
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionFile
@@ -25,20 +26,22 @@
class KtSingleModuleResolveExtensionProviderForTest(
private val files: List<KtResolveExtensionFile>,
private val packages: Set<FqName>,
+ private val shadowedScope: GlobalSearchScope,
) : KtResolveExtensionProvider() {
override fun provideExtensionsFor(module: KtModule): List<KtResolveExtension> {
- return listOf(KtResolveExtensionForTest(files, packages))
+ return listOf(KtResolveExtensionForTest(files, packages, shadowedScope))
}
}
class KtMultiModuleResolveExtensionProviderForTest(
private val files: List<KtResolveExtensionFile>,
private val packages: Set<FqName>,
+ private val shadowedScope: GlobalSearchScope,
private val hasResolveExtension: (KtModule) -> Boolean,
) : KtResolveExtensionProvider() {
override fun provideExtensionsFor(module: KtModule): List<KtResolveExtension> {
if (!hasResolveExtension(module)) return emptyList()
- return listOf(KtResolveExtensionForTest(files, packages))
+ return listOf(KtResolveExtensionForTest(files, packages, shadowedScope))
}
}
@@ -59,10 +62,12 @@
class KtResolveExtensionForTest(
private val files: List<KtResolveExtensionFile>,
private val packages: Set<FqName>,
+ private val shadowedScope: GlobalSearchScope,
) : KtResolveExtension() {
override fun getKtFiles(): List<KtResolveExtensionFile> = files
override fun getModificationTracker(): ModificationTracker = ModificationTracker.NEVER_CHANGED
override fun getContainedPackages(): Set<FqName> = packages
+ override fun getShadowedScope(): GlobalSearchScope = shadowedScope
}
class KtResolveExtensionFileForTests(
diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleMultiModuleReferenceResolveWithResolveExtensionTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleMultiModuleReferenceResolveWithResolveExtensionTestGenerated.java
index 726735a..76967f1 100644
--- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleMultiModuleReferenceResolveWithResolveExtensionTestGenerated.java
+++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleMultiModuleReferenceResolveWithResolveExtensionTestGenerated.java
@@ -68,6 +68,24 @@
}
@Test
+ @TestMetadata("shadowedDeclaration.kt")
+ public void testShadowedDeclaration() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedDeclaration.kt");
+ }
+
+ @Test
+ @TestMetadata("shadowedJava.kt")
+ public void testShadowedJava() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedJava.kt");
+ }
+
+ @Test
+ @TestMetadata("shadowedOverload.kt")
+ public void testShadowedOverload() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedOverload.kt");
+ }
+
+ @Test
@TestMetadata("topLevelFunction.kt")
public void testTopLevelFunction() throws Exception {
runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/topLevelFunction.kt");
diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleSingleModuleReferenceResolveWithResolveExtensionTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleSingleModuleReferenceResolveWithResolveExtensionTestGenerated.java
index 57c5698..4e746e0 100644
--- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleSingleModuleReferenceResolveWithResolveExtensionTestGenerated.java
+++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleSingleModuleReferenceResolveWithResolveExtensionTestGenerated.java
@@ -59,6 +59,24 @@
}
@Test
+ @TestMetadata("shadowedDeclaration.kt")
+ public void testShadowedDeclaration() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedDeclaration.kt");
+ }
+
+ @Test
+ @TestMetadata("shadowedJava.kt")
+ public void testShadowedJava() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedJava.kt");
+ }
+
+ @Test
+ @TestMetadata("shadowedOverload.kt")
+ public void testShadowedOverload() throws Exception {
+ runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedOverload.kt");
+ }
+
+ @Test
@TestMetadata("topLevelFunction.kt")
public void testTopLevelFunction() throws Exception {
runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/topLevelFunction.kt");
diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/resolve/extensions/KtResolveExtension.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/resolve/extensions/KtResolveExtension.kt
index 6615394..6fbd2e4 100644
--- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/resolve/extensions/KtResolveExtension.kt
+++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/resolve/extensions/KtResolveExtension.kt
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.api.resolve.extensions
import com.intellij.openapi.util.ModificationTracker
+import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.name.FqName
/**
@@ -53,4 +54,17 @@
* @see KtResolveExtension
*/
public abstract fun getContainedPackages(): Set<FqName>
+
+ /**
+ * Returns the scope of files that should be shadowed by the files provided by [getKtFiles].
+ *
+ * Any files in the module that are included in this scope will be removed from analysis results. This allows the files provided by
+ * [getKtFiles] to cleanly replace those files from the module.
+ *
+ * If this resolve extension is being used to generate declarations that would normally be provided by sources generated by an external
+ * build task, such as a resource compiler or annotation processor, the resolve extension should provide a scope here that covers those
+ * externally generated sources. This will prevent collisions between the definitions provided by [getKtFiles] and those provided by the
+ * (potentially stale) externally generated sources.
+ */
+ public open fun getShadowedScope(): GlobalSearchScope = GlobalSearchScope.EMPTY_SCOPE
}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedDeclaration.kt b/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedDeclaration.kt
new file mode 100644
index 0000000..efff20c
--- /dev/null
+++ b/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedDeclaration.kt
@@ -0,0 +1,15 @@
+// UNRESOLVED_REFERENCE
+
+// MODULE: extendedModule
+// FILE: declarations.hidden.kt
+package foo
+
+fun bar() = "baz"
+
+// MODULE: dependency2
+
+// MODULE: main(extendedModule, dependency2)()()
+// FILE: main.kt
+fun main() {
+ val x = foo.<caret>bar()
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedJava.kt b/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedJava.kt
new file mode 100644
index 0000000..a47c38e
--- /dev/null
+++ b/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedJava.kt
@@ -0,0 +1,19 @@
+// UNRESOLVED_REFERENCE
+
+// MODULE: extendedModule
+// FILE: TestClass.hidden.java
+package foo;
+
+public class TestClass {
+ public TestClass() {}
+}
+
+// MODULE: dependency2
+
+// MODULE: main(extendedModule, dependency2)()()
+// FILE: main.kt
+package foo
+
+fun main() {
+ val x = <caret>TestClass()
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedOverload.kt b/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedOverload.kt
new file mode 100644
index 0000000..03d24c7
--- /dev/null
+++ b/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedOverload.kt
@@ -0,0 +1,15 @@
+// MODULE: extendedModule
+// FILE: generated.hidden.kt
+package generated
+
+fun String.generatedOverloadedExtensionFunction(): Int = TODO()
+
+// MODULE: dependency2
+
+// MODULE: main(extendedModule, dependency2)()()
+// FILE: main.kt
+import generated.*
+
+fun main() {
+ "string".generatedOverloadedExtension<caret>Function()
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedOverload.txt b/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedOverload.txt
new file mode 100644
index 0000000..fbdbb1d
--- /dev/null
+++ b/analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/shadowedOverload.txt
@@ -0,0 +1,2 @@
+Resolved to:
+0: (in generated) fun kotlin.Any.generatedOverloadedExtensionFunction(): kotlin.Int
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedDeclaration.kt b/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedDeclaration.kt
new file mode 100644
index 0000000..94a6ec3
--- /dev/null
+++ b/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedDeclaration.kt
@@ -0,0 +1,11 @@
+// UNRESOLVED_REFERENCE
+
+// FILE: declarations.hidden.kt
+package foo
+
+fun bar() = "baz"
+
+// FILE: main.kt
+fun main() {
+ val x = foo.<caret>bar()
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedJava.kt b/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedJava.kt
new file mode 100644
index 0000000..36a4a5b
--- /dev/null
+++ b/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedJava.kt
@@ -0,0 +1,15 @@
+// UNRESOLVED_REFERENCE
+
+// FILE: TestClass.hidden.java
+package foo;
+
+public class TestClass {
+ public TestClass() {}
+}
+
+// FILE: main.kt
+package foo
+
+fun main() {
+ val x = <caret>TestClass()
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedOverload.kt b/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedOverload.kt
new file mode 100644
index 0000000..2354781
--- /dev/null
+++ b/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedOverload.kt
@@ -0,0 +1,11 @@
+// FILE: generated.hidden.kt
+package generated
+
+fun String.generatedOverloadedExtensionFunction(): Int = TODO()
+
+// FILE: main.kt
+import generated.*
+
+fun main() {
+ "string".generatedOverloadedExtension<caret>Function()
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedOverload.txt b/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedOverload.txt
new file mode 100644
index 0000000..fbdbb1d
--- /dev/null
+++ b/analysis/analysis-api/testData/resolveExtensions/referenceResolve/shadowedOverload.txt
@@ -0,0 +1,2 @@
+Resolved to:
+0: (in generated) fun kotlin.Any.generatedOverloadedExtensionFunction(): kotlin.Int
\ No newline at end of file
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt
index 5889958..60c9085 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt
@@ -92,15 +92,3 @@
)
}
-
-internal fun createJavaSymbolProvider(
- firSession: FirSession,
- moduleData: LLFirModuleData,
- project: Project,
- contentScope: GlobalSearchScope
-): JavaSymbolProvider {
- return JavaSymbolProvider(
- firSession,
- FirJavaFacadeForSource(firSession, moduleData, project.createJavaClassFinder(contentScope))
- )
-}
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirCombinedJavaSymbolProvider.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirCombinedJavaSymbolProvider.kt
index 54a7f45..5a7781a 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirCombinedJavaSymbolProvider.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirCombinedJavaSymbolProvider.kt
@@ -90,9 +90,9 @@
override fun getPackage(fqName: FqName): FqName? = providers.firstNotNullOfOrNull { it.getPackage(fqName) }
companion object {
- fun merge(session: FirSession, project: Project, providers: List<JavaSymbolProvider>): FirSymbolProvider? =
+ fun merge(session: FirSession, project: Project, providers: List<LLFirJavaSymbolProvider>): FirSymbolProvider? =
if (providers.size > 1) {
- val combinedScope = GlobalSearchScope.union(providers.map { it.session.llFirModuleData.ktModule.contentScope })
+ val combinedScope = GlobalSearchScope.union(providers.map { it.searchScope })
val javaClassFinder = project.createJavaClassFinder(combinedScope)
LLFirCombinedJavaSymbolProvider(session, project, providers, javaClassFinder)
} else providers.singleOrNull()
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirJavaSymbolProvider.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirJavaSymbolProvider.kt
new file mode 100644
index 0000000..d1b7eda
--- /dev/null
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirJavaSymbolProvider.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010-2023 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.low.level.api.fir.providers
+
+import com.intellij.openapi.project.Project
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirModuleData
+import org.jetbrains.kotlin.fir.FirSession
+import org.jetbrains.kotlin.fir.java.FirJavaFacadeForSource
+import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
+import org.jetbrains.kotlin.load.java.createJavaClassFinder
+
+internal class LLFirJavaSymbolProvider(
+ firSession: FirSession,
+ moduleData: LLFirModuleData,
+ project: Project,
+ val searchScope: GlobalSearchScope
+) : JavaSymbolProvider(
+ firSession,
+ FirJavaFacadeForSource(firSession, moduleData, project.createJavaClassFinder(searchScope))
+)
\ No newline at end of file
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProvider.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProvider.kt
index 22f8a8b..e01eec4 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProvider.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProvider.kt
@@ -5,11 +5,11 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
+import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
+import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.SyntheticFirClassProvider
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
-import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
-import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.NoMutableState
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
@@ -29,22 +29,23 @@
@ThreadSafeMutableState
internal class LLFirProvider(
- val session: FirSession,
+ val session: LLFirSession,
private val moduleComponents: LLFirModuleResolveComponents,
- private val declarationProvider: KotlinDeclarationProvider,
- packageProvider: KotlinPackageProvider,
canContainKotlinPackage: Boolean,
+ declarationProviderFactory: (GlobalSearchScope) -> KotlinDeclarationProvider?,
) : FirProvider() {
override val symbolProvider: FirSymbolProvider = SymbolProvider()
private val providerHelper = LLFirProviderHelper(
session,
moduleComponents.firFileBuilder,
- declarationProvider,
- packageProvider,
canContainKotlinPackage,
+ declarationProviderFactory,
)
+ val searchScope: GlobalSearchScope
+ get() = providerHelper.searchScope
+
override val isPhasedFirAllowed: Boolean get() = true
override fun getFirClassifierByFqName(classId: ClassId): FirClassLikeDeclaration? =
@@ -103,9 +104,7 @@
override fun getFirFilesByPackage(fqName: FqName): List<FirFile> = error("Should not be called in FIR IDE")
-
- override fun getClassNamesInPackage(fqName: FqName): Set<Name> =
- declarationProvider.getTopLevelKotlinClassLikeDeclarationNamesInPackage(fqName)
+ override fun getClassNamesInPackage(fqName: FqName): Set<Name> = providerHelper.getTopLevelClassNamesInPackage(fqName)
@NoMutableState
internal inner class SymbolProvider : LLFirKotlinSymbolProvider(session) {
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProviderHelper.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProviderHelper.kt
index c47e006..2a3b629 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProviderHelper.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProviderHelper.kt
@@ -5,18 +5,19 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
+import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirFileBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.CompositeKotlinPackageProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.LLFirResolveExtensionTool
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.llResolveExtensionTool
+import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirElementFinder
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirKotlinSymbolNamesProvider
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
-import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
+import org.jetbrains.kotlin.analysis.providers.createPackageProvider
import org.jetbrains.kotlin.analysis.providers.impl.declarationProviders.CompositeKotlinDeclarationProvider
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.AnalysisFlags
-import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.caches.firCachesFactory
import org.jetbrains.kotlin.fir.caches.getValue
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
@@ -35,27 +36,37 @@
import org.jetbrains.kotlin.psi.KtFile
internal class LLFirProviderHelper(
- firSession: FirSession,
+ firSession: LLFirSession,
private val firFileBuilder: LLFirFileBuilder,
- mainDeclarationProvider: KotlinDeclarationProvider,
- mainPackageProvider: KotlinPackageProvider,
canContainKotlinPackage: Boolean,
+ declarationProviderFactory: (GlobalSearchScope) -> KotlinDeclarationProvider?
) {
private val extensionTool: LLFirResolveExtensionTool? = firSession.llResolveExtensionTool
+ val searchScope: GlobalSearchScope =
+ firSession.ktModule.contentScope.run {
+ val notShadowedScope = extensionTool?.shadowedSearchScope?.let { GlobalSearchScope.notScope(it) }
+ if (notShadowedScope != null) {
+ this.intersectWith(notShadowedScope)
+ } else {
+ this
+ }
+ }
+
val declarationProvider = CompositeKotlinDeclarationProvider.create(
listOfNotNull(
- mainDeclarationProvider,
+ declarationProviderFactory(searchScope),
extensionTool?.declarationProvider,
)
)
private val packageProvider = CompositeKotlinPackageProvider.create(
listOfNotNull(
- mainPackageProvider,
+ firSession.project.createPackageProvider(searchScope),
extensionTool?.packageProvider,
)
)
+
private val allowKotlinPackage = canContainKotlinPackage ||
firSession.languageVersionSettings.getFlag(AnalysisFlags.allowKotlinPackage)
@@ -100,6 +111,11 @@
return classifierByClassId.getValue(classId, classLikeDeclaration)
}
+ fun getTopLevelClassNamesInPackage(packageFqName: FqName): Set<Name> {
+ if (!allowKotlinPackage && packageFqName.isKotlinPackage()) return emptySet()
+ return declarationProvider.getTopLevelKotlinClassLikeDeclarationNamesInPackage(packageFqName)
+ }
+
fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List<FirCallableSymbol<*>> {
if (!allowKotlinPackage && packageFqName.isKotlinPackage()) return emptyList()
val callableId = CallableId(packageFqName, name)
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 30bee09..23aa10a 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
@@ -8,6 +8,7 @@
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.ModificationTracker
import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.KtAnalysisAllowanceManager
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtension
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionFile
@@ -40,6 +41,7 @@
abstract val declarationProvider: LLFirResolveExtensionToolDeclarationProvider
abstract val packageProvider: KotlinPackageProvider
abstract val packageFilter: LLFirResolveExtensionToolPackageFilter
+ abstract val shadowedSearchScope: GlobalSearchScope
internal abstract val symbolNamesProvider: FirSymbolNamesProvider
}
@@ -57,13 +59,19 @@
override val packageFilter = LLFirResolveExtensionToolPackageFilter(extensions)
- override val modificationTrackers by lazy { extensions.map { it.getModificationTracker() } }
+ override val modificationTrackers by lazy { forbidAnalysis { extensions.map { it.getModificationTracker() } } }
override val declarationProvider: LLFirResolveExtensionToolDeclarationProvider =
LLFirResolveExtensionToolDeclarationProvider(fileProvider, session.ktModule)
override val packageProvider: KotlinPackageProvider = LLFirResolveExtensionToolPackageProvider(packageFilter)
+ override val shadowedSearchScope by lazy {
+ forbidAnalysis {
+ GlobalSearchScope.union(extensions.mapTo(mutableSetOf()) { it.getShadowedScope() })
+ }
+ }
+
override val symbolNamesProvider: FirSymbolNamesProvider = LLFirResolveExtensionToolSymbolNamesProvider(packageFilter, fileProvider)
}
@@ -310,7 +318,7 @@
.filter { it.getFilePackageName() == packageFqName }
}
- fun getAllFiles(): Sequence<KtResolveExtensionFile> {
+ fun getAllFiles(): Sequence<KtResolveExtensionFile> = forbidAnalysis {
return extensions
.asSequence()
.flatMap { it.getKtFiles() }
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt
index d0cf098..13e95a5 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt
@@ -15,11 +15,11 @@
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.*
import org.jetbrains.kotlin.analysis.project.structure.*
+import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
import org.jetbrains.kotlin.analysis.providers.createAnnotationResolver
import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider
-import org.jetbrains.kotlin.analysis.providers.createPackageProvider
-import org.jetbrains.kotlin.analysis.providers.impl.declarationProviders.EmptyKotlinDeclarationProvider
import org.jetbrains.kotlin.analysis.providers.impl.declarationProviders.FileBasedKotlinDeclarationProvider
+import org.jetbrains.kotlin.analysis.providers.impl.util.mergeInto
import org.jetbrains.kotlin.analysis.utils.trackers.CompositeModificationTracker
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
@@ -48,7 +48,6 @@
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration
-import org.jetbrains.kotlin.analysis.providers.impl.util.mergeInto
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
internal abstract class LLFirAbstractSessionFactory(protected val project: Project) {
@@ -66,7 +65,6 @@
val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
- val contentScope = module.contentScope
val dependencies = collectSourceModuleDependencies(module)
val dependencyTracker = createSourceModuleDependencyTracker(module, dependencies)
@@ -90,10 +88,10 @@
val provider = LLFirProvider(
this,
components,
- FileBasedKotlinDeclarationProvider(module.file),
- project.createPackageProvider(contentScope),
canContainKotlinPackage = true,
- )
+ ) { scope ->
+ scope.createScopedDeclarationProviderForFile(module.file)
+ }
register(FirProvider::class, provider)
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
@@ -103,7 +101,7 @@
add(builtinsSession.symbolProvider)
})
- val javaSymbolProvider = createJavaSymbolProvider(this, moduleData, project, contentScope)
+ val javaSymbolProvider = LLFirJavaSymbolProvider(this, moduleData, project, provider.searchScope)
register(JavaSymbolProvider::class, javaSymbolProvider)
register(
@@ -170,10 +168,10 @@
val provider = LLFirProvider(
this,
components,
- if (ktFile != null) FileBasedKotlinDeclarationProvider(ktFile) else EmptyKotlinDeclarationProvider,
- project.createPackageProvider(module.contentScope),
canContainKotlinPackage = true,
- )
+ ) { scope ->
+ ktFile?.let { scope.createScopedDeclarationProviderForFile(it) }
+ }
register(FirProvider::class, provider)
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
@@ -226,8 +224,6 @@
components.session = session
val moduleData = createModuleData(session)
- val contentScope = module.contentScope
-
return session.apply {
registerModuleData(moduleData)
@@ -240,16 +236,16 @@
val firProvider = LLFirProvider(
this,
components,
- project.createDeclarationProvider(contentScope, module),
- project.createPackageProvider(contentScope),
/* Source modules can contain `kotlin` package only if `-Xallow-kotlin-package` is specified, this is handled in LLFirProvider */
canContainKotlinPackage = false,
- )
+ ) { scope ->
+ project.createDeclarationProvider(scope, module)
+ }
register(FirProvider::class, firProvider)
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
- registerCompilerPluginServices(contentScope, project, module)
+ registerCompilerPluginServices(firProvider.searchScope, project, module)
registerCompilerPluginExtensions(project, module)
registerCommonComponentsAfterExtensionsAreConfigured()
@@ -273,7 +269,7 @@
}
val context = SourceSessionCreationContext(
- moduleData, contentScope, firProvider, dependencyProvider, syntheticFunctionInterfaceProvider,
+ moduleData, firProvider.searchScope, firProvider, dependencyProvider, syntheticFunctionInterfaceProvider,
switchableExtensionDeclarationsSymbolProvider,
)
additionalSessionConfiguration(context)
@@ -320,22 +316,20 @@
registerCommonComponentsAfterExtensionsAreConfigured()
registerResolveComponents()
- val contentScope = module.contentScope
-
val firProvider = LLFirProvider(
this,
components,
- project.createDeclarationProvider(contentScope, module),
- project.createPackageProvider(contentScope),
canContainKotlinPackage = true,
- )
+ ) { scope ->
+ project.createDeclarationProvider(scope, module)
+ }
register(FirProvider::class, firProvider)
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
// We need FirRegisteredPluginAnnotations during extensions' registration process
- val annotationsResolver = project.createAnnotationResolver(contentScope)
+ val annotationsResolver = project.createAnnotationResolver(firProvider.searchScope)
register(FirRegisteredPluginAnnotations::class, LLFirIdeRegisteredPluginAnnotations(this, annotationsResolver))
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
@@ -360,7 +354,7 @@
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
- val context = LibrarySessionCreationContext(moduleData, contentScope, firProvider, dependencyProvider)
+ val context = LibrarySessionCreationContext(moduleData, firProvider.searchScope, firProvider, dependencyProvider)
additionalSessionConfiguration(context)
LLFirSessionConfigurator.configure(this)
@@ -504,8 +498,21 @@
) {
mergeInto(destination) {
merge<LLFirProvider.SymbolProvider> { LLFirCombinedKotlinSymbolProvider.merge(session, project, it) }
- merge<JavaSymbolProvider> { LLFirCombinedJavaSymbolProvider.merge(session, project, it) }
+ merge<LLFirJavaSymbolProvider> { LLFirCombinedJavaSymbolProvider.merge(session, project, it) }
merge<FirExtensionSyntheticFunctionInterfaceProvider> { LLFirCombinedSyntheticFunctionSymbolProvider.merge(session, it) }
}
}
+
+ /**
+ * Creates a single-file [KotlinDeclarationProvider] for the provided file, if it is in the search scope.
+ *
+ * Otherwise, returns `null`.
+ */
+ private fun GlobalSearchScope.createScopedDeclarationProviderForFile(file: KtFile): KotlinDeclarationProvider? =
+ // KtFiles without a backing VirtualFile can't be covered by a shadow scope, and are thus assumed in-scope.
+ if (file.virtualFile == null || contains(file.virtualFile)) {
+ FileBasedKotlinDeclarationProvider(file)
+ } else {
+ null
+ }
}
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJvmSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJvmSessionFactory.kt
index 1c82bef..6e3cf81 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJvmSessionFactory.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJvmSessionFactory.kt
@@ -25,7 +25,7 @@
return doCreateSourcesSession(module, FirKotlinScopeProvider(::wrapScopeWithJvmMapped)) { context ->
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
registerJavaSpecificResolveComponents()
- val javaSymbolProvider = createJavaSymbolProvider(this, context.moduleData, project, context.contentScope)
+ val javaSymbolProvider = LLFirJavaSymbolProvider(this, context.moduleData, project, context.contentScope)
register(JavaSymbolProvider::class, javaSymbolProvider)
register(
@@ -50,7 +50,7 @@
return doCreateLibrarySession(module) { context ->
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
registerJavaSpecificResolveComponents()
- val javaSymbolProvider = createJavaSymbolProvider(this, context.moduleData, project, context.contentScope)
+ val javaSymbolProvider = LLFirJavaSymbolProvider(this, context.moduleData, project, context.contentScope)
register(
FirSymbolProvider::class,
LLFirModuleWithDependenciesSymbolProvider(
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedDeserializedSymbolProviderFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedDeserializedSymbolProviderFactory.kt
index 1e37eb9..87225c4 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedDeserializedSymbolProviderFactory.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedDeserializedSymbolProviderFactory.kt
@@ -13,7 +13,7 @@
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirInternals
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.JvmFirDeserializedSymbolProviderFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirModuleData
-import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.createJavaSymbolProvider
+import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirJavaSymbolProvider
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider
@@ -56,7 +56,7 @@
FirDeclarationOrigin.Library
)
)
- add(createJavaSymbolProvider(session, moduleData, project, scope))
+ add(LLFirJavaSymbolProvider(session, moduleData, project, scope))
}
}
}
\ No newline at end of file
diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt
index 58148c4..c19ab2c 100644
--- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt
+++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt
@@ -25,7 +25,7 @@
// For library and incremental compilation sessions use `KotlinDeserializedJvmSymbolsProvider`
// in order to load Kotlin classes as well.
//Also used in IDE for loading java classes separately from stub based kotlin classes
-class JavaSymbolProvider(
+open class JavaSymbolProvider(
session: FirSession,
private val javaFacade: FirJavaFacade,
) : FirSymbolProvider(session) {