Analysis API FIR: introduce declarations from library resolve
^KT-50252 fixed
This commit is contained in:
+6
-4
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
|
||||
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir.getTowerContextProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirOfType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.ResolutionParameters
|
||||
@@ -61,7 +60,7 @@ internal class KtFirCompletionCandidateChecker(
|
||||
val file = originalFile.getOrBuildFirFile(firResolveState)
|
||||
val explicitReceiverExpression = possibleExplicitReceiver?.getOrBuildFirOfType<FirExpression>(firResolveState)
|
||||
val resolver = SingleCandidateResolver(firResolveState.rootModuleSession, file)
|
||||
val implicitReceivers = getImplicitReceivers(nameExpression)
|
||||
val implicitReceivers = getImplicitReceivers(originalFile, nameExpression)
|
||||
for (implicitReceiverValue in implicitReceivers) {
|
||||
val resolutionParameters = ResolutionParameters(
|
||||
singleCandidateResolutionMode = SingleCandidateResolutionMode.CHECK_EXTENSION_FOR_COMPLETION,
|
||||
@@ -84,8 +83,11 @@ internal class KtFirCompletionCandidateChecker(
|
||||
return KtExtensionApplicabilityResult.NonApplicable(KtSubstitutor.Empty(token))
|
||||
}
|
||||
|
||||
private fun getImplicitReceivers(fakeNameExpression: KtSimpleNameExpression): Sequence<ImplicitReceiverValue<*>?> {
|
||||
val towerDataContext = analysisSession.firResolveState.getTowerContextProvider()
|
||||
private fun getImplicitReceivers(
|
||||
originalFile: KtFile,
|
||||
fakeNameExpression: KtSimpleNameExpression
|
||||
): Sequence<ImplicitReceiverValue<*>?> {
|
||||
val towerDataContext = analysisSession.firResolveState.getTowerContextProvider(originalFile)
|
||||
.getClosestAvailableParentContext(fakeNameExpression)
|
||||
?: error("Cannot find enclosing declaration for ${fakeNameExpression.getElementTextInContext()}")
|
||||
|
||||
|
||||
+1
-3
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir.getTowerContextProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
@@ -189,9 +188,8 @@ internal class KtFirScopeProvider(
|
||||
originalFile: KtFile,
|
||||
positionInFakeFile: KtElement
|
||||
): KtScopeContext = withValidityAssertion {
|
||||
|
||||
val towerDataContext =
|
||||
analysisSession.firResolveState.getTowerContextProvider().getClosestAvailableParentContext(positionInFakeFile)
|
||||
analysisSession.firResolveState.getTowerContextProvider(originalFile).getClosestAvailableParentContext(positionInFakeFile)
|
||||
?: error("Cannot find enclosing declaration for ${positionInFakeFile.getElementTextInContext()}")
|
||||
|
||||
val implicitReceivers = towerDataContext.nonLocalTowerDataElements.mapNotNull { it.implicitReceiver }.distinct()
|
||||
|
||||
+1
-3
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir.getTowerContextProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
||||
import org.jetbrains.kotlin.fir.FirRenderer
|
||||
@@ -28,7 +27,6 @@ import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker.isCompatible
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.typeParameterSymbols
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
||||
@@ -124,7 +122,7 @@ internal class KtFirTypeProvider(
|
||||
}
|
||||
|
||||
override fun getImplicitReceiverTypesAtPosition(position: KtElement): List<KtType> {
|
||||
return analysisSession.firResolveState.getTowerContextProvider()
|
||||
return analysisSession.firResolveState.getTowerContextProvider(position.containingKtFile)
|
||||
.getClosestAvailableParentContext(position)?.implicitReceiverStack?.map { it.type.asKtType() } ?: emptyList()
|
||||
}
|
||||
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* 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.utils.errors
|
||||
|
||||
public fun unexpectedElementError(elementName: String, element: Any?): Nothing {
|
||||
error("Unexpected $elementName ${element?.let { it::class.simpleName }}")
|
||||
}
|
||||
+35
-14
@@ -13,7 +13,13 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSessionProviderStorage
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSourcesSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibraryOrLibrarySourceResolvableModuleSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.FirSourceModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirLibraryOrLibrarySourceResolvableModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
|
||||
@@ -27,10 +33,10 @@ internal class FirIdeResolveStateService(project: Project) {
|
||||
project.createProjectWideOutOfBlockModificationTracker(),
|
||||
ProjectRootModificationTracker.getInstance(project),
|
||||
) {
|
||||
ConcurrentHashMap<KtModule, FirSourceModuleResolveState>()
|
||||
ConcurrentHashMap<KtModule, LLFirResolvableModuleResolveState>()
|
||||
}
|
||||
|
||||
fun getResolveState(module: KtModule): FirSourceModuleResolveState =
|
||||
fun getResolveState(module: KtModule): LLFirResolvableModuleResolveState =
|
||||
stateCache.computeIfAbsent(module) { createResolveStateFor(module, sessionProviderStorage) }
|
||||
|
||||
companion object {
|
||||
@@ -41,19 +47,34 @@ internal class FirIdeResolveStateService(project: Project) {
|
||||
module: KtModule,
|
||||
sessionProviderStorage: FirIdeSessionProviderStorage,
|
||||
configureSession: (FirIdeSession.() -> Unit)? = null,
|
||||
): FirSourceModuleResolveState {
|
||||
if (module !is KtSourceModule) {
|
||||
error("Creating FirModuleResolveState is not yet supported for $module")
|
||||
}
|
||||
): LLFirResolvableModuleResolveState {
|
||||
val sessionProvider = sessionProviderStorage.getSessionProvider(module, configureSession)
|
||||
val firFileBuilder = sessionProvider.rootModuleSession.firFileBuilder
|
||||
return FirSourceModuleResolveState(
|
||||
sessionProviderStorage.project,
|
||||
module,
|
||||
sessionProvider,
|
||||
firFileBuilder,
|
||||
FirLazyDeclarationResolver(firFileBuilder),
|
||||
)
|
||||
return when (module) {
|
||||
is KtSourceModule -> {
|
||||
val firFileBuilder = (sessionProvider.rootModuleSession as FirIdeSourcesSession).firFileBuilder
|
||||
FirSourceModuleResolveState(
|
||||
sessionProviderStorage.project,
|
||||
module,
|
||||
sessionProvider,
|
||||
firFileBuilder,
|
||||
FirLazyDeclarationResolver(firFileBuilder),
|
||||
)
|
||||
}
|
||||
is KtLibraryModule, is KtLibrarySourceModule -> {
|
||||
val firFileBuilder = (sessionProvider.rootModuleSession as LLFirLibraryOrLibrarySourceResolvableModuleSession).firFileBuilder
|
||||
LLFirLibraryOrLibrarySourceResolvableModuleResolveState(
|
||||
sessionProviderStorage.project,
|
||||
module,
|
||||
sessionProvider,
|
||||
firFileBuilder,
|
||||
FirLazyDeclarationResolver(firFileBuilder),
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
error("Unexpected $module")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-17
@@ -8,10 +8,13 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirElementBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.KtToFirMapping
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.FirSourceModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.TowerProviderForElementForState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.containingKtFileIfAny
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalKtFile
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
@@ -28,35 +31,21 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||
|
||||
internal class FirModuleResolveStateDepended(
|
||||
val originalState: FirSourceModuleResolveState,
|
||||
val originalState: LLFirResolvableModuleResolveState,
|
||||
val towerProviderBuiltUponElement: FirTowerContextProvider,
|
||||
private val ktToFirMapping: KtToFirMapping?,
|
||||
) : FirModuleResolveState() {
|
||||
|
||||
override val project: Project get() = originalState.project
|
||||
override val module: KtModule get() = originalState.module
|
||||
override val rootModuleSession get() = originalState.rootModuleSession
|
||||
private val fileStructureCache get() = originalState.fileStructureCache
|
||||
|
||||
override fun getSessionFor(module: KtModule): FirSession =
|
||||
originalState.getSessionFor(module)
|
||||
|
||||
override fun getOrBuildFirFor(element: KtElement): FirElement? {
|
||||
val elementBuilder = originalState.elementBuilder
|
||||
|
||||
val psi = elementBuilder.getPsiAsFirElementSource(element) ?: return null
|
||||
if (!elementBuilder.doKtElementHasCorrespondingFirElement(element)) return null
|
||||
|
||||
val psi = FirElementBuilder.getPsiAsFirElementSource(element) ?: return null
|
||||
ktToFirMapping?.getFirOfClosestParent(psi, this)?.let { return it }
|
||||
|
||||
return elementBuilder.getOrBuildFirFor(
|
||||
element = element,
|
||||
firFileBuilder = originalState.firFileBuilder,
|
||||
moduleFileCache = originalState.rootModuleSession.cache,
|
||||
fileStructureCache = fileStructureCache,
|
||||
firLazyDeclarationResolver = originalState.firLazyDeclarationResolver,
|
||||
state = this,
|
||||
)
|
||||
return originalState.getOrBuildFirFor(element = element)
|
||||
}
|
||||
|
||||
override fun getOrBuildFirFile(ktFile: KtFile): FirFile =
|
||||
@@ -82,4 +71,7 @@ internal class FirModuleResolveStateDepended(
|
||||
override fun resolveToFirSymbol(ktDeclaration: KtDeclaration, phase: FirResolvePhase): FirBasedSymbol<*> {
|
||||
return originalState.resolveToFirSymbol(ktDeclaration, phase)
|
||||
}
|
||||
|
||||
override fun getTowerContextProvider(ktFile: KtFile): FirTowerContextProvider =
|
||||
TowerProviderForElementForState(this)
|
||||
}
|
||||
|
||||
+3
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.api
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
@@ -56,4 +57,6 @@ abstract class FirModuleResolveState {
|
||||
abstract fun resolveToFirSymbol(ktDeclaration: KtDeclaration, phase: FirResolvePhase): FirBasedSymbol<*>
|
||||
|
||||
internal abstract fun resolveFirToPhase(declaration: FirDeclaration, toPhase: FirResolvePhase)
|
||||
|
||||
abstract fun getTowerContextProvider(ktFile: KtFile): FirTowerContextProvider
|
||||
}
|
||||
|
||||
+18
-32
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.analysis.api.impl.barebone.parentOfType
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentsOfType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.DeclarationCopyBuilder.withBodyFrom
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.FirModuleResolveStateDepended
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.FirSourceModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FileTowerProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerDataContextAllElementsCollector
|
||||
@@ -18,8 +17,8 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.runCustomRes
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FirElementsRecorder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.KtToFirMapping
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.*
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSourcesSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
|
||||
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
||||
@@ -31,6 +30,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTypeResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
|
||||
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -67,7 +67,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
place: T,
|
||||
elementToResolve: T,
|
||||
): FirElement {
|
||||
require(state is FirSourceModuleResolveState)
|
||||
require(state is LLFirResolvableModuleResolveState)
|
||||
require(place.isPhysical)
|
||||
|
||||
val declaration = runBodyResolveOnAir(
|
||||
@@ -95,7 +95,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
state: FirModuleResolveState,
|
||||
place: KtElement,
|
||||
): FirTowerContextProvider {
|
||||
require(state is FirSourceModuleResolveState)
|
||||
require(state is LLFirResolvableModuleResolveState)
|
||||
|
||||
return if (place is KtFile) {
|
||||
FileTowerProvider(place, onAirGetTowerContextForFile(state, place))
|
||||
@@ -116,11 +116,11 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
}
|
||||
|
||||
private fun onAirGetTowerContextForFile(
|
||||
state: FirSourceModuleResolveState,
|
||||
state: LLFirResolvableModuleResolveState,
|
||||
file: KtFile,
|
||||
): FirTowerDataContext {
|
||||
require(file.isPhysical)
|
||||
val session = state.getSessionFor(file.getKtModule(state.project)) as FirIdeSourcesSession
|
||||
val session = state.getSessionFor(file.getKtModule(state.project)) as LLFirResolvableModuleSession
|
||||
|
||||
val firFile = session.firFileBuilder.buildRawFirFileWithCaching(
|
||||
ktFile = file,
|
||||
@@ -144,7 +144,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
originalKtFile: KtFile,
|
||||
elementToAnalyze: KtElement
|
||||
): FirModuleResolveState {
|
||||
require(originalState is FirSourceModuleResolveState)
|
||||
require(originalState is LLFirResolvableModuleResolveState)
|
||||
require(elementToAnalyze !is KtFile) { "KtFile for dependency element not supported" }
|
||||
require(!elementToAnalyze.isPhysical) { "Depended state should be build only for non-physical elements" }
|
||||
|
||||
@@ -178,21 +178,21 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
|
||||
private fun tryResolveAsFileAnnotation(
|
||||
annotationEntry: KtAnnotationEntry,
|
||||
state: FirSourceModuleResolveState,
|
||||
state: LLFirResolvableModuleResolveState,
|
||||
replacement: RawFirReplacement,
|
||||
firFile: FirFile,
|
||||
collector: FirTowerDataContextCollector? = null,
|
||||
): FirAnnotation {
|
||||
val annotationCall = buildFileFirAnnotation(
|
||||
session = firFile.moduleData.session,
|
||||
baseScopeProvider = firFile.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
||||
baseScopeProvider = firFile.moduleData.session.kotlinScopeProvider,
|
||||
fileAnnotation = annotationEntry,
|
||||
replacement = replacement
|
||||
)
|
||||
state.firLazyDeclarationResolver.resolveFileAnnotations(
|
||||
firFile = firFile,
|
||||
annotations = listOf(annotationCall),
|
||||
moduleFileCache = state.rootModuleSession.cache,
|
||||
moduleFileCache = state.cache,
|
||||
scopeSession = ScopeSession(),
|
||||
checkPCE = true,
|
||||
collector = collector
|
||||
@@ -202,7 +202,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
}
|
||||
|
||||
private fun runBodyResolveOnAir(
|
||||
state: FirSourceModuleResolveState,
|
||||
state: LLFirResolvableModuleResolveState,
|
||||
replacement: RawFirReplacement,
|
||||
onAirCreatedDeclaration: Boolean,
|
||||
collector: FirTowerDataContextCollector? = null,
|
||||
@@ -233,7 +233,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
|
||||
val newDeclarationWithReplacement = RawFirNonLocalDeclarationBuilder.buildWithReplacement(
|
||||
session = originalDeclaration.moduleData.session,
|
||||
scopeProvider = originalDeclaration.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
||||
scopeProvider = originalDeclaration.moduleData.session.kotlinScopeProvider,
|
||||
designation = originalDesignation,
|
||||
rootNonLocalDeclaration = nonLocalDeclaration,
|
||||
replacement = replacement,
|
||||
@@ -241,7 +241,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
|
||||
val isInBodyReplacement = isInBodyReplacement(nonLocalDeclaration, replacement)
|
||||
|
||||
return state.rootModuleSession.cache.firFileLockProvider.runCustomResolveUnderLock(originalFirFile, true) {
|
||||
return state.cache.firFileLockProvider.runCustomResolveUnderLock(originalFirFile, true) {
|
||||
val copiedFirDeclaration = if (isInBodyReplacement) {
|
||||
when (originalDeclaration) {
|
||||
is FirSimpleFunction ->
|
||||
@@ -263,7 +263,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
ResolveTreeBuilder.resolveEnsure(onAirDesignation.declaration, FirResolvePhase.BODY_RESOLVE) {
|
||||
state.firLazyDeclarationResolver.runLazyDesignatedOnAirResolveToBodyWithoutLock(
|
||||
designation = onAirDesignation,
|
||||
moduleFileCache = state.rootModuleSession.cache,
|
||||
moduleFileCache = state.cache,
|
||||
checkPCE = true,
|
||||
onAirCreatedDeclaration = onAirCreatedDeclaration,
|
||||
towerDataContextCollector = collector,
|
||||
@@ -299,16 +299,16 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
fun onAirResolveTypeInPlace(
|
||||
place: KtElement,
|
||||
typeReference: KtTypeReference,
|
||||
state: FirModuleResolveState
|
||||
state: FirModuleResolveState,
|
||||
): FirResolvedTypeRef {
|
||||
val context = state.getTowerContextProvider().getClosestAvailableParentContext(place)
|
||||
val context = state.getTowerContextProvider(place.containingKtFile).getClosestAvailableParentContext(place)
|
||||
?: error("TowerContext not found for ${place.getElementTextInContext()}")
|
||||
|
||||
val session = state.rootModuleSession
|
||||
val firTypeReference = buildFirUserTypeRef(
|
||||
typeReference = typeReference,
|
||||
session = session,
|
||||
baseScopeProvider = session.firIdeProvider.kotlinScopeProvider
|
||||
baseScopeProvider = session.kotlinScopeProvider
|
||||
)
|
||||
|
||||
return FirTypeResolveTransformer(
|
||||
@@ -317,18 +317,4 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
initialScopes = context.towerDataElements.asReversed().mapNotNull { it.scope }
|
||||
).transformTypeRef(firTypeReference, null)
|
||||
}
|
||||
|
||||
private class TowerProviderForElementForState(private val state: FirModuleResolveState) : FirTowerContextProvider {
|
||||
override fun getClosestAvailableParentContext(ktElement: KtElement): FirTowerDataContext? {
|
||||
return if (state is FirModuleResolveStateDepended) {
|
||||
state.towerProviderBuiltUponElement.getClosestAvailableParentContext(ktElement)
|
||||
?: onAirGetTowerContextProvider(state.originalState, ktElement).getClosestAvailableParentContext(ktElement)
|
||||
} else {
|
||||
onAirGetTowerContextProvider(state, ktElement).getClosestAvailableParentContext(ktElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun FirModuleResolveState.getTowerContextProvider(): FirTowerContextProvider =
|
||||
TowerProviderForElementForState(this)
|
||||
}
|
||||
|
||||
+22
-19
@@ -32,29 +32,32 @@ import org.jetbrains.kotlin.psi2ir.deparenthesize
|
||||
*/
|
||||
@ThreadSafe
|
||||
internal class FirElementBuilder {
|
||||
fun getPsiAsFirElementSource(element: KtElement): KtElement? {
|
||||
val deparenthesized = if (element is KtPropertyDelegate) element.deparenthesize() else element
|
||||
return when {
|
||||
deparenthesized is KtParenthesizedExpression -> deparenthesized.deparenthesize()
|
||||
deparenthesized is KtPropertyDelegate -> deparenthesized.expression ?: element
|
||||
deparenthesized is KtQualifiedExpression && deparenthesized.selectorExpression is KtCallExpression -> {
|
||||
/*
|
||||
KtQualifiedExpression with KtCallExpression in selector transformed in FIR to FirFunctionCall expression
|
||||
Which will have a receiver as qualifier
|
||||
*/
|
||||
deparenthesized.selectorExpression ?: error("Incomplete code:\n${element.getElementTextInContext()}")
|
||||
companion object {
|
||||
fun getPsiAsFirElementSource(element: KtElement): KtElement? {
|
||||
val deparenthesized = if (element is KtPropertyDelegate) element.deparenthesize() else element
|
||||
return when {
|
||||
deparenthesized is KtParenthesizedExpression -> deparenthesized.deparenthesize()
|
||||
deparenthesized is KtPropertyDelegate -> deparenthesized.expression ?: element
|
||||
deparenthesized is KtQualifiedExpression && deparenthesized.selectorExpression is KtCallExpression -> {
|
||||
/*
|
||||
KtQualifiedExpression with KtCallExpression in selector transformed in FIR to FirFunctionCall expression
|
||||
Which will have a receiver as qualifier
|
||||
*/
|
||||
deparenthesized.selectorExpression ?: error("Incomplete code:\n${element.getElementTextInContext()}")
|
||||
}
|
||||
deparenthesized is KtValueArgument -> {
|
||||
// null will be return in case of invalid KtValueArgument
|
||||
deparenthesized.getArgumentExpression()
|
||||
}
|
||||
deparenthesized is KtObjectLiteralExpression -> deparenthesized.objectDeclaration
|
||||
deparenthesized is KtStringTemplateEntryWithExpression -> deparenthesized.expression
|
||||
deparenthesized is KtUserType && deparenthesized.parent is KtNullableType -> deparenthesized.parent as KtNullableType
|
||||
else -> deparenthesized
|
||||
}
|
||||
deparenthesized is KtValueArgument -> {
|
||||
// null will be return in case of invalid KtValueArgument
|
||||
deparenthesized.getArgumentExpression()
|
||||
}
|
||||
deparenthesized is KtObjectLiteralExpression -> deparenthesized.objectDeclaration
|
||||
deparenthesized is KtStringTemplateEntryWithExpression -> deparenthesized.expression
|
||||
deparenthesized is KtUserType && deparenthesized.parent is KtNullableType -> deparenthesized.parent as KtNullableType
|
||||
else -> deparenthesized
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun doKtElementHasCorrespondingFirElement(ktElement: KtElement): Boolean = when (ktElement) {
|
||||
is KtImportList -> false
|
||||
else -> true
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.file.builder
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.FirPhaseRunner
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerDataContextAllElementsCollector
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FirElementsRecorder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.KtToFirMapping
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibraryOrLibrarySourceResolvableModuleSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
internal class LLFirLibraryResolveModuleFileCache(
|
||||
val kotlinScopeProvider: FirScopeProvider,
|
||||
override val session: LLFirLibraryOrLibrarySourceResolvableModuleSession
|
||||
) : ModuleFileCache() {
|
||||
private val firFileBuilder = FirFileBuilder(kotlinScopeProvider, FirPhaseRunner())
|
||||
|
||||
private val firLazyDeclarationResolver = FirLazyDeclarationResolver(firFileBuilder)
|
||||
|
||||
private val kfFileToFirCache = ConcurrentHashMap<KtFile, ResolvedFile>()
|
||||
|
||||
override val classifierByClassId: ConcurrentHashMap<ClassId, Optional<FirClassLikeDeclaration>> get() = error("Should not be called")
|
||||
override val callableByCallableId: ConcurrentHashMap<CallableId, List<FirCallableSymbol<*>>> get() = error("Should not be called")
|
||||
|
||||
override fun fileCached(file: KtFile, createValue: () -> FirFile): FirFile {
|
||||
return getResolvedFile(file) { createValue() }.firFile
|
||||
}
|
||||
|
||||
override fun getContainerFirFile(declaration: FirDeclaration): FirFile? {
|
||||
val ktFile = declaration.psi?.containingFile as? KtFile ?: return null
|
||||
return getCachedFirFile(ktFile)
|
||||
}
|
||||
|
||||
override fun getCachedFirFile(ktFile: KtFile): FirFile? {
|
||||
return kfFileToFirCache[ktFile]?.firFile
|
||||
}
|
||||
|
||||
override val firFileLockProvider: LockProvider<FirFile> = LockProvider()
|
||||
|
||||
fun getResolvedFile(
|
||||
ktFile: KtFile,
|
||||
createKtFile: (KtFile) -> FirFile
|
||||
): ResolvedFile = kfFileToFirCache.computeIfAbsent(ktFile) {
|
||||
val collector = FirTowerDataContextAllElementsCollector()
|
||||
val scopeSession = ScopeSession()
|
||||
|
||||
val firFile = createKtFile(ktFile)
|
||||
|
||||
firLazyDeclarationResolver.lazyResolveFileDeclaration(
|
||||
firFile,
|
||||
this,
|
||||
FirResolvePhase.BODY_RESOLVE,
|
||||
scopeSession,
|
||||
collector = collector,
|
||||
checkPCE = true
|
||||
)
|
||||
|
||||
ResolvedFile(
|
||||
firFile,
|
||||
KtToFirMapping(firFile, FirElementsRecorder()),
|
||||
collector
|
||||
)
|
||||
}
|
||||
|
||||
class ResolvedFile(
|
||||
val firFile: FirFile,
|
||||
val mapping: KtToFirMapping,
|
||||
val collector: FirTowerDataContextAllElementsCollector,
|
||||
)
|
||||
}
|
||||
+4
-4
@@ -11,13 +11,14 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLoc
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.FirIdeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@@ -40,7 +41,7 @@ internal class FileStructure private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private val firIdeProvider = firFile.moduleData.session.firIdeProvider
|
||||
private val firProvider = firFile.moduleData.session.firProvider
|
||||
|
||||
private val structureElements = ConcurrentHashMap<KtAnnotated, FileStructureElement>()
|
||||
|
||||
@@ -59,7 +60,6 @@ internal class FileStructure private constructor(
|
||||
newKtDeclaration = declaration as KtDeclaration,
|
||||
cache = moduleFileCache,
|
||||
firLazyDeclarationResolver = firLazyDeclarationResolver,
|
||||
firIdeProvider = firIdeProvider,
|
||||
)
|
||||
}
|
||||
else -> structureElement
|
||||
@@ -112,7 +112,7 @@ internal class FileStructure private constructor(
|
||||
private fun createDeclarationStructure(declaration: KtDeclaration): FileStructureElement {
|
||||
val firDeclaration = declaration.findSourceNonLocalFirDeclaration(
|
||||
firFileBuilder,
|
||||
firIdeProvider.symbolProvider,
|
||||
firProvider.symbolProvider,
|
||||
moduleFileCache,
|
||||
firFile
|
||||
)
|
||||
|
||||
+5
-10
@@ -18,11 +18,12 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDecla
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.RawFirNonLocalDeclarationBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.FirIdeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableModuleResolveState
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
@@ -36,12 +37,10 @@ internal sealed class FileStructureElement(val firFile: FirFile, protected val l
|
||||
}
|
||||
|
||||
internal class KtToFirMapping(firElement: FirElement, recorder: FirElementsRecorder) {
|
||||
|
||||
private val mapping = FirElementsRecorder.recordElementsFrom(firElement, recorder)
|
||||
|
||||
private val userTypeMapping = ConcurrentHashMap<KtUserType, FirElement>()
|
||||
fun getElement(ktElement: KtElement, state: FirModuleResolveState): FirElement? {
|
||||
|
||||
fun getElement(ktElement: KtElement, state: FirModuleResolveState): FirElement? {
|
||||
mapping[ktElement]?.let { return it }
|
||||
|
||||
val userType = when (ktElement) {
|
||||
@@ -87,7 +86,6 @@ internal sealed class ReanalyzableStructureElement<KT : KtDeclaration, S : FirBa
|
||||
newKtDeclaration: KT,
|
||||
cache: ModuleFileCache,
|
||||
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
||||
firIdeProvider: FirIdeProvider,
|
||||
): ReanalyzableStructureElement<KT, S>
|
||||
|
||||
fun isUpToDate(): Boolean = psi.getModificationStamp() == timestamp
|
||||
@@ -116,20 +114,18 @@ internal class ReanalyzableFunctionStructureElement(
|
||||
newKtDeclaration: KtNamedFunction,
|
||||
cache: ModuleFileCache,
|
||||
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
||||
firIdeProvider: FirIdeProvider,
|
||||
): ReanalyzableFunctionStructureElement {
|
||||
val originalFunction = firSymbol.fir as FirSimpleFunction
|
||||
val designation = originalFunction.collectDesignation()
|
||||
|
||||
val temporaryFunction = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
||||
session = originalFunction.moduleData.session,
|
||||
scopeProvider = originalFunction.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
||||
scopeProvider = originalFunction.moduleData.session.kotlinScopeProvider,
|
||||
designation = designation,
|
||||
rootNonLocalDeclaration = newKtDeclaration,
|
||||
) as FirSimpleFunction
|
||||
|
||||
return cache.firFileLockProvider.withWriteLock(firFile) {
|
||||
|
||||
val upgradedPhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS)
|
||||
with(originalFunction) {
|
||||
replaceBody(temporaryFunction.body)
|
||||
@@ -172,14 +168,13 @@ internal class ReanalyzablePropertyStructureElement(
|
||||
newKtDeclaration: KtProperty,
|
||||
cache: ModuleFileCache,
|
||||
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
||||
firIdeProvider: FirIdeProvider,
|
||||
): ReanalyzablePropertyStructureElement {
|
||||
val originalProperty = firSymbol.fir
|
||||
val designation = originalProperty.collectDesignation()
|
||||
|
||||
val temporaryProperty = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
||||
session = originalProperty.moduleData.session,
|
||||
scopeProvider = originalProperty.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
||||
scopeProvider = originalProperty.moduleData.session.kotlinScopeProvider,
|
||||
designation = designation,
|
||||
rootNonLocalDeclaration = newKtDeclaration,
|
||||
) as FirProperty
|
||||
|
||||
+4
-4
@@ -9,7 +9,6 @@ import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignation
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.getExplicitBackingField
|
||||
@@ -18,6 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirLazyBlock
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirLazyExpression
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
@@ -41,7 +41,7 @@ internal object FirLazyBodiesCalculator {
|
||||
if (simpleFunction.body !is FirLazyBlock) return
|
||||
val newFunction = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
||||
session = simpleFunction.moduleData.session,
|
||||
scopeProvider = simpleFunction.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
||||
scopeProvider = simpleFunction.moduleData.session.kotlinScopeProvider,
|
||||
designation = designation,
|
||||
rootNonLocalDeclaration = simpleFunction.psi as KtNamedFunction,
|
||||
) as FirSimpleFunction
|
||||
@@ -58,7 +58,7 @@ internal object FirLazyBodiesCalculator {
|
||||
|
||||
val newFunction = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
||||
session = secondaryConstructor.moduleData.session,
|
||||
scopeProvider = secondaryConstructor.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
||||
scopeProvider = secondaryConstructor.moduleData.session.kotlinScopeProvider,
|
||||
designation = designation,
|
||||
rootNonLocalDeclaration = secondaryConstructor.psi as KtSecondaryConstructor,
|
||||
) as FirSimpleFunction
|
||||
@@ -74,7 +74,7 @@ internal object FirLazyBodiesCalculator {
|
||||
|
||||
val newProperty = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
||||
session = firProperty.moduleData.session,
|
||||
scopeProvider = firProperty.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
||||
scopeProvider = firProperty.moduleData.session.kotlinScopeProvider,
|
||||
designation = designation,
|
||||
rootNonLocalDeclaration = firProperty.psi as KtProperty
|
||||
) as FirProperty
|
||||
|
||||
+5
-4
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLoc
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.runCustomResolveUnderLock
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.FirFileAnnotationsResolveTransformer
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.FirProviderInterceptorForIDE
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LazyTransformerFactory
|
||||
@@ -114,6 +113,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
||||
moduleFileCache: ModuleFileCache,
|
||||
toPhase: FirResolvePhase,
|
||||
scopeSession: ScopeSession,
|
||||
collector: FirTowerDataContextCollector? = null,
|
||||
checkPCE: Boolean = false,
|
||||
) {
|
||||
if (toPhase == FirResolvePhase.RAW_FIR) return
|
||||
@@ -126,6 +126,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
||||
firFile = firFile,
|
||||
moduleFileCache = moduleFileCache,
|
||||
toPhase = toPhase,
|
||||
collector = collector,
|
||||
scopeSession = scopeSession,
|
||||
checkPCE = checkPCE,
|
||||
)
|
||||
@@ -185,7 +186,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
||||
scopeSession = scopeSession,
|
||||
moduleFileCache = moduleFileCache,
|
||||
lazyDeclarationResolver = this,
|
||||
towerDataContextCollector = null,
|
||||
towerDataContextCollector = collector,
|
||||
firProviderInterceptor = null,
|
||||
checkPCE = checkPCE,
|
||||
)
|
||||
@@ -298,14 +299,14 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
||||
|
||||
declarationToResolve = enumEntry.findSourceNonLocalFirDeclaration(
|
||||
firFileBuilder,
|
||||
firDeclarationToResolve.moduleData.session.firIdeProvider.symbolProvider,
|
||||
firDeclarationToResolve.moduleData.session.firProvider.symbolProvider,
|
||||
moduleFileCache
|
||||
)
|
||||
neededPhase = FirResolvePhase.BODY_RESOLVE
|
||||
} else {
|
||||
declarationToResolve = nonLocalDeclaration.findSourceNonLocalFirDeclaration(
|
||||
firFileBuilder,
|
||||
firDeclarationToResolve.moduleData.session.firIdeProvider.symbolProvider,
|
||||
firDeclarationToResolve.moduleData.session.firProvider.symbolProvider,
|
||||
moduleFileCache
|
||||
)
|
||||
neededPhase = toPhase
|
||||
|
||||
+1
@@ -30,3 +30,4 @@ internal class FirIdeLibrariesSessionProvider(
|
||||
|
||||
private fun shouldNotBeCalled(): Nothing = error("Should not be called for FirIdeLibrariesSessionProvider")
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -124,5 +124,3 @@ internal class FirIdeProvider(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal val FirSession.firIdeProvider: FirIdeProvider by FirSession.sessionComponentAccessor()
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.providers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLibraryResolveModuleFileCache
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.java.deserialization.JvmClassFileBasedSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal class LLFirLibraryResolvableProvider(
|
||||
override val symbolProvider: JvmClassFileBasedSymbolProvider,
|
||||
private val cache: LLFirLibraryResolveModuleFileCache,
|
||||
) : FirProvider() {
|
||||
|
||||
override fun getFirClassifierByFqName(classId: ClassId): FirClassLikeDeclaration? =
|
||||
symbolProvider.getClassLikeSymbolByClassId(classId)?.fir
|
||||
|
||||
override fun getFirClassifierContainerFile(fqName: ClassId): FirFile =
|
||||
getFirClassifierContainerFileIfAny(fqName)!!
|
||||
|
||||
override fun getFirClassifierContainerFileIfAny(fqName: ClassId): FirFile? = null
|
||||
override fun getFirCallableContainerFile(symbol: FirCallableSymbol<*>): FirFile? = null
|
||||
override fun getFirFilesByPackage(fqName: FqName): List<FirFile> = emptyList()
|
||||
|
||||
override fun getClassNamesInPackage(fqName: FqName): Set<Name> = shouldNotBeCalled()
|
||||
|
||||
private fun shouldNotBeCalled(): Nothing = error("Should not be called for FirIdeLibrariesSessionProvider")
|
||||
}
|
||||
+112
-3
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.ProjectScope
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.FirPhaseRunner
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeFirPhaseManager
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeSessionComponents
|
||||
@@ -60,12 +62,12 @@ internal object FirIdeSessionFactory {
|
||||
firPhaseRunner: FirPhaseRunner,
|
||||
sessionInvalidator: FirSessionInvalidator,
|
||||
builtinTypes: BuiltinTypes,
|
||||
sessionsCache: MutableMap<KtSourceModule, FirIdeSourcesSession>,
|
||||
sessionsCache: MutableMap<KtModule, LLFirResolvableModuleSession>,
|
||||
isRootModule: Boolean,
|
||||
librariesCache: LibrariesCache,
|
||||
configureSession: (FirIdeSession.() -> Unit)? = null
|
||||
): FirIdeSourcesSession {
|
||||
sessionsCache[module]?.let { return it }
|
||||
sessionsCache[module]?.let { return it as FirIdeSourcesSession }
|
||||
val languageVersionSettings = module.languageVersionSettings
|
||||
val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
||||
val firBuilder = FirFileBuilder(scopeProvider, firPhaseRunner)
|
||||
@@ -211,7 +213,7 @@ internal object FirIdeSessionFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private fun createModuleDataProvider(sourceModule: KtSourceModule, session: FirIdeSession): ModuleDataProvider {
|
||||
private fun createModuleDataProvider(sourceModule: KtModule, session: FirIdeSession): ModuleDataProvider {
|
||||
val dependencyList = DependencyListForCliModule.build(
|
||||
Name.special("<${sourceModule.moduleDescription}>"),
|
||||
sourceModule.platform,
|
||||
@@ -264,6 +266,113 @@ internal object FirIdeSessionFactory {
|
||||
}
|
||||
}
|
||||
|
||||
fun creatLibraryOrLibrarySourceResolvableSession(
|
||||
project: Project,
|
||||
module: KtModule,
|
||||
builtinsAndCloneableSession: FirIdeBuiltinsAndCloneableSession,
|
||||
firPhaseRunner: FirPhaseRunner,
|
||||
sessionInvalidator: FirSessionInvalidator,
|
||||
builtinTypes: BuiltinTypes,
|
||||
sessionsCache: MutableMap<KtModule, LLFirResolvableModuleSession>,
|
||||
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
|
||||
configureSession: (FirIdeSession.() -> Unit)? = null
|
||||
): LLFirLibraryOrLibrarySourceResolvableModuleSession {
|
||||
LLFirLibraryOrLibrarySourceResolvableModuleSession.checkIsValidKtModule(module)
|
||||
sessionsCache[module]?.let { return it as LLFirLibraryOrLibrarySourceResolvableModuleSession }
|
||||
checkCanceled()
|
||||
|
||||
val libraryModule = when (module) {
|
||||
is KtLibraryModule -> module
|
||||
is KtLibrarySourceModule -> module.binaryLibrary
|
||||
else -> error("Unexpected module ${module::class.simpleName}")
|
||||
}
|
||||
|
||||
|
||||
val scopeProvider = FirKotlinScopeProvider()
|
||||
val firFileBuilder = FirFileBuilder(scopeProvider, firPhaseRunner)
|
||||
val contentScope = module.contentScope
|
||||
val session = LLFirLibraryOrLibrarySourceResolvableModuleSession(module, project, firFileBuilder, builtinTypes)
|
||||
sessionsCache[module] = session
|
||||
|
||||
return session.apply session@{
|
||||
val moduleData = KtModuleBasedModuleData(module).apply { bindSession(this@session) }
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
val cache = ModuleFileCacheImpl(this)
|
||||
val firPhaseManager = IdeFirPhaseManager(FirLazyDeclarationResolver(firFileBuilder), cache, sessionInvalidator)
|
||||
|
||||
registerIdeComponents(project)
|
||||
registerCommonComponents(languageVersionSettings)
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerResolveComponents()
|
||||
|
||||
val provider = FirIdeProvider(
|
||||
project,
|
||||
this,
|
||||
module,
|
||||
scopeProvider,
|
||||
firFileBuilder,
|
||||
cache,
|
||||
project.createDeclarationProvider(contentScope),
|
||||
project.createPackageProvider(contentScope),
|
||||
)
|
||||
|
||||
register(FirProvider::class, provider)
|
||||
register(FirIdeProvider::class, provider)
|
||||
|
||||
register(FirPhaseManager::class, firPhaseManager)
|
||||
val dependentProviders = buildList {
|
||||
val librariesSearchScope = ProjectScope.getLibrariesScope(project)
|
||||
.intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope)) // <all libraries scope> - <current library scope>
|
||||
add(builtinsAndCloneableSession.symbolProvider)
|
||||
add(
|
||||
JvmClassFileBasedSymbolProvider(
|
||||
this@session,
|
||||
moduleDataProvider = createModuleDataProvider(module, this@session),
|
||||
kotlinScopeProvider = scopeProvider,
|
||||
packagePartProvider = project.createPackagePartProviderForLibrary(librariesSearchScope),
|
||||
kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(librariesSearchScope),
|
||||
javaFacade = FirJavaFacade(
|
||||
this@session, moduleData, project.createJavaClassFinder(librariesSearchScope)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val dependencyProvider = DependentModuleProviders(this, dependentProviders)
|
||||
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
FirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOf(
|
||||
provider.symbolProvider,
|
||||
JavaSymbolProvider(
|
||||
this,
|
||||
FirJavaFacade(
|
||||
this, moduleData, project.createJavaClassFinder(contentScope)
|
||||
)
|
||||
),
|
||||
),
|
||||
dependencyProvider
|
||||
)
|
||||
)
|
||||
|
||||
register(FirDependenciesSymbolProvider::class, dependencyProvider)
|
||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||
|
||||
registerJavaSpecificResolveComponents()
|
||||
FirSessionFactory.FirSessionConfigurator(this).apply {
|
||||
for (extensionRegistrar in FirExtensionRegistrar.getInstances(project)) {
|
||||
registerExtensions(extensionRegistrar.configure())
|
||||
}
|
||||
}.configure()
|
||||
configureSession?.invoke(this)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun FirIdeSession.registerIdeComponents(project: Project) {
|
||||
register(IdeSessionComponents::class, IdeSessionComponents.create(this))
|
||||
register(FirCachesFactory::class, FirThreadSafeCachesFactory)
|
||||
|
||||
+4
-4
@@ -17,8 +17,8 @@ import org.jetbrains.kotlin.fir.FirSessionProvider
|
||||
@Immutable
|
||||
class FirIdeSessionProvider internal constructor(
|
||||
val project: Project,
|
||||
internal val rootModuleSession: FirIdeSourcesSession,
|
||||
val sessions: Map<KtSourceModule, FirIdeSession>
|
||||
internal val rootModuleSession: LLFirResolvableModuleSession,
|
||||
val sessions: Map<KtModule, LLFirResolvableModuleSession>
|
||||
) : FirSessionProvider() {
|
||||
override fun getSession(moduleData: FirModuleData): FirSession? =
|
||||
sessions[moduleData.module]
|
||||
@@ -26,6 +26,6 @@ class FirIdeSessionProvider internal constructor(
|
||||
fun getSession(module: KtModule): FirSession? =
|
||||
sessions[module]
|
||||
|
||||
internal fun getModuleCache(module: KtSourceModule): ModuleFileCache =
|
||||
(sessions.getValue(module) as FirIdeSourcesSession).cache
|
||||
internal fun getModuleCache(module: KtModule): ModuleFileCache =
|
||||
sessions.getValue(module).cache
|
||||
}
|
||||
|
||||
+53
-32
@@ -6,51 +6,71 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import kotlinx.collections.immutable.PersistentMap
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
import kotlinx.collections.immutable.toPersistentMap
|
||||
import org.jetbrains.kotlin.analysis.providers.createLibrariesModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.providers.createModuleWithoutDependenciesOutOfBlockModificationTracker
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.moduleData
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.FirPhaseRunner
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.addValueFor
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.executeWithoutPCE
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.analysis.utils.caches.*
|
||||
import org.jetbrains.kotlin.analysis.providers.createLibrariesModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.providers.createModuleWithoutDependenciesOutOfBlockModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.utils.caches.getValue
|
||||
import org.jetbrains.kotlin.analysis.utils.caches.softCachedValue
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.moduleData
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class FirIdeSessionProviderStorage(val project: Project) {
|
||||
private val sessionsCache = ConcurrentHashMap<KtSourceModule, FromModuleViewSessionCache>()
|
||||
private val sessionsCache = ConcurrentHashMap<KtModule, FromModuleViewSessionCache>()
|
||||
|
||||
private val librariesCache by softCachedValue(project, project.createLibrariesModificationTracker()) { LibrariesCache() }
|
||||
|
||||
fun getSessionProvider(
|
||||
rootModule: KtSourceModule,
|
||||
rootModule: KtModule,
|
||||
configureSession: (FirIdeSession.() -> Unit)? = null
|
||||
): FirIdeSessionProvider {
|
||||
val firPhaseRunner = FirPhaseRunner()
|
||||
|
||||
val builtinTypes = BuiltinTypes()
|
||||
val builtinsAndCloneableSession = FirIdeSessionFactory.createBuiltinsAndCloneableSession(project, builtinTypes)
|
||||
val cache = sessionsCache.getOrPut(rootModule) { FromModuleViewSessionCache(rootModule) }
|
||||
val cache = sessionsCache.getOrPut(rootModule) { FromModuleViewSessionCache() }
|
||||
val (sessions, session) = cache.withMappings(project) { mappings ->
|
||||
val sessions = mutableMapOf<KtSourceModule, FirIdeSourcesSession>().apply { putAll(mappings) }
|
||||
val sessions = mutableMapOf<KtModule, LLFirResolvableModuleSession>().apply { putAll(mappings) }
|
||||
val session = executeWithoutPCE {
|
||||
FirIdeSessionFactory.createSourcesSession(
|
||||
project,
|
||||
rootModule,
|
||||
builtinsAndCloneableSession,
|
||||
firPhaseRunner,
|
||||
cache.sessionInvalidator,
|
||||
builtinTypes,
|
||||
sessions,
|
||||
isRootModule = true,
|
||||
librariesCache = librariesCache,
|
||||
configureSession = configureSession,
|
||||
)
|
||||
when (rootModule) {
|
||||
is KtSourceModule -> {
|
||||
FirIdeSessionFactory.createSourcesSession(
|
||||
project,
|
||||
rootModule,
|
||||
builtinsAndCloneableSession,
|
||||
firPhaseRunner,
|
||||
cache.sessionInvalidator,
|
||||
builtinTypes,
|
||||
sessions,
|
||||
isRootModule = true,
|
||||
librariesCache = librariesCache,
|
||||
configureSession = configureSession,
|
||||
)
|
||||
}
|
||||
is KtLibraryModule, is KtLibrarySourceModule -> FirIdeSessionFactory.creatLibraryOrLibrarySourceResolvableSession(
|
||||
project,
|
||||
rootModule,
|
||||
builtinsAndCloneableSession,
|
||||
firPhaseRunner,
|
||||
cache.sessionInvalidator,
|
||||
builtinTypes,
|
||||
sessions,
|
||||
configureSession = configureSession,
|
||||
)
|
||||
else -> error("Unexpected ${rootModule::class.simpleName}")
|
||||
}
|
||||
|
||||
}
|
||||
sessions to session
|
||||
}
|
||||
@@ -59,11 +79,9 @@ class FirIdeSessionProviderStorage(val project: Project) {
|
||||
}
|
||||
}
|
||||
|
||||
private class FromModuleViewSessionCache(
|
||||
val root: KtSourceModule,
|
||||
) {
|
||||
private class FromModuleViewSessionCache {
|
||||
@Volatile
|
||||
private var mappings: PersistentMap<KtSourceModule, FirSessionWithModificationTracker> = persistentMapOf()
|
||||
private var mappings: PersistentMap<KtModule, FirSessionWithModificationTracker> = persistentMapOf()
|
||||
|
||||
val sessionInvalidator: FirSessionInvalidator = FirSessionInvalidator { session ->
|
||||
mappings[session.moduleData.module]?.invalidate()
|
||||
@@ -72,15 +90,15 @@ private class FromModuleViewSessionCache(
|
||||
|
||||
inline fun <R> withMappings(
|
||||
project: Project,
|
||||
action: (Map<KtSourceModule, FirIdeSourcesSession>) -> Pair<Map<KtSourceModule, FirIdeSourcesSession>, R>
|
||||
): Pair<Map<KtSourceModule, FirIdeSourcesSession>, R> {
|
||||
action: (Map<KtModule, LLFirResolvableModuleSession>) -> Pair<Map<KtModule, LLFirResolvableModuleSession>, R>
|
||||
): Pair<Map<KtModule, LLFirResolvableModuleSession>, R> {
|
||||
val (newMappings, result) = action(getSessions().mapValues { it.value })
|
||||
mappings = newMappings.mapValues { FirSessionWithModificationTracker(project, it.value) }.toPersistentMap()
|
||||
return newMappings to result
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun getSessions(): Map<KtSourceModule, FirIdeSourcesSession> = buildMap {
|
||||
private fun getSessions(): Map<KtModule, LLFirResolvableModuleSession> = buildMap {
|
||||
val sessions = mappings.values
|
||||
val wasSessionInvalidated = sessions.associateWithTo(hashMapOf()) { false }
|
||||
|
||||
@@ -122,10 +140,13 @@ private class FromModuleViewSessionCache(
|
||||
|
||||
private class FirSessionWithModificationTracker(
|
||||
project: Project,
|
||||
val firSession: FirIdeSourcesSession,
|
||||
val firSession: LLFirResolvableModuleSession,
|
||||
) {
|
||||
private val modificationTracker =
|
||||
firSession.moduleData.module.createModuleWithoutDependenciesOutOfBlockModificationTracker(project)
|
||||
when (val moduleInfo = firSession.moduleData.module) {
|
||||
is KtSourceModule -> moduleInfo.createModuleWithoutDependenciesOutOfBlockModificationTracker(project)
|
||||
else -> ModificationTracker.NEVER_CHANGED
|
||||
}
|
||||
|
||||
private val timeStamp = modificationTracker.modificationCount
|
||||
|
||||
@@ -139,7 +160,7 @@ private class FirSessionWithModificationTracker(
|
||||
val isValid: Boolean get() = !isInvalidated && modificationTracker.modificationCount == timeStamp
|
||||
}
|
||||
|
||||
internal val FirModuleData.module: KtSourceModule get() = moduleUnsafe()
|
||||
internal val FirModuleData.module: KtModule get() = moduleUnsafe()
|
||||
|
||||
internal inline fun <reified T : KtModule> FirModuleData.moduleUnsafe(): T = (this as KtModuleBasedModuleData).module as T
|
||||
internal inline fun <reified T : KtModule> FirModuleData.moduleInfoSafe(): T? = (this as KtModuleBasedModuleData).module as? T
|
||||
|
||||
+2
-9
@@ -6,21 +6,14 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
|
||||
@OptIn(PrivateSessionConstructor::class)
|
||||
internal class FirIdeSourcesSession @PrivateSessionConstructor constructor(
|
||||
override val module: KtSourceModule,
|
||||
override val project: Project,
|
||||
val firFileBuilder: FirFileBuilder,
|
||||
override val firFileBuilder: FirFileBuilder,
|
||||
builtinTypes: BuiltinTypes,
|
||||
) : FirIdeModuleSession(builtinTypes, Kind.Source) {
|
||||
val cache get() = firIdeProvider.cache
|
||||
}
|
||||
|
||||
) : LLFirResolvableModuleSession(builtinTypes)
|
||||
|
||||
+2
-2
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
|
||||
internal class FirSessionInvalidator(private val invalidateSourcesSession: (FirIdeSourcesSession) -> Unit) {
|
||||
internal class FirSessionInvalidator(private val invalidateSourcesSession: (LLFirResolvableModuleSession) -> Unit) {
|
||||
fun invalidate(session: FirSession) {
|
||||
require(session is FirIdeSourcesSession)
|
||||
require(session is LLFirResolvableModuleSession)
|
||||
invalidateSourcesSession(session)
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLibraryResolveModuleFileCache
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
|
||||
internal class LLFirLibraryOrLibrarySourceResolvableModuleSession(
|
||||
override val module: KtModule,
|
||||
override val project: Project,
|
||||
override val firFileBuilder: FirFileBuilder,
|
||||
builtinTypes: BuiltinTypes,
|
||||
) : LLFirResolvableModuleSession(builtinTypes) {
|
||||
init {
|
||||
checkIsValidKtModule(module)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun checkIsValidKtModule(module: KtModule) {
|
||||
require(module is KtLibraryModule || module is KtLibrarySourceModule) {
|
||||
"Expected ${KtLibraryModule::class.simpleName} or ${KtLibrarySourceModule::class.simpleName}, but ${module::class.simpleName} found"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.sessions
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.FirIdeProvider
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
|
||||
internal abstract class LLFirResolvableModuleSession(
|
||||
builtinTypes: BuiltinTypes,
|
||||
) : FirIdeModuleSession(builtinTypes, Kind.Source) {
|
||||
internal val cache: ModuleFileCache get() = (firProvider as FirIdeProvider).cache
|
||||
abstract val firFileBuilder: FirFileBuilder
|
||||
}
|
||||
+5
-4
@@ -5,16 +5,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@JvmInline
|
||||
internal value class LibrariesCache(
|
||||
private val cache: ConcurrentHashMap<KtSourceModule, FirIdeLibrariesSession> = ConcurrentHashMap()
|
||||
private val cache: ConcurrentHashMap<KtModule, FirIdeLibrariesSession> = ConcurrentHashMap()
|
||||
) {
|
||||
fun cached(
|
||||
moduleSourceInfo: KtSourceModule,
|
||||
create: (KtSourceModule) -> FirIdeLibrariesSession
|
||||
module: KtModule,
|
||||
create: (KtModule) -> FirIdeLibrariesSession
|
||||
): FirIdeLibrariesSession =
|
||||
cache.computeIfAbsent(moduleSourceInfo, create)
|
||||
cache.computeIfAbsent(module, create)
|
||||
}
|
||||
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.state
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
|
||||
abstract class FirPhysicalModuleResolveState : FirModuleResolveState()
|
||||
+15
-121
@@ -8,73 +8,25 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.state
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.DiagnosticsCollector
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirElementBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSourcesSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirDeclarationForCompiledElementSearcher
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError
|
||||
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
internal class FirSourceModuleResolveState(
|
||||
override val project: Project,
|
||||
override val module: KtSourceModule,
|
||||
private val sessionProvider: FirIdeSessionProvider,
|
||||
val firFileBuilder: FirFileBuilder,
|
||||
val firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
||||
) : FirPhysicalModuleResolveState() {
|
||||
override val rootModuleSession: FirIdeSourcesSession get() = sessionProvider.rootModuleSession
|
||||
|
||||
/**
|
||||
* WARNING! This object contains scopes for all statements and declarations that were ever resolved.
|
||||
* It can grow unbounded if you never edit the files in the opened project.
|
||||
*
|
||||
* It is a temporary solution until we can retrieve scopes for any fir element without re-resolving it.
|
||||
*/
|
||||
val fileStructureCache = FileStructureCache(firFileBuilder, firLazyDeclarationResolver)
|
||||
val elementBuilder = FirElementBuilder()
|
||||
private val diagnosticsCollector = DiagnosticsCollector(fileStructureCache, rootModuleSession.cache)
|
||||
|
||||
override fun getSessionFor(module: KtModule): FirSession =
|
||||
sessionProvider.getSession(module)!!
|
||||
|
||||
override fun getOrBuildFirFor(element: KtElement): FirElement? =
|
||||
elementBuilder.getOrBuildFirFor(
|
||||
element = element,
|
||||
firFileBuilder = firFileBuilder,
|
||||
moduleFileCache = rootModuleSession.cache,
|
||||
fileStructureCache = fileStructureCache,
|
||||
firLazyDeclarationResolver = firLazyDeclarationResolver,
|
||||
state = this
|
||||
)
|
||||
|
||||
override fun getOrBuildFirFile(ktFile: KtFile): FirFile =
|
||||
firFileBuilder.buildRawFirFileWithCaching(ktFile, rootModuleSession.cache)
|
||||
|
||||
override fun tryGetCachedFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? =
|
||||
cache.getContainerFirFile(declaration)
|
||||
override val module: KtModule,
|
||||
sessionProvider: FirIdeSessionProvider,
|
||||
firFileBuilder: FirFileBuilder,
|
||||
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
||||
) : LLFirResolvableModuleResolveState(sessionProvider, firFileBuilder, firLazyDeclarationResolver) {
|
||||
private val diagnosticsCollector = DiagnosticsCollector(fileStructureCache, cache)
|
||||
|
||||
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> =
|
||||
diagnosticsCollector.getDiagnosticsFor(element, filter)
|
||||
@@ -82,70 +34,12 @@ internal class FirSourceModuleResolveState(
|
||||
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> =
|
||||
diagnosticsCollector.collectDiagnosticsForFile(ktFile, filter)
|
||||
|
||||
override fun resolveToFirSymbol(
|
||||
ktDeclaration: KtDeclaration,
|
||||
phase: FirResolvePhase
|
||||
): FirBasedSymbol<*> {
|
||||
return when (val module = ktDeclaration.getKtModule()) {
|
||||
is KtSourceModule -> findSourceFirSymbol(ktDeclaration).also { resolveFirToPhase(it.fir, phase) }
|
||||
is KtLibraryModule -> findFirCompiledSymbol(ktDeclaration)
|
||||
else -> error("unsupported module $module")
|
||||
override fun getModuleKind(module: KtModule): ModuleKind {
|
||||
return when (module) {
|
||||
is KtSourceModule -> ModuleKind.RESOLVABLE_MODULE
|
||||
is KtLibraryModule -> ModuleKind.BINARY_MODULE
|
||||
else -> unexpectedElementError("module", module)
|
||||
}
|
||||
}
|
||||
|
||||
private fun findSourceFirSymbol(ktDeclaration: KtDeclaration): FirBasedSymbol<*> {
|
||||
return findSourceFirDeclarationByExpression(ktDeclaration.originalDeclaration ?: ktDeclaration).symbol
|
||||
}
|
||||
|
||||
private fun findFirCompiledSymbol(ktDeclaration: KtDeclaration): FirBasedSymbol<*> {
|
||||
require(ktDeclaration.containingKtFile.isCompiled) {
|
||||
"This method will only work on compiled declarations, but this declaration is not compiled: ${ktDeclaration.getElementTextInContext()}"
|
||||
}
|
||||
|
||||
val searcher = FirDeclarationForCompiledElementSearcher(rootModuleSession.symbolProvider)
|
||||
val firDeclaration = searcher.findNonLocalDeclaration(ktDeclaration)
|
||||
return firDeclaration.symbol
|
||||
}
|
||||
|
||||
/**
|
||||
* [ktDeclaration] should be either [KtDeclaration] or [KtLambdaExpression]
|
||||
*/
|
||||
private fun findSourceFirDeclarationByExpression(ktDeclaration: KtExpression): FirDeclaration {
|
||||
val module = ktDeclaration.getKtModule(project)
|
||||
require(module is KtSourceModule) {
|
||||
"Declaration should have ModuleSourceInfo, instead it had ${module::class}"
|
||||
}
|
||||
val nonLocalNamedDeclaration = ktDeclaration.getNonLocalContainingOrThisDeclaration()
|
||||
?: error("Declaration should have non-local container${ktDeclaration.getElementTextInContext()}")
|
||||
|
||||
if (ktDeclaration == nonLocalNamedDeclaration) {
|
||||
return nonLocalNamedDeclaration.findSourceNonLocalFirDeclaration(
|
||||
firFileBuilder = firFileBuilder,
|
||||
firSymbolProvider = rootModuleSession.firIdeProvider.symbolProvider,
|
||||
moduleFileCache = sessionProvider.getModuleCache(module)
|
||||
)
|
||||
}
|
||||
|
||||
return when (val localFirElement = getOrBuildFirFor(ktDeclaration)) {
|
||||
is FirDeclaration -> localFirElement
|
||||
is FirAnonymousFunctionExpression -> localFirElement.anonymousFunction
|
||||
is FirAnonymousObjectExpression -> localFirElement.anonymousObject
|
||||
else -> error("FirDeclaration was not found for\n${ktDeclaration.getElementTextInContext()}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun resolveFirToPhase(declaration: FirDeclaration, toPhase: FirResolvePhase) {
|
||||
if (toPhase == FirResolvePhase.RAW_FIR) return
|
||||
val fileCache = when (val session = declaration.moduleData.session) {
|
||||
is FirIdeSourcesSession -> session.cache
|
||||
else -> return
|
||||
}
|
||||
firLazyDeclarationResolver.lazyResolveDeclaration(
|
||||
firDeclarationToResolve = declaration,
|
||||
moduleFileCache = fileCache,
|
||||
scopeSession = ScopeSession(),
|
||||
toPhase = toPhase,
|
||||
checkPCE = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.state
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibraryOrLibrarySourceResolvableModuleSession
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
|
||||
internal class LLFirLibraryOrLibrarySourceResolvableModuleResolveState(
|
||||
override val project: Project,
|
||||
override val module: KtModule,
|
||||
sessionProvider: FirIdeSessionProvider,
|
||||
firFileBuilder: FirFileBuilder,
|
||||
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
||||
) : LLFirResolvableModuleResolveState(sessionProvider, firFileBuilder, firLazyDeclarationResolver) {
|
||||
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> =
|
||||
emptyList()
|
||||
|
||||
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> =
|
||||
emptyList()
|
||||
|
||||
override fun getModuleKind(module: KtModule): ModuleKind {
|
||||
LLFirLibraryOrLibrarySourceResolvableModuleSession.checkIsValidKtModule(module)
|
||||
return when {
|
||||
module == this.module -> ModuleKind.RESOLVABLE_MODULE
|
||||
else -> ModuleKind.BINARY_MODULE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.state
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirElementBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.FirIdeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSourcesSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirDeclarationForCompiledElementSearcher
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
internal abstract class LLFirResolvableModuleResolveState(
|
||||
protected val sessionProvider: FirIdeSessionProvider,
|
||||
val firFileBuilder: FirFileBuilder,
|
||||
val firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
||||
) : FirModuleResolveState() {
|
||||
final override val rootModuleSession = sessionProvider.rootModuleSession
|
||||
val cache = (rootModuleSession.firProvider as FirIdeProvider).cache
|
||||
|
||||
val fileStructureCache = FileStructureCache(firFileBuilder, firLazyDeclarationResolver)
|
||||
val elementBuilder = FirElementBuilder()
|
||||
|
||||
override fun getSessionFor(module: KtModule): FirSession =
|
||||
sessionProvider.getSession(module)!!
|
||||
|
||||
override fun getOrBuildFirFor(element: KtElement): FirElement? =
|
||||
elementBuilder.getOrBuildFirFor(
|
||||
element = element,
|
||||
firFileBuilder = firFileBuilder,
|
||||
moduleFileCache = cache,
|
||||
fileStructureCache = fileStructureCache,
|
||||
firLazyDeclarationResolver = firLazyDeclarationResolver,
|
||||
state = this
|
||||
)
|
||||
|
||||
|
||||
override fun getOrBuildFirFile(ktFile: KtFile): FirFile =
|
||||
firFileBuilder.buildRawFirFileWithCaching(ktFile, cache)
|
||||
|
||||
override fun tryGetCachedFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? =
|
||||
cache.getContainerFirFile(declaration)
|
||||
|
||||
override fun resolveToFirSymbol(
|
||||
ktDeclaration: KtDeclaration,
|
||||
phase: FirResolvePhase
|
||||
): FirBasedSymbol<*> {
|
||||
val module = ktDeclaration.getKtModule()
|
||||
return when (getModuleKind(module)) {
|
||||
ModuleKind.RESOLVABLE_MODULE -> findSourceFirSymbol(ktDeclaration, module).also { resolveFirToPhase(it.fir, phase) }
|
||||
ModuleKind.BINARY_MODULE -> findFirCompiledSymbol(ktDeclaration)
|
||||
}
|
||||
}
|
||||
|
||||
private fun findFirCompiledSymbol(ktDeclaration: KtDeclaration): FirBasedSymbol<*> {
|
||||
require(ktDeclaration.containingKtFile.isCompiled) {
|
||||
"This method will only work on compiled declarations, but this declaration is not compiled: ${ktDeclaration.getElementTextInContext()}"
|
||||
}
|
||||
|
||||
val searcher = FirDeclarationForCompiledElementSearcher(rootModuleSession.symbolProvider)
|
||||
val firDeclaration = searcher.findNonLocalDeclaration(ktDeclaration)
|
||||
return firDeclaration.symbol
|
||||
}
|
||||
|
||||
private fun findSourceFirSymbol(ktDeclaration: KtDeclaration, module: KtModule): FirBasedSymbol<*> {
|
||||
return findSourceFirDeclarationByExpression(ktDeclaration.originalDeclaration ?: ktDeclaration, module)
|
||||
}
|
||||
|
||||
/**
|
||||
* [ktDeclaration] should be either [KtDeclaration] or [KtLambdaExpression]
|
||||
*/
|
||||
private fun findSourceFirDeclarationByExpression(ktDeclaration: KtExpression, module: KtModule): FirBasedSymbol<*> {
|
||||
require(getModuleKind(module) == ModuleKind.RESOLVABLE_MODULE) {
|
||||
"Declaration should be resolvable module, instead it had ${module::class}"
|
||||
}
|
||||
val nonLocalNamedDeclaration = ktDeclaration.getNonLocalContainingOrThisDeclaration()
|
||||
?: error("Declaration should have non-local container${ktDeclaration.getElementTextInContext()}")
|
||||
|
||||
if (ktDeclaration == nonLocalNamedDeclaration) {
|
||||
return nonLocalNamedDeclaration.findSourceNonLocalFirDeclaration(
|
||||
firFileBuilder = firFileBuilder,
|
||||
firSymbolProvider = rootModuleSession.firProvider.symbolProvider,
|
||||
moduleFileCache = sessionProvider.getModuleCache(module)
|
||||
).symbol
|
||||
}
|
||||
|
||||
return findDeclarationInSourceViaResolve(ktDeclaration)
|
||||
}
|
||||
|
||||
protected abstract fun getModuleKind(module: KtModule): ModuleKind
|
||||
|
||||
private fun findDeclarationInSourceViaResolve(ktDeclaration: KtExpression): FirBasedSymbol<*> {
|
||||
val firDeclaration = when (val fir = getOrBuildFirFor(ktDeclaration)) {
|
||||
is FirDeclaration -> fir
|
||||
is FirAnonymousFunctionExpression -> fir.anonymousFunction
|
||||
is FirAnonymousObjectExpression -> fir.anonymousObject
|
||||
else -> error("FirDeclaration was not found for\n${ktDeclaration.getElementTextInContext()}")
|
||||
}
|
||||
return firDeclaration.symbol
|
||||
}
|
||||
|
||||
override fun resolveFirToPhase(declaration: FirDeclaration, toPhase: FirResolvePhase) {
|
||||
if (toPhase == FirResolvePhase.RAW_FIR) return
|
||||
val fileCache = when (val session = declaration.moduleData.session) {
|
||||
is FirIdeSourcesSession -> session.cache
|
||||
else -> return
|
||||
}
|
||||
firLazyDeclarationResolver.lazyResolveDeclaration(
|
||||
firDeclarationToResolve = declaration,
|
||||
moduleFileCache = fileCache,
|
||||
scopeSession = ScopeSession(),
|
||||
toPhase = toPhase,
|
||||
checkPCE = true,
|
||||
)
|
||||
}
|
||||
|
||||
override fun getTowerContextProvider(ktFile: KtFile): FirTowerContextProvider {
|
||||
return TowerProviderForElementForState(this)
|
||||
}
|
||||
|
||||
protected enum class ModuleKind {
|
||||
RESOLVABLE_MODULE,
|
||||
BINARY_MODULE
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.state
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.FirModuleResolveStateDepended
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTowerDataContext
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
|
||||
internal class TowerProviderForElementForState(private val state: FirModuleResolveState) : FirTowerContextProvider {
|
||||
override fun getClosestAvailableParentContext(ktElement: KtElement): FirTowerDataContext? {
|
||||
return if (state is FirModuleResolveStateDepended) {
|
||||
state.towerProviderBuiltUponElement.getClosestAvailableParentContext(ktElement)
|
||||
?: LowLevelFirApiFacadeForResolveOnAir.onAirGetTowerContextProvider(state.originalState, ktElement)
|
||||
.getClosestAvailableParentContext(ktElement)
|
||||
} else {
|
||||
LowLevelFirApiFacadeForResolveOnAir.onAirGetTowerContextProvider(state, ktElement).getClosestAvailableParentContext(ktElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.util
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
|
||||
internal object LLFirResolvePhaseChecker {
|
||||
fun requireResolvePhase(firDeclaration: FirDeclaration, requiredPhase: FirResolvePhase) {
|
||||
require(firDeclaration.resolvePhase == FirResolvePhase.BODY_RESOLVE) {
|
||||
"Required $requiredPhase for $firDeclaration but ${firDeclaration.resolvePhase} found"
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -15,14 +15,13 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirLazyBlock
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirLazyExpression
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest
|
||||
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
|
||||
abstract class AbstractFirLazyBodiesCalculatorTest : AbstractLowLevelApiSingleFileTest() {
|
||||
|
||||
private val lazyChecker = object : FirVisitorVoid() {
|
||||
override fun visitElement(element: FirElement) {
|
||||
TestCase.assertFalse("${FirLazyBlock::class.qualifiedName} should not present in the tree", element is FirLazyBlock)
|
||||
@@ -34,7 +33,7 @@ abstract class AbstractFirLazyBodiesCalculatorTest : AbstractLowLevelApiSingleFi
|
||||
override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) {
|
||||
resolveWithClearCaches(ktFile) { resolveState ->
|
||||
val session = resolveState.rootModuleSession
|
||||
val provider = session.firIdeProvider.kotlinScopeProvider
|
||||
val provider = session.kotlinScopeProvider
|
||||
|
||||
val laziedFirFile = RawFirBuilder(
|
||||
session,
|
||||
@@ -59,5 +58,4 @@ abstract class AbstractFirLazyBodiesCalculatorTest : AbstractLowLevelApiSingleFi
|
||||
TestCase.assertEquals(laziedFirFileDump, fullFirFileDump)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -43,7 +43,7 @@ abstract class AbstractFirContextCollectionTest : AbstractLowLevelApiSingleFileT
|
||||
) { resolveState ->
|
||||
check(resolveState is FirSourceModuleResolveState)
|
||||
|
||||
val fileStructure = resolveState.fileStructureCache.getFileStructure(ktFile, resolveState.rootModuleSession.cache)
|
||||
val fileStructure = resolveState.fileStructureCache.getFileStructure(ktFile, resolveState.cache)
|
||||
val allStructureElements = fileStructure.getAllStructureElements()
|
||||
|
||||
handler.elementsToCheckContext = allStructureElements.map { it.getFirDeclaration() }
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ abstract class AbstractFileStructureTest : AbstractLowLevelApiSingleFileTest() {
|
||||
val moduleResolveState = getResolveState() as FirSourceModuleResolveState
|
||||
return moduleResolveState.fileStructureCache.getFileStructure(
|
||||
ktFile = this,
|
||||
moduleFileCache = moduleResolveState.rootModuleSession.cache
|
||||
moduleFileCache = moduleResolveState.cache
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user