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 10540022c0c..902a0b47eb6 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 @@ class KtFe10AnalysisSession( 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 4704c7b0038..9dcf00cb5b4 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 @@ private constructor( 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 @@ private constructor( internal val firSymbolProvider: FirSymbolProvider get() = useSiteSession.symbolProvider internal val targetPlatform: TargetPlatform get() = useSiteSession.moduleData.platform - val useSiteAnalysisScope: GlobalSearchScope = analysisScopeProviderImpl.getAnalysisScope() - val extensionTools: List + + val useSiteAnalysisScope: GlobalSearchScope + val useSiteScopeDeclarationProvider: KotlinDeclarationProvider val useSitePackageProvider: KotlinPackageProvider @@ -167,6 +168,20 @@ private constructor( 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 b4ea9b950d4..e5786dc648f 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 @@ -67,6 +67,24 @@ public class FirIdeNormalAnalysisSourceModuleMultiModuleReferenceResolveWithReso runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/extensionFunction.kt"); } + @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 { 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 8fa1fd2d260..9074af9d0df 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 @@ -58,6 +58,24 @@ public class FirIdeNormalAnalysisSourceModuleSingleModuleReferenceResolveWithRes runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/extensionFunction.kt"); } + @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 { 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 24c41369e5f..715e40d92a6 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 @@ import org.jetbrains.kotlin.psi.psiUtil.contains 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 @@ class KtAnalysisScopeProviderImpl( } 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 @@ class KtAnalysisScopeProviderImpl( 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 e94af32a8ed..4f58b7b08e7 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.analysis.project.structure.KtSourceModule import org.jetbrains.kotlin.name.FqName abstract class AbstractMultiModuleReferenceResolveWithResolveExtensionTest : AbstractReferenceResolveWithResolveExtensionTest() { - override fun createResolveExtensionProvider(files: List, packages: Set): KtResolveExtensionProvider = - KtMultiModuleResolveExtensionProviderForTest(files, packages) { it is KtSourceModule && it.moduleName == "extendedModule" } + override fun createResolveExtensionProvider( + files: List, + packages: Set, + 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 08df27a956e..9253a9782be 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 class AbstractReferenceResolveWithResolveExtensionTest : AbstractRefere abstract fun createResolveExtensionProvider( files: List, packages: Set, + 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 @@ abstract class AbstractReferenceResolveWithResolveExtensionTest : AbstractRefere |fun generatedTopLevelFunction1(): GeneratedClass2 | |fun String.generatedTopLevelExtensionFunction1(boolean: Boolean): Int + | + |fun Any.generatedOverloadedExtensionFunction(): Int """.trimMargin() ), KtResolveExtensionFileForTests( @@ -52,7 +62,14 @@ abstract class AbstractReferenceResolveWithResolveExtensionTest : AbstractRefere """.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 fa88458f1c5..4b5b3e39309 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, packages: Set): KtResolveExtensionProvider = - KtSingleModuleResolveExtensionProviderForTest(files, packages) + override fun createResolveExtensionProvider( + files: List, + packages: Set, + 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 183e9e1c5b6..ce0ae399c73 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 @@ package org.jetbrains.kotlin.analysis.api.impl.base.test.util 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 @@ import org.jetbrains.kotlin.test.services.TestServices class KtSingleModuleResolveExtensionProviderForTest( private val files: List, private val packages: Set, + private val shadowedScope: GlobalSearchScope, ) : KtResolveExtensionProvider() { override fun provideExtensionsFor(module: KtModule): List { - return listOf(KtResolveExtensionForTest(files, packages)) + return listOf(KtResolveExtensionForTest(files, packages, shadowedScope)) } } class KtMultiModuleResolveExtensionProviderForTest( private val files: List, private val packages: Set, + private val shadowedScope: GlobalSearchScope, private val hasResolveExtension: (KtModule) -> Boolean, ) : KtResolveExtensionProvider() { override fun provideExtensionsFor(module: KtModule): List { if (!hasResolveExtension(module)) return emptyList() - return listOf(KtResolveExtensionForTest(files, packages)) + return listOf(KtResolveExtensionForTest(files, packages, shadowedScope)) } } @@ -59,10 +62,12 @@ class KtResolveExtensionProviderForTestPreAnalysisHandler( class KtResolveExtensionForTest( private val files: List, private val packages: Set, + private val shadowedScope: GlobalSearchScope, ) : KtResolveExtension() { override fun getKtFiles(): List = files override fun getModificationTracker(): ModificationTracker = ModificationTracker.NEVER_CHANGED override fun getContainedPackages(): Set = 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 726735a7e9c..76967f1c4e1 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 @@ -67,6 +67,24 @@ public class FirStandaloneNormalAnalysisSourceModuleMultiModuleReferenceResolveW runTest("analysis/analysis-api/testData/resolveExtensions/multiModule/referenceResolve/extendedModuleDependency/extensionFunction.kt"); } + @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 { 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 57c5698d984..4e746e053f2 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 @@ -58,6 +58,24 @@ public class FirStandaloneNormalAnalysisSourceModuleSingleModuleReferenceResolve runTest("analysis/analysis-api/testData/resolveExtensions/referenceResolve/extensionFunction.kt"); } + @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 { 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 6615394a6b1..6fbd2e4d85a 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 @@ public abstract class KtResolveExtension { * @see KtResolveExtension */ public abstract fun getContainedPackages(): Set + + /** + * 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 00000000000..efff20c908e --- /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.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 00000000000..a47c38e0782 --- /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 = 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 00000000000..03d24c7e154 --- /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".generatedOverloadedExtensionFunction() +} \ 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 00000000000..fbdbb1d6982 --- /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 00000000000..94a6ec38473 --- /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.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 00000000000..36a4a5bee60 --- /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 = 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 00000000000..2354781ef6d --- /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".generatedOverloadedExtensionFunction() +} \ 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 00000000000..fbdbb1d6982 --- /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 5889958932f..60c9085d26a 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 LLFirSourcesSession.registerCompilerPluginServices( ) } - -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 54a7f45a624..5a7781ad26b 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 @@ internal class LLFirCombinedJavaSymbolProvider private constructor( override fun getPackage(fqName: FqName): FqName? = providers.firstNotNullOfOrNull { it.getPackage(fqName) } companion object { - fun merge(session: FirSession, project: Project, providers: List): FirSymbolProvider? = + fun merge(session: FirSession, project: Project, providers: List): 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 00000000000..d1b7eda4135 --- /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 22f8a8b1918..e01eec49874 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 @@ import org.jetbrains.kotlin.psi.KtProperty @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 @@ internal class LLFirProvider( override fun getFirFilesByPackage(fqName: FqName): List = error("Should not be called in FIR IDE") - - override fun getClassNamesInPackage(fqName: FqName): Set = - declarationProvider.getTopLevelKotlinClassLikeDeclarationNamesInPackage(fqName) + override fun getClassNamesInPackage(fqName: FqName): Set = 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 c47e00687fa..2a3b629d1d1 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.KtClassLikeDeclaration 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 @@ internal class LLFirProviderHelper( return classifierByClassId.getValue(classId, classLikeDeclaration) } + fun getTopLevelClassNamesInPackage(packageFqName: FqName): Set { + if (!allowKotlinPackage && packageFqName.isKotlinPackage()) return emptySet() + return declarationProvider.getTopLevelKotlinClassLikeDeclarationNamesInPackage(packageFqName) + } + fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List> { 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 30bee09ee7a..23aa10a3b93 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 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions 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 class LLFirResolveExtensionTool : FirSessionComponent { 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 @@ internal class LLFirNonEmptyResolveExtensionTool( 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 @@ internal class LLFirResolveExtensionsFileProvider( .filter { it.getFilePackageName() == packageFqName } } - fun getAllFiles(): Sequence { + fun getAllFiles(): Sequence = 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 d0cf098b358..13e95a5d7bf 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.LLFirModuleResolveCompone 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.compiler.plugin.FirScriptingSamWithReceive 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 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje 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 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje 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 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje 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 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje 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 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje components.session = session val moduleData = createModuleData(session) - val contentScope = module.contentScope - return session.apply { registerModuleData(moduleData) @@ -240,16 +236,16 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje 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 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje } val context = SourceSessionCreationContext( - moduleData, contentScope, firProvider, dependencyProvider, syntheticFunctionInterfaceProvider, + moduleData, firProvider.searchScope, firProvider, dependencyProvider, syntheticFunctionInterfaceProvider, switchableExtensionDeclarationsSymbolProvider, ) additionalSessionConfiguration(context) @@ -320,22 +316,20 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje 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 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje 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 @@ internal abstract class LLFirAbstractSessionFactory(protected val project: Proje ) { mergeInto(destination) { merge { LLFirCombinedKotlinSymbolProvider.merge(session, project, it) } - merge { LLFirCombinedJavaSymbolProvider.merge(session, project, it) } + merge { LLFirCombinedJavaSymbolProvider.merge(session, project, it) } merge { 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 1c82bef1fef..6e3cf8150eb 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 @@ internal class LLFirJvmSessionFactory(project: Project) : LLFirAbstractSessionFa 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 @@ internal class LLFirJvmSessionFactory(project: Project) : LLFirAbstractSessionFa 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 1e37eb9287f..87225c458aa 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 com.intellij.psi.search.GlobalSearchScope 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 @@ class JvmStubBasedDeserializedSymbolProviderFactory : JvmFirDeserializedSymbolPr 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 58148c475b1..c19ab2c2a7c 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 @@ import org.jetbrains.kotlin.name.Name // 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) {