[kotlin fir] fix creating symbol not in analysis scope

^KTIJ-21504 fixed
This commit is contained in:
Ilya Kirillov
2022-04-19 13:17:28 +02:00
parent 25d6439471
commit 3b4eb2d788
7 changed files with 113 additions and 7 deletions
@@ -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)
@@ -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)
@@ -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) {
@@ -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"
@@ -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<KtModule> {
val stack = mutableListOf(this)
val visited = mutableSetOf<KtModule>()
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()
}
@@ -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
@@ -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)
}