diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/Fe10AnalysisFacade.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/Fe10AnalysisFacade.kt index a9a02008b3b..bf31d01773c 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/Fe10AnalysisFacade.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/Fe10AnalysisFacade.kt @@ -49,7 +49,7 @@ interface Fe10AnalysisFacade { class Fe10AnalysisContext( facade: Fe10AnalysisFacade, - contextElement: KtElement, + val contextElement: KtElement, val token: ValidityToken ) : Fe10AnalysisFacade by facade { val resolveSession: ResolveSession = getResolveSession(contextElement) 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 1eae4e3b0e1..a5f191db92e 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 @@ -8,15 +8,24 @@ package org.jetbrains.kotlin.analysis.api.descriptors import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.components.* import org.jetbrains.kotlin.analysis.api.descriptors.components.* +import org.jetbrains.kotlin.analysis.api.impl.base.components.KtAnalysisScopeProviderImpl import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolProvider import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.project.structure.getKtModule import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile @Suppress("LeakingThis") -class KtFe10AnalysisSession(val analysisContext: Fe10AnalysisContext) : KtAnalysisSession(analysisContext.token) { - constructor(contextElement: KtElement, token: ValidityToken) : - this(Fe10AnalysisContext(Fe10AnalysisFacade.getInstance(contextElement.project), contextElement, token)) +class KtFe10AnalysisSession( + val analysisContext: Fe10AnalysisContext, + override val useSiteModule: KtModule +) : KtAnalysisSession(analysisContext.token) { + constructor(contextElement: KtElement, token: ValidityToken) : this( + Fe10AnalysisContext(Fe10AnalysisFacade.getInstance(contextElement.project), contextElement, token), + contextElement.getKtModule() + ) + override val smartCastProviderImpl: KtSmartCastProvider = KtFe10SmartCastProvider(this) override val diagnosticProviderImpl: KtDiagnosticProvider = KtFe10DiagnosticProvider(this) @@ -25,7 +34,8 @@ class KtFe10AnalysisSession(val analysisContext: Fe10AnalysisContext) : KtAnalys override val symbolProviderImpl: KtSymbolProvider = KtFe10SymbolProvider(this) override val callResolverImpl: KtCallResolver = KtFe10CallResolver(this) override val completionCandidateCheckerImpl: KtCompletionCandidateChecker = KtFe10CompletionCandidateChecker(this) - override val symbolDeclarationOverridesProviderImpl: KtSymbolDeclarationOverridesProvider = KtFe10SymbolDeclarationOverridesProvider(this) + override val symbolDeclarationOverridesProviderImpl: KtSymbolDeclarationOverridesProvider = + KtFe10SymbolDeclarationOverridesProvider(this) override val referenceShortenerImpl: KtReferenceShortener = KtFe10ReferenceShortener(this) override val symbolDeclarationRendererProviderImpl: KtSymbolDeclarationRendererProvider = KtFe10SymbolDeclarationRendererProvider(this) override val expressionTypeProviderImpl: KtExpressionTypeProvider = KtFe10ExpressionTypeProvider(this) @@ -43,6 +53,7 @@ class KtFe10AnalysisSession(val analysisContext: Fe10AnalysisContext) : KtAnalys 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 fun createContextDependentCopy(originalKtFile: KtFile, elementToReanalyze: KtElement): KtAnalysisSession { return KtFe10AnalysisSession(elementToReanalyze, token) diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10CliAnalysisSessionProvider.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10CliAnalysisSessionProvider.kt index f05234e36ce..1eec54ae870 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10CliAnalysisSessionProvider.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/KtFe10CliAnalysisSessionProvider.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisSessionProvider import org.jetbrains.kotlin.analysis.api.descriptors.symbols.base.KtFe10Symbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.analysis.api.tokens.ValidityTokenFactory +import org.jetbrains.kotlin.analysis.project.structure.getKtModule import org.jetbrains.kotlin.psi.KtElement import java.lang.UnsupportedOperationException @@ -24,7 +25,7 @@ class KtFe10AnalysisSessionProvider : KtAnalysisSessionProvider() { @InvalidWayOfUsingAnalysisSession override fun getAnalysisSessionBySymbol(contextSymbol: KtSymbol): KtAnalysisSession { if (contextSymbol is KtFe10Symbol) { - return KtFe10AnalysisSession(contextSymbol.analysisContext) + return KtFe10AnalysisSession(contextSymbol.analysisContext, contextSymbol.analysisContext.contextElement.getKtModule()) } else { val contextElement = contextSymbol.psi if (contextElement is KtElement) { 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 dd5eae6742a..692b3e1ab4f 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 @@ -13,9 +13,11 @@ import org.jetbrains.kotlin.analysis.api.fir.components.* import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirOverrideInfoProvider import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbolProvider import org.jetbrains.kotlin.analysis.api.fir.utils.threadLocal +import org.jetbrains.kotlin.analysis.api.impl.base.components.KtAnalysisScopeProviderImpl import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir +import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.resolve.ScopeSession @@ -34,6 +36,8 @@ private constructor( private val mode: AnalysisSessionMode, ) : KtAnalysisSession(token) { + override val useSiteModule: KtModule get() = firResolveState.module + private enum class AnalysisSessionMode { REGULAR, DEPENDENT_COPY @@ -92,6 +96,8 @@ private constructor( override val typesCreatorImpl: KtTypeCreator = KtFirTypeCreator(this, token) + override val analysisScopeProviderImpl: KtAnalysisScopeProvider = KtAnalysisScopeProviderImpl(this, token) + override fun createContextDependentCopy(originalKtFile: KtFile, elementToReanalyze: KtElement): KtAnalysisSession { check(mode == AnalysisSessionMode.REGULAR) { "Cannot create context-dependent copy of KtAnalysis session from a context dependent one" 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 new file mode 100644 index 00000000000..df49656c605 --- /dev/null +++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/KtAnalysisScopeProviderImpl.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.impl.base.components + +import com.intellij.psi.PsiElement +import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession +import org.jetbrains.kotlin.analysis.api.components.KtAnalysisScopeProvider +import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.project.structure.allDirectDependencies +import org.jetbrains.kotlin.psi.psiUtil.contains + +class KtAnalysisScopeProviderImpl( + override val analysisSession: KtAnalysisSession, + override val token: ValidityToken +) : KtAnalysisScopeProvider() { + + private val allModules = analysisSession.useSiteModule.collectAllDependenciesWithSelf() + private val analysisScope = GlobalSearchScope.union(allModules.map { it.contentScope }) + + override fun getAnalysisScope(): GlobalSearchScope = analysisScope + + override fun canBeAnalysed(psi: PsiElement): Boolean { + return analysisScope.contains(psi) + } +} + +private fun KtModule.collectAllDependenciesWithSelf(): List { + val stack = mutableListOf(this) + val visited = mutableSetOf() + + while (stack.isNotEmpty()) { + val current = stack.removeLast() + if (visited.add(current)) continue + + current.allDirectDependencies().forEach { dependency -> + if (dependency !in visited) stack += dependency + } + } + + return visited.toList() +} \ No newline at end of file diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/KtAnalysisSession.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/KtAnalysisSession.kt index 9e07a513aa7..efb5895f05b 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/KtAnalysisSession.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/KtAnalysisSession.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolProvider import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolProviderMixIn import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken +import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile @@ -53,7 +54,10 @@ public abstract class KtAnalysisSession(final override val token: ValidityToken) KtVisibilityCheckerMixIn, KtMemberSymbolProviderMixin, KtInheritorsProviderMixIn, - KtTypeCreatorMixIn { + KtTypeCreatorMixIn, + KtAnalysisScopeProviderMixIn { + + public abstract val useSiteModule: KtModule override val analysisSession: KtAnalysisSession get() = this @@ -131,6 +135,9 @@ public abstract class KtAnalysisSession(final override val token: ValidityToken) internal val symbolInfoProvider: KtSymbolInfoProvider get() = symbolInfoProviderImpl protected abstract val symbolInfoProviderImpl: KtSymbolInfoProvider + internal val analysisScopeProvider: KtAnalysisScopeProvider get() = analysisScopeProviderImpl + protected abstract val analysisScopeProviderImpl: KtAnalysisScopeProvider + @PublishedApi internal val typesCreator: KtTypeCreator get() = typesCreatorImpl diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtAnalysisScopeProvider.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtAnalysisScopeProvider.kt new file mode 100644 index 00000000000..cf23fdfd332 --- /dev/null +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtAnalysisScopeProvider.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.components + +import com.intellij.psi.PsiElement +import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.analysis.api.KtAnalysisSession + +public abstract class KtAnalysisScopeProvider : KtAnalysisSessionComponent() { + public abstract fun getAnalysisScope(): GlobalSearchScope + + public abstract fun canBeAnalysed(psi: PsiElement): Boolean +} + +public interface KtAnalysisScopeProviderMixIn : KtAnalysisSessionMixIn { + /** + * Return [GlobalSearchScope] represent a scope code in which can be analysed by current [KtAnalysisSession]. + * That means [org.jetbrains.kotlin.analysis.api.symbols.KtSymbol] can be built for the declarations from this scope. + */ + public val analysisScope: GlobalSearchScope + get() = analysisSession.analysisScopeProvider.getAnalysisScope() + + + /** + * Checks if [PsiElement] is inside analysis scope. + * That means [org.jetbrains.kotlin.analysis.api.symbols.KtSymbol] can be built by this [PsiElement] + * + * @see analysisScope + */ + public fun PsiElement.canBeAnalysed(): Boolean = + analysisSession.analysisScopeProvider.canBeAnalysed(this) +} \ No newline at end of file