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.tokens.ValidityToken
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
|
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
|
||||||
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
|
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.getOrBuildFirFile
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirOfType
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirOfType
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.ResolutionParameters
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.ResolutionParameters
|
||||||
@@ -61,7 +60,7 @@ internal class KtFirCompletionCandidateChecker(
|
|||||||
val file = originalFile.getOrBuildFirFile(firResolveState)
|
val file = originalFile.getOrBuildFirFile(firResolveState)
|
||||||
val explicitReceiverExpression = possibleExplicitReceiver?.getOrBuildFirOfType<FirExpression>(firResolveState)
|
val explicitReceiverExpression = possibleExplicitReceiver?.getOrBuildFirOfType<FirExpression>(firResolveState)
|
||||||
val resolver = SingleCandidateResolver(firResolveState.rootModuleSession, file)
|
val resolver = SingleCandidateResolver(firResolveState.rootModuleSession, file)
|
||||||
val implicitReceivers = getImplicitReceivers(nameExpression)
|
val implicitReceivers = getImplicitReceivers(originalFile, nameExpression)
|
||||||
for (implicitReceiverValue in implicitReceivers) {
|
for (implicitReceiverValue in implicitReceivers) {
|
||||||
val resolutionParameters = ResolutionParameters(
|
val resolutionParameters = ResolutionParameters(
|
||||||
singleCandidateResolutionMode = SingleCandidateResolutionMode.CHECK_EXTENSION_FOR_COMPLETION,
|
singleCandidateResolutionMode = SingleCandidateResolutionMode.CHECK_EXTENSION_FOR_COMPLETION,
|
||||||
@@ -84,8 +83,11 @@ internal class KtFirCompletionCandidateChecker(
|
|||||||
return KtExtensionApplicabilityResult.NonApplicable(KtSubstitutor.Empty(token))
|
return KtExtensionApplicabilityResult.NonApplicable(KtSubstitutor.Empty(token))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getImplicitReceivers(fakeNameExpression: KtSimpleNameExpression): Sequence<ImplicitReceiverValue<*>?> {
|
private fun getImplicitReceivers(
|
||||||
val towerDataContext = analysisSession.firResolveState.getTowerContextProvider()
|
originalFile: KtFile,
|
||||||
|
fakeNameExpression: KtSimpleNameExpression
|
||||||
|
): Sequence<ImplicitReceiverValue<*>?> {
|
||||||
|
val towerDataContext = analysisSession.firResolveState.getTowerContextProvider(originalFile)
|
||||||
.getClosestAvailableParentContext(fakeNameExpression)
|
.getClosestAvailableParentContext(fakeNameExpression)
|
||||||
?: error("Cannot find enclosing declaration for ${fakeNameExpression.getElementTextInContext()}")
|
?: 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.types.KtType
|
||||||
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
|
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.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.analysis.low.level.api.fir.util.getElementTextInContext
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
@@ -189,9 +188,8 @@ internal class KtFirScopeProvider(
|
|||||||
originalFile: KtFile,
|
originalFile: KtFile,
|
||||||
positionInFakeFile: KtElement
|
positionInFakeFile: KtElement
|
||||||
): KtScopeContext = withValidityAssertion {
|
): KtScopeContext = withValidityAssertion {
|
||||||
|
|
||||||
val towerDataContext =
|
val towerDataContext =
|
||||||
analysisSession.firResolveState.getTowerContextProvider().getClosestAvailableParentContext(positionInFakeFile)
|
analysisSession.firResolveState.getTowerContextProvider(originalFile).getClosestAvailableParentContext(positionInFakeFile)
|
||||||
?: error("Cannot find enclosing declaration for ${positionInFakeFile.getElementTextInContext()}")
|
?: error("Cannot find enclosing declaration for ${positionInFakeFile.getElementTextInContext()}")
|
||||||
|
|
||||||
val implicitReceivers = towerDataContext.nonLocalTowerDataElements.mapNotNull { it.implicitReceiver }.distinct()
|
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.KtType
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||||
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
|
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.getOrBuildFir
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
||||||
import org.jetbrains.kotlin.fir.FirRenderer
|
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.ConeTypeCompatibilityChecker.isCompatible
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass
|
import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.typeParameterSymbols
|
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.FirResolvePhase
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
||||||
@@ -124,7 +122,7 @@ internal class KtFirTypeProvider(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getImplicitReceiverTypesAtPosition(position: KtElement): List<KtType> {
|
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()
|
.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.lazy.resolve.FirLazyDeclarationResolver
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSession
|
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.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.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.KtModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||||
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
|
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
|
||||||
@@ -27,10 +33,10 @@ internal class FirIdeResolveStateService(project: Project) {
|
|||||||
project.createProjectWideOutOfBlockModificationTracker(),
|
project.createProjectWideOutOfBlockModificationTracker(),
|
||||||
ProjectRootModificationTracker.getInstance(project),
|
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) }
|
stateCache.computeIfAbsent(module) { createResolveStateFor(module, sessionProviderStorage) }
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -41,19 +47,34 @@ internal class FirIdeResolveStateService(project: Project) {
|
|||||||
module: KtModule,
|
module: KtModule,
|
||||||
sessionProviderStorage: FirIdeSessionProviderStorage,
|
sessionProviderStorage: FirIdeSessionProviderStorage,
|
||||||
configureSession: (FirIdeSession.() -> Unit)? = null,
|
configureSession: (FirIdeSession.() -> Unit)? = null,
|
||||||
): FirSourceModuleResolveState {
|
): LLFirResolvableModuleResolveState {
|
||||||
if (module !is KtSourceModule) {
|
|
||||||
error("Creating FirModuleResolveState is not yet supported for $module")
|
|
||||||
}
|
|
||||||
val sessionProvider = sessionProviderStorage.getSessionProvider(module, configureSession)
|
val sessionProvider = sessionProviderStorage.getSessionProvider(module, configureSession)
|
||||||
val firFileBuilder = sessionProvider.rootModuleSession.firFileBuilder
|
return when (module) {
|
||||||
return FirSourceModuleResolveState(
|
is KtSourceModule -> {
|
||||||
sessionProviderStorage.project,
|
val firFileBuilder = (sessionProvider.rootModuleSession as FirIdeSourcesSession).firFileBuilder
|
||||||
module,
|
FirSourceModuleResolveState(
|
||||||
sessionProvider,
|
sessionProviderStorage.project,
|
||||||
firFileBuilder,
|
module,
|
||||||
FirLazyDeclarationResolver(firFileBuilder),
|
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 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.DiagnosticCheckerFilter
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
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.FirTowerContextProvider
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
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.file.structure.KtToFirMapping
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.FirSourceModuleResolveState
|
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.containingKtFileIfAny
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalKtFile
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalKtFile
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
@@ -28,35 +31,21 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||||
|
|
||||||
internal class FirModuleResolveStateDepended(
|
internal class FirModuleResolveStateDepended(
|
||||||
val originalState: FirSourceModuleResolveState,
|
val originalState: LLFirResolvableModuleResolveState,
|
||||||
val towerProviderBuiltUponElement: FirTowerContextProvider,
|
val towerProviderBuiltUponElement: FirTowerContextProvider,
|
||||||
private val ktToFirMapping: KtToFirMapping?,
|
private val ktToFirMapping: KtToFirMapping?,
|
||||||
) : FirModuleResolveState() {
|
) : FirModuleResolveState() {
|
||||||
|
|
||||||
override val project: Project get() = originalState.project
|
override val project: Project get() = originalState.project
|
||||||
override val module: KtModule get() = originalState.module
|
override val module: KtModule get() = originalState.module
|
||||||
override val rootModuleSession get() = originalState.rootModuleSession
|
override val rootModuleSession get() = originalState.rootModuleSession
|
||||||
private val fileStructureCache get() = originalState.fileStructureCache
|
|
||||||
|
|
||||||
override fun getSessionFor(module: KtModule): FirSession =
|
override fun getSessionFor(module: KtModule): FirSession =
|
||||||
originalState.getSessionFor(module)
|
originalState.getSessionFor(module)
|
||||||
|
|
||||||
override fun getOrBuildFirFor(element: KtElement): FirElement? {
|
override fun getOrBuildFirFor(element: KtElement): FirElement? {
|
||||||
val elementBuilder = originalState.elementBuilder
|
val psi = FirElementBuilder.getPsiAsFirElementSource(element) ?: return null
|
||||||
|
|
||||||
val psi = elementBuilder.getPsiAsFirElementSource(element) ?: return null
|
|
||||||
if (!elementBuilder.doKtElementHasCorrespondingFirElement(element)) return null
|
|
||||||
|
|
||||||
ktToFirMapping?.getFirOfClosestParent(psi, this)?.let { return it }
|
ktToFirMapping?.getFirOfClosestParent(psi, this)?.let { return it }
|
||||||
|
return originalState.getOrBuildFirFor(element = element)
|
||||||
return elementBuilder.getOrBuildFirFor(
|
|
||||||
element = element,
|
|
||||||
firFileBuilder = originalState.firFileBuilder,
|
|
||||||
moduleFileCache = originalState.rootModuleSession.cache,
|
|
||||||
fileStructureCache = fileStructureCache,
|
|
||||||
firLazyDeclarationResolver = originalState.firLazyDeclarationResolver,
|
|
||||||
state = this,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOrBuildFirFile(ktFile: KtFile): FirFile =
|
override fun getOrBuildFirFile(ktFile: KtFile): FirFile =
|
||||||
@@ -82,4 +71,7 @@ internal class FirModuleResolveStateDepended(
|
|||||||
override fun resolveToFirSymbol(ktDeclaration: KtDeclaration, phase: FirResolvePhase): FirBasedSymbol<*> {
|
override fun resolveToFirSymbol(ktDeclaration: KtDeclaration, phase: FirResolvePhase): FirBasedSymbol<*> {
|
||||||
return originalState.resolveToFirSymbol(ktDeclaration, phase)
|
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
|
package org.jetbrains.kotlin.analysis.low.level.api.fir.api
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
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.low.level.api.fir.file.builder.ModuleFileCache
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
@@ -56,4 +57,6 @@ abstract class FirModuleResolveState {
|
|||||||
abstract fun resolveToFirSymbol(ktDeclaration: KtDeclaration, phase: FirResolvePhase): FirBasedSymbol<*>
|
abstract fun resolveToFirSymbol(ktDeclaration: KtDeclaration, phase: FirResolvePhase): FirBasedSymbol<*>
|
||||||
|
|
||||||
internal abstract fun resolveFirToPhase(declaration: FirDeclaration, toPhase: FirResolvePhase)
|
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.api.impl.barebone.parentsOfType
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.DeclarationCopyBuilder.withBodyFrom
|
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.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.FileTowerProvider
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerDataContextAllElementsCollector
|
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.FirElementsRecorder
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.KtToFirMapping
|
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.lazy.resolve.*
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSourcesSession
|
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.getElementTextInContext
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
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.FirTypeResolveTransformer
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||||
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
|
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.types.FirResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -67,7 +67,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
place: T,
|
place: T,
|
||||||
elementToResolve: T,
|
elementToResolve: T,
|
||||||
): FirElement {
|
): FirElement {
|
||||||
require(state is FirSourceModuleResolveState)
|
require(state is LLFirResolvableModuleResolveState)
|
||||||
require(place.isPhysical)
|
require(place.isPhysical)
|
||||||
|
|
||||||
val declaration = runBodyResolveOnAir(
|
val declaration = runBodyResolveOnAir(
|
||||||
@@ -95,7 +95,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
state: FirModuleResolveState,
|
state: FirModuleResolveState,
|
||||||
place: KtElement,
|
place: KtElement,
|
||||||
): FirTowerContextProvider {
|
): FirTowerContextProvider {
|
||||||
require(state is FirSourceModuleResolveState)
|
require(state is LLFirResolvableModuleResolveState)
|
||||||
|
|
||||||
return if (place is KtFile) {
|
return if (place is KtFile) {
|
||||||
FileTowerProvider(place, onAirGetTowerContextForFile(state, place))
|
FileTowerProvider(place, onAirGetTowerContextForFile(state, place))
|
||||||
@@ -116,11 +116,11 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun onAirGetTowerContextForFile(
|
private fun onAirGetTowerContextForFile(
|
||||||
state: FirSourceModuleResolveState,
|
state: LLFirResolvableModuleResolveState,
|
||||||
file: KtFile,
|
file: KtFile,
|
||||||
): FirTowerDataContext {
|
): FirTowerDataContext {
|
||||||
require(file.isPhysical)
|
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(
|
val firFile = session.firFileBuilder.buildRawFirFileWithCaching(
|
||||||
ktFile = file,
|
ktFile = file,
|
||||||
@@ -144,7 +144,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
originalKtFile: KtFile,
|
originalKtFile: KtFile,
|
||||||
elementToAnalyze: KtElement
|
elementToAnalyze: KtElement
|
||||||
): FirModuleResolveState {
|
): FirModuleResolveState {
|
||||||
require(originalState is FirSourceModuleResolveState)
|
require(originalState is LLFirResolvableModuleResolveState)
|
||||||
require(elementToAnalyze !is KtFile) { "KtFile for dependency element not supported" }
|
require(elementToAnalyze !is KtFile) { "KtFile for dependency element not supported" }
|
||||||
require(!elementToAnalyze.isPhysical) { "Depended state should be build only for non-physical elements" }
|
require(!elementToAnalyze.isPhysical) { "Depended state should be build only for non-physical elements" }
|
||||||
|
|
||||||
@@ -178,21 +178,21 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
|
|
||||||
private fun tryResolveAsFileAnnotation(
|
private fun tryResolveAsFileAnnotation(
|
||||||
annotationEntry: KtAnnotationEntry,
|
annotationEntry: KtAnnotationEntry,
|
||||||
state: FirSourceModuleResolveState,
|
state: LLFirResolvableModuleResolveState,
|
||||||
replacement: RawFirReplacement,
|
replacement: RawFirReplacement,
|
||||||
firFile: FirFile,
|
firFile: FirFile,
|
||||||
collector: FirTowerDataContextCollector? = null,
|
collector: FirTowerDataContextCollector? = null,
|
||||||
): FirAnnotation {
|
): FirAnnotation {
|
||||||
val annotationCall = buildFileFirAnnotation(
|
val annotationCall = buildFileFirAnnotation(
|
||||||
session = firFile.moduleData.session,
|
session = firFile.moduleData.session,
|
||||||
baseScopeProvider = firFile.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
baseScopeProvider = firFile.moduleData.session.kotlinScopeProvider,
|
||||||
fileAnnotation = annotationEntry,
|
fileAnnotation = annotationEntry,
|
||||||
replacement = replacement
|
replacement = replacement
|
||||||
)
|
)
|
||||||
state.firLazyDeclarationResolver.resolveFileAnnotations(
|
state.firLazyDeclarationResolver.resolveFileAnnotations(
|
||||||
firFile = firFile,
|
firFile = firFile,
|
||||||
annotations = listOf(annotationCall),
|
annotations = listOf(annotationCall),
|
||||||
moduleFileCache = state.rootModuleSession.cache,
|
moduleFileCache = state.cache,
|
||||||
scopeSession = ScopeSession(),
|
scopeSession = ScopeSession(),
|
||||||
checkPCE = true,
|
checkPCE = true,
|
||||||
collector = collector
|
collector = collector
|
||||||
@@ -202,7 +202,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun runBodyResolveOnAir(
|
private fun runBodyResolveOnAir(
|
||||||
state: FirSourceModuleResolveState,
|
state: LLFirResolvableModuleResolveState,
|
||||||
replacement: RawFirReplacement,
|
replacement: RawFirReplacement,
|
||||||
onAirCreatedDeclaration: Boolean,
|
onAirCreatedDeclaration: Boolean,
|
||||||
collector: FirTowerDataContextCollector? = null,
|
collector: FirTowerDataContextCollector? = null,
|
||||||
@@ -233,7 +233,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
|
|
||||||
val newDeclarationWithReplacement = RawFirNonLocalDeclarationBuilder.buildWithReplacement(
|
val newDeclarationWithReplacement = RawFirNonLocalDeclarationBuilder.buildWithReplacement(
|
||||||
session = originalDeclaration.moduleData.session,
|
session = originalDeclaration.moduleData.session,
|
||||||
scopeProvider = originalDeclaration.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
scopeProvider = originalDeclaration.moduleData.session.kotlinScopeProvider,
|
||||||
designation = originalDesignation,
|
designation = originalDesignation,
|
||||||
rootNonLocalDeclaration = nonLocalDeclaration,
|
rootNonLocalDeclaration = nonLocalDeclaration,
|
||||||
replacement = replacement,
|
replacement = replacement,
|
||||||
@@ -241,7 +241,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
|
|
||||||
val isInBodyReplacement = isInBodyReplacement(nonLocalDeclaration, replacement)
|
val isInBodyReplacement = isInBodyReplacement(nonLocalDeclaration, replacement)
|
||||||
|
|
||||||
return state.rootModuleSession.cache.firFileLockProvider.runCustomResolveUnderLock(originalFirFile, true) {
|
return state.cache.firFileLockProvider.runCustomResolveUnderLock(originalFirFile, true) {
|
||||||
val copiedFirDeclaration = if (isInBodyReplacement) {
|
val copiedFirDeclaration = if (isInBodyReplacement) {
|
||||||
when (originalDeclaration) {
|
when (originalDeclaration) {
|
||||||
is FirSimpleFunction ->
|
is FirSimpleFunction ->
|
||||||
@@ -263,7 +263,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
ResolveTreeBuilder.resolveEnsure(onAirDesignation.declaration, FirResolvePhase.BODY_RESOLVE) {
|
ResolveTreeBuilder.resolveEnsure(onAirDesignation.declaration, FirResolvePhase.BODY_RESOLVE) {
|
||||||
state.firLazyDeclarationResolver.runLazyDesignatedOnAirResolveToBodyWithoutLock(
|
state.firLazyDeclarationResolver.runLazyDesignatedOnAirResolveToBodyWithoutLock(
|
||||||
designation = onAirDesignation,
|
designation = onAirDesignation,
|
||||||
moduleFileCache = state.rootModuleSession.cache,
|
moduleFileCache = state.cache,
|
||||||
checkPCE = true,
|
checkPCE = true,
|
||||||
onAirCreatedDeclaration = onAirCreatedDeclaration,
|
onAirCreatedDeclaration = onAirCreatedDeclaration,
|
||||||
towerDataContextCollector = collector,
|
towerDataContextCollector = collector,
|
||||||
@@ -299,16 +299,16 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
fun onAirResolveTypeInPlace(
|
fun onAirResolveTypeInPlace(
|
||||||
place: KtElement,
|
place: KtElement,
|
||||||
typeReference: KtTypeReference,
|
typeReference: KtTypeReference,
|
||||||
state: FirModuleResolveState
|
state: FirModuleResolveState,
|
||||||
): FirResolvedTypeRef {
|
): FirResolvedTypeRef {
|
||||||
val context = state.getTowerContextProvider().getClosestAvailableParentContext(place)
|
val context = state.getTowerContextProvider(place.containingKtFile).getClosestAvailableParentContext(place)
|
||||||
?: error("TowerContext not found for ${place.getElementTextInContext()}")
|
?: error("TowerContext not found for ${place.getElementTextInContext()}")
|
||||||
|
|
||||||
val session = state.rootModuleSession
|
val session = state.rootModuleSession
|
||||||
val firTypeReference = buildFirUserTypeRef(
|
val firTypeReference = buildFirUserTypeRef(
|
||||||
typeReference = typeReference,
|
typeReference = typeReference,
|
||||||
session = session,
|
session = session,
|
||||||
baseScopeProvider = session.firIdeProvider.kotlinScopeProvider
|
baseScopeProvider = session.kotlinScopeProvider
|
||||||
)
|
)
|
||||||
|
|
||||||
return FirTypeResolveTransformer(
|
return FirTypeResolveTransformer(
|
||||||
@@ -317,18 +317,4 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
|||||||
initialScopes = context.towerDataElements.asReversed().mapNotNull { it.scope }
|
initialScopes = context.towerDataElements.asReversed().mapNotNull { it.scope }
|
||||||
).transformTypeRef(firTypeReference, null)
|
).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
|
@ThreadSafe
|
||||||
internal class FirElementBuilder {
|
internal class FirElementBuilder {
|
||||||
fun getPsiAsFirElementSource(element: KtElement): KtElement? {
|
companion object {
|
||||||
val deparenthesized = if (element is KtPropertyDelegate) element.deparenthesize() else element
|
fun getPsiAsFirElementSource(element: KtElement): KtElement? {
|
||||||
return when {
|
val deparenthesized = if (element is KtPropertyDelegate) element.deparenthesize() else element
|
||||||
deparenthesized is KtParenthesizedExpression -> deparenthesized.deparenthesize()
|
return when {
|
||||||
deparenthesized is KtPropertyDelegate -> deparenthesized.expression ?: element
|
deparenthesized is KtParenthesizedExpression -> deparenthesized.deparenthesize()
|
||||||
deparenthesized is KtQualifiedExpression && deparenthesized.selectorExpression is KtCallExpression -> {
|
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
|
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.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) {
|
fun doKtElementHasCorrespondingFirElement(ktElement: KtElement): Boolean = when (ktElement) {
|
||||||
is KtImportList -> false
|
is KtImportList -> false
|
||||||
else -> true
|
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.FirFileBuilder
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
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.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.findSourceNonLocalFirDeclaration
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
|
||||||
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
|
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
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>()
|
private val structureElements = ConcurrentHashMap<KtAnnotated, FileStructureElement>()
|
||||||
|
|
||||||
@@ -59,7 +60,6 @@ internal class FileStructure private constructor(
|
|||||||
newKtDeclaration = declaration as KtDeclaration,
|
newKtDeclaration = declaration as KtDeclaration,
|
||||||
cache = moduleFileCache,
|
cache = moduleFileCache,
|
||||||
firLazyDeclarationResolver = firLazyDeclarationResolver,
|
firLazyDeclarationResolver = firLazyDeclarationResolver,
|
||||||
firIdeProvider = firIdeProvider,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> structureElement
|
else -> structureElement
|
||||||
@@ -112,7 +112,7 @@ internal class FileStructure private constructor(
|
|||||||
private fun createDeclarationStructure(declaration: KtDeclaration): FileStructureElement {
|
private fun createDeclarationStructure(declaration: KtDeclaration): FileStructureElement {
|
||||||
val firDeclaration = declaration.findSourceNonLocalFirDeclaration(
|
val firDeclaration = declaration.findSourceNonLocalFirDeclaration(
|
||||||
firFileBuilder,
|
firFileBuilder,
|
||||||
firIdeProvider.symbolProvider,
|
firProvider.symbolProvider,
|
||||||
moduleFileCache,
|
moduleFileCache,
|
||||||
firFile
|
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.RawFirNonLocalDeclarationBuilder
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved
|
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.providers.firIdeProvider
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableModuleResolveState
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.psi
|
import org.jetbrains.kotlin.fir.psi
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
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.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
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) {
|
internal class KtToFirMapping(firElement: FirElement, recorder: FirElementsRecorder) {
|
||||||
|
|
||||||
private val mapping = FirElementsRecorder.recordElementsFrom(firElement, recorder)
|
private val mapping = FirElementsRecorder.recordElementsFrom(firElement, recorder)
|
||||||
|
|
||||||
private val userTypeMapping = ConcurrentHashMap<KtUserType, FirElement>()
|
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 }
|
mapping[ktElement]?.let { return it }
|
||||||
|
|
||||||
val userType = when (ktElement) {
|
val userType = when (ktElement) {
|
||||||
@@ -87,7 +86,6 @@ internal sealed class ReanalyzableStructureElement<KT : KtDeclaration, S : FirBa
|
|||||||
newKtDeclaration: KT,
|
newKtDeclaration: KT,
|
||||||
cache: ModuleFileCache,
|
cache: ModuleFileCache,
|
||||||
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
||||||
firIdeProvider: FirIdeProvider,
|
|
||||||
): ReanalyzableStructureElement<KT, S>
|
): ReanalyzableStructureElement<KT, S>
|
||||||
|
|
||||||
fun isUpToDate(): Boolean = psi.getModificationStamp() == timestamp
|
fun isUpToDate(): Boolean = psi.getModificationStamp() == timestamp
|
||||||
@@ -116,20 +114,18 @@ internal class ReanalyzableFunctionStructureElement(
|
|||||||
newKtDeclaration: KtNamedFunction,
|
newKtDeclaration: KtNamedFunction,
|
||||||
cache: ModuleFileCache,
|
cache: ModuleFileCache,
|
||||||
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
||||||
firIdeProvider: FirIdeProvider,
|
|
||||||
): ReanalyzableFunctionStructureElement {
|
): ReanalyzableFunctionStructureElement {
|
||||||
val originalFunction = firSymbol.fir as FirSimpleFunction
|
val originalFunction = firSymbol.fir as FirSimpleFunction
|
||||||
val designation = originalFunction.collectDesignation()
|
val designation = originalFunction.collectDesignation()
|
||||||
|
|
||||||
val temporaryFunction = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
val temporaryFunction = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
||||||
session = originalFunction.moduleData.session,
|
session = originalFunction.moduleData.session,
|
||||||
scopeProvider = originalFunction.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
scopeProvider = originalFunction.moduleData.session.kotlinScopeProvider,
|
||||||
designation = designation,
|
designation = designation,
|
||||||
rootNonLocalDeclaration = newKtDeclaration,
|
rootNonLocalDeclaration = newKtDeclaration,
|
||||||
) as FirSimpleFunction
|
) as FirSimpleFunction
|
||||||
|
|
||||||
return cache.firFileLockProvider.withWriteLock(firFile) {
|
return cache.firFileLockProvider.withWriteLock(firFile) {
|
||||||
|
|
||||||
val upgradedPhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS)
|
val upgradedPhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS)
|
||||||
with(originalFunction) {
|
with(originalFunction) {
|
||||||
replaceBody(temporaryFunction.body)
|
replaceBody(temporaryFunction.body)
|
||||||
@@ -172,14 +168,13 @@ internal class ReanalyzablePropertyStructureElement(
|
|||||||
newKtDeclaration: KtProperty,
|
newKtDeclaration: KtProperty,
|
||||||
cache: ModuleFileCache,
|
cache: ModuleFileCache,
|
||||||
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
||||||
firIdeProvider: FirIdeProvider,
|
|
||||||
): ReanalyzablePropertyStructureElement {
|
): ReanalyzablePropertyStructureElement {
|
||||||
val originalProperty = firSymbol.fir
|
val originalProperty = firSymbol.fir
|
||||||
val designation = originalProperty.collectDesignation()
|
val designation = originalProperty.collectDesignation()
|
||||||
|
|
||||||
val temporaryProperty = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
val temporaryProperty = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
||||||
session = originalProperty.moduleData.session,
|
session = originalProperty.moduleData.session,
|
||||||
scopeProvider = originalProperty.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
scopeProvider = originalProperty.moduleData.session.kotlinScopeProvider,
|
||||||
designation = designation,
|
designation = designation,
|
||||||
rootNonLocalDeclaration = newKtDeclaration,
|
rootNonLocalDeclaration = newKtDeclaration,
|
||||||
) as FirProperty
|
) as FirProperty
|
||||||
|
|||||||
+4
-4
@@ -9,7 +9,6 @@ import kotlinx.collections.immutable.PersistentList
|
|||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toPersistentList
|
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.api.FirDeclarationDesignation
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
|
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.getExplicitBackingField
|
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.FirLazyBlock
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirLazyExpression
|
import org.jetbrains.kotlin.fir.expressions.impl.FirLazyExpression
|
||||||
import org.jetbrains.kotlin.fir.psi
|
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.FirTransformer
|
||||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
@@ -41,7 +41,7 @@ internal object FirLazyBodiesCalculator {
|
|||||||
if (simpleFunction.body !is FirLazyBlock) return
|
if (simpleFunction.body !is FirLazyBlock) return
|
||||||
val newFunction = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
val newFunction = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
||||||
session = simpleFunction.moduleData.session,
|
session = simpleFunction.moduleData.session,
|
||||||
scopeProvider = simpleFunction.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
scopeProvider = simpleFunction.moduleData.session.kotlinScopeProvider,
|
||||||
designation = designation,
|
designation = designation,
|
||||||
rootNonLocalDeclaration = simpleFunction.psi as KtNamedFunction,
|
rootNonLocalDeclaration = simpleFunction.psi as KtNamedFunction,
|
||||||
) as FirSimpleFunction
|
) as FirSimpleFunction
|
||||||
@@ -58,7 +58,7 @@ internal object FirLazyBodiesCalculator {
|
|||||||
|
|
||||||
val newFunction = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
val newFunction = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
||||||
session = secondaryConstructor.moduleData.session,
|
session = secondaryConstructor.moduleData.session,
|
||||||
scopeProvider = secondaryConstructor.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
scopeProvider = secondaryConstructor.moduleData.session.kotlinScopeProvider,
|
||||||
designation = designation,
|
designation = designation,
|
||||||
rootNonLocalDeclaration = secondaryConstructor.psi as KtSecondaryConstructor,
|
rootNonLocalDeclaration = secondaryConstructor.psi as KtSecondaryConstructor,
|
||||||
) as FirSimpleFunction
|
) as FirSimpleFunction
|
||||||
@@ -74,7 +74,7 @@ internal object FirLazyBodiesCalculator {
|
|||||||
|
|
||||||
val newProperty = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
val newProperty = RawFirNonLocalDeclarationBuilder.buildWithFunctionSymbolRebind(
|
||||||
session = firProperty.moduleData.session,
|
session = firProperty.moduleData.session,
|
||||||
scopeProvider = firProperty.moduleData.session.firIdeProvider.kotlinScopeProvider,
|
scopeProvider = firProperty.moduleData.session.kotlinScopeProvider,
|
||||||
designation = designation,
|
designation = designation,
|
||||||
rootNonLocalDeclaration = firProperty.psi as KtProperty
|
rootNonLocalDeclaration = firProperty.psi as KtProperty
|
||||||
) as FirProperty
|
) 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.FirFileBuilder
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
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.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.FirFileAnnotationsResolveTransformer
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.FirProviderInterceptorForIDE
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.FirProviderInterceptorForIDE
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LazyTransformerFactory
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LazyTransformerFactory
|
||||||
@@ -114,6 +113,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
|||||||
moduleFileCache: ModuleFileCache,
|
moduleFileCache: ModuleFileCache,
|
||||||
toPhase: FirResolvePhase,
|
toPhase: FirResolvePhase,
|
||||||
scopeSession: ScopeSession,
|
scopeSession: ScopeSession,
|
||||||
|
collector: FirTowerDataContextCollector? = null,
|
||||||
checkPCE: Boolean = false,
|
checkPCE: Boolean = false,
|
||||||
) {
|
) {
|
||||||
if (toPhase == FirResolvePhase.RAW_FIR) return
|
if (toPhase == FirResolvePhase.RAW_FIR) return
|
||||||
@@ -126,6 +126,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
|||||||
firFile = firFile,
|
firFile = firFile,
|
||||||
moduleFileCache = moduleFileCache,
|
moduleFileCache = moduleFileCache,
|
||||||
toPhase = toPhase,
|
toPhase = toPhase,
|
||||||
|
collector = collector,
|
||||||
scopeSession = scopeSession,
|
scopeSession = scopeSession,
|
||||||
checkPCE = checkPCE,
|
checkPCE = checkPCE,
|
||||||
)
|
)
|
||||||
@@ -185,7 +186,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
|||||||
scopeSession = scopeSession,
|
scopeSession = scopeSession,
|
||||||
moduleFileCache = moduleFileCache,
|
moduleFileCache = moduleFileCache,
|
||||||
lazyDeclarationResolver = this,
|
lazyDeclarationResolver = this,
|
||||||
towerDataContextCollector = null,
|
towerDataContextCollector = collector,
|
||||||
firProviderInterceptor = null,
|
firProviderInterceptor = null,
|
||||||
checkPCE = checkPCE,
|
checkPCE = checkPCE,
|
||||||
)
|
)
|
||||||
@@ -298,14 +299,14 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
|||||||
|
|
||||||
declarationToResolve = enumEntry.findSourceNonLocalFirDeclaration(
|
declarationToResolve = enumEntry.findSourceNonLocalFirDeclaration(
|
||||||
firFileBuilder,
|
firFileBuilder,
|
||||||
firDeclarationToResolve.moduleData.session.firIdeProvider.symbolProvider,
|
firDeclarationToResolve.moduleData.session.firProvider.symbolProvider,
|
||||||
moduleFileCache
|
moduleFileCache
|
||||||
)
|
)
|
||||||
neededPhase = FirResolvePhase.BODY_RESOLVE
|
neededPhase = FirResolvePhase.BODY_RESOLVE
|
||||||
} else {
|
} else {
|
||||||
declarationToResolve = nonLocalDeclaration.findSourceNonLocalFirDeclaration(
|
declarationToResolve = nonLocalDeclaration.findSourceNonLocalFirDeclaration(
|
||||||
firFileBuilder,
|
firFileBuilder,
|
||||||
firDeclarationToResolve.moduleData.session.firIdeProvider.symbolProvider,
|
firDeclarationToResolve.moduleData.session.firProvider.symbolProvider,
|
||||||
moduleFileCache
|
moduleFileCache
|
||||||
)
|
)
|
||||||
neededPhase = toPhase
|
neededPhase = toPhase
|
||||||
|
|||||||
+1
@@ -30,3 +30,4 @@ internal class FirIdeLibrariesSessionProvider(
|
|||||||
|
|
||||||
private fun shouldNotBeCalled(): Nothing = error("Should not be called for 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
|
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
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.FirPhaseRunner
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeFirPhaseManager
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeFirPhaseManager
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeSessionComponents
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeSessionComponents
|
||||||
@@ -60,12 +62,12 @@ internal object FirIdeSessionFactory {
|
|||||||
firPhaseRunner: FirPhaseRunner,
|
firPhaseRunner: FirPhaseRunner,
|
||||||
sessionInvalidator: FirSessionInvalidator,
|
sessionInvalidator: FirSessionInvalidator,
|
||||||
builtinTypes: BuiltinTypes,
|
builtinTypes: BuiltinTypes,
|
||||||
sessionsCache: MutableMap<KtSourceModule, FirIdeSourcesSession>,
|
sessionsCache: MutableMap<KtModule, LLFirResolvableModuleSession>,
|
||||||
isRootModule: Boolean,
|
isRootModule: Boolean,
|
||||||
librariesCache: LibrariesCache,
|
librariesCache: LibrariesCache,
|
||||||
configureSession: (FirIdeSession.() -> Unit)? = null
|
configureSession: (FirIdeSession.() -> Unit)? = null
|
||||||
): FirIdeSourcesSession {
|
): FirIdeSourcesSession {
|
||||||
sessionsCache[module]?.let { return it }
|
sessionsCache[module]?.let { return it as FirIdeSourcesSession }
|
||||||
val languageVersionSettings = module.languageVersionSettings
|
val languageVersionSettings = module.languageVersionSettings
|
||||||
val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
||||||
val firBuilder = FirFileBuilder(scopeProvider, firPhaseRunner)
|
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(
|
val dependencyList = DependencyListForCliModule.build(
|
||||||
Name.special("<${sourceModule.moduleDescription}>"),
|
Name.special("<${sourceModule.moduleDescription}>"),
|
||||||
sourceModule.platform,
|
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) {
|
private fun FirIdeSession.registerIdeComponents(project: Project) {
|
||||||
register(IdeSessionComponents::class, IdeSessionComponents.create(this))
|
register(IdeSessionComponents::class, IdeSessionComponents.create(this))
|
||||||
register(FirCachesFactory::class, FirThreadSafeCachesFactory)
|
register(FirCachesFactory::class, FirThreadSafeCachesFactory)
|
||||||
|
|||||||
+4
-4
@@ -17,8 +17,8 @@ import org.jetbrains.kotlin.fir.FirSessionProvider
|
|||||||
@Immutable
|
@Immutable
|
||||||
class FirIdeSessionProvider internal constructor(
|
class FirIdeSessionProvider internal constructor(
|
||||||
val project: Project,
|
val project: Project,
|
||||||
internal val rootModuleSession: FirIdeSourcesSession,
|
internal val rootModuleSession: LLFirResolvableModuleSession,
|
||||||
val sessions: Map<KtSourceModule, FirIdeSession>
|
val sessions: Map<KtModule, LLFirResolvableModuleSession>
|
||||||
) : FirSessionProvider() {
|
) : FirSessionProvider() {
|
||||||
override fun getSession(moduleData: FirModuleData): FirSession? =
|
override fun getSession(moduleData: FirModuleData): FirSession? =
|
||||||
sessions[moduleData.module]
|
sessions[moduleData.module]
|
||||||
@@ -26,6 +26,6 @@ class FirIdeSessionProvider internal constructor(
|
|||||||
fun getSession(module: KtModule): FirSession? =
|
fun getSession(module: KtModule): FirSession? =
|
||||||
sessions[module]
|
sessions[module]
|
||||||
|
|
||||||
internal fun getModuleCache(module: KtSourceModule): ModuleFileCache =
|
internal fun getModuleCache(module: KtModule): ModuleFileCache =
|
||||||
(sessions.getValue(module) as FirIdeSourcesSession).cache
|
sessions.getValue(module).cache
|
||||||
}
|
}
|
||||||
|
|||||||
+53
-32
@@ -6,51 +6,71 @@
|
|||||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.util.ModificationTracker
|
||||||
import kotlinx.collections.immutable.PersistentMap
|
import kotlinx.collections.immutable.PersistentMap
|
||||||
import kotlinx.collections.immutable.persistentMapOf
|
import kotlinx.collections.immutable.persistentMapOf
|
||||||
import kotlinx.collections.immutable.toPersistentMap
|
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.FirPhaseRunner
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.addValueFor
|
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.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.KtModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
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
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
class FirIdeSessionProviderStorage(val project: Project) {
|
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() }
|
private val librariesCache by softCachedValue(project, project.createLibrariesModificationTracker()) { LibrariesCache() }
|
||||||
|
|
||||||
fun getSessionProvider(
|
fun getSessionProvider(
|
||||||
rootModule: KtSourceModule,
|
rootModule: KtModule,
|
||||||
configureSession: (FirIdeSession.() -> Unit)? = null
|
configureSession: (FirIdeSession.() -> Unit)? = null
|
||||||
): FirIdeSessionProvider {
|
): FirIdeSessionProvider {
|
||||||
val firPhaseRunner = FirPhaseRunner()
|
val firPhaseRunner = FirPhaseRunner()
|
||||||
|
|
||||||
val builtinTypes = BuiltinTypes()
|
val builtinTypes = BuiltinTypes()
|
||||||
val builtinsAndCloneableSession = FirIdeSessionFactory.createBuiltinsAndCloneableSession(project, 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, session) = cache.withMappings(project) { mappings ->
|
||||||
val sessions = mutableMapOf<KtSourceModule, FirIdeSourcesSession>().apply { putAll(mappings) }
|
val sessions = mutableMapOf<KtModule, LLFirResolvableModuleSession>().apply { putAll(mappings) }
|
||||||
val session = executeWithoutPCE {
|
val session = executeWithoutPCE {
|
||||||
FirIdeSessionFactory.createSourcesSession(
|
when (rootModule) {
|
||||||
project,
|
is KtSourceModule -> {
|
||||||
rootModule,
|
FirIdeSessionFactory.createSourcesSession(
|
||||||
builtinsAndCloneableSession,
|
project,
|
||||||
firPhaseRunner,
|
rootModule,
|
||||||
cache.sessionInvalidator,
|
builtinsAndCloneableSession,
|
||||||
builtinTypes,
|
firPhaseRunner,
|
||||||
sessions,
|
cache.sessionInvalidator,
|
||||||
isRootModule = true,
|
builtinTypes,
|
||||||
librariesCache = librariesCache,
|
sessions,
|
||||||
configureSession = configureSession,
|
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
|
sessions to session
|
||||||
}
|
}
|
||||||
@@ -59,11 +79,9 @@ class FirIdeSessionProviderStorage(val project: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FromModuleViewSessionCache(
|
private class FromModuleViewSessionCache {
|
||||||
val root: KtSourceModule,
|
|
||||||
) {
|
|
||||||
@Volatile
|
@Volatile
|
||||||
private var mappings: PersistentMap<KtSourceModule, FirSessionWithModificationTracker> = persistentMapOf()
|
private var mappings: PersistentMap<KtModule, FirSessionWithModificationTracker> = persistentMapOf()
|
||||||
|
|
||||||
val sessionInvalidator: FirSessionInvalidator = FirSessionInvalidator { session ->
|
val sessionInvalidator: FirSessionInvalidator = FirSessionInvalidator { session ->
|
||||||
mappings[session.moduleData.module]?.invalidate()
|
mappings[session.moduleData.module]?.invalidate()
|
||||||
@@ -72,15 +90,15 @@ private class FromModuleViewSessionCache(
|
|||||||
|
|
||||||
inline fun <R> withMappings(
|
inline fun <R> withMappings(
|
||||||
project: Project,
|
project: Project,
|
||||||
action: (Map<KtSourceModule, FirIdeSourcesSession>) -> Pair<Map<KtSourceModule, FirIdeSourcesSession>, R>
|
action: (Map<KtModule, LLFirResolvableModuleSession>) -> Pair<Map<KtModule, LLFirResolvableModuleSession>, R>
|
||||||
): Pair<Map<KtSourceModule, FirIdeSourcesSession>, R> {
|
): Pair<Map<KtModule, LLFirResolvableModuleSession>, R> {
|
||||||
val (newMappings, result) = action(getSessions().mapValues { it.value })
|
val (newMappings, result) = action(getSessions().mapValues { it.value })
|
||||||
mappings = newMappings.mapValues { FirSessionWithModificationTracker(project, it.value) }.toPersistentMap()
|
mappings = newMappings.mapValues { FirSessionWithModificationTracker(project, it.value) }.toPersistentMap()
|
||||||
return newMappings to result
|
return newMappings to result
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
private fun getSessions(): Map<KtSourceModule, FirIdeSourcesSession> = buildMap {
|
private fun getSessions(): Map<KtModule, LLFirResolvableModuleSession> = buildMap {
|
||||||
val sessions = mappings.values
|
val sessions = mappings.values
|
||||||
val wasSessionInvalidated = sessions.associateWithTo(hashMapOf()) { false }
|
val wasSessionInvalidated = sessions.associateWithTo(hashMapOf()) { false }
|
||||||
|
|
||||||
@@ -122,10 +140,13 @@ private class FromModuleViewSessionCache(
|
|||||||
|
|
||||||
private class FirSessionWithModificationTracker(
|
private class FirSessionWithModificationTracker(
|
||||||
project: Project,
|
project: Project,
|
||||||
val firSession: FirIdeSourcesSession,
|
val firSession: LLFirResolvableModuleSession,
|
||||||
) {
|
) {
|
||||||
private val modificationTracker =
|
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
|
private val timeStamp = modificationTracker.modificationCount
|
||||||
|
|
||||||
@@ -139,7 +160,7 @@ private class FirSessionWithModificationTracker(
|
|||||||
val isValid: Boolean get() = !isInvalidated && modificationTracker.modificationCount == timeStamp
|
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.moduleUnsafe(): T = (this as KtModuleBasedModuleData).module as T
|
||||||
internal inline fun <reified T : KtModule> FirModuleData.moduleInfoSafe(): 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
|
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
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.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.analysis.project.structure.KtSourceModule
|
||||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||||
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||||
|
|
||||||
@OptIn(PrivateSessionConstructor::class)
|
|
||||||
internal class FirIdeSourcesSession @PrivateSessionConstructor constructor(
|
internal class FirIdeSourcesSession @PrivateSessionConstructor constructor(
|
||||||
override val module: KtSourceModule,
|
override val module: KtSourceModule,
|
||||||
override val project: Project,
|
override val project: Project,
|
||||||
val firFileBuilder: FirFileBuilder,
|
override val firFileBuilder: FirFileBuilder,
|
||||||
builtinTypes: BuiltinTypes,
|
builtinTypes: BuiltinTypes,
|
||||||
) : FirIdeModuleSession(builtinTypes, Kind.Source) {
|
) : LLFirResolvableModuleSession(builtinTypes)
|
||||||
val cache get() = firIdeProvider.cache
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
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) {
|
fun invalidate(session: FirSession) {
|
||||||
require(session is FirIdeSourcesSession)
|
require(session is LLFirResolvableModuleSession)
|
||||||
invalidateSourcesSession(session)
|
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
|
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 org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
@JvmInline
|
@JvmInline
|
||||||
internal value class LibrariesCache(
|
internal value class LibrariesCache(
|
||||||
private val cache: ConcurrentHashMap<KtSourceModule, FirIdeLibrariesSession> = ConcurrentHashMap()
|
private val cache: ConcurrentHashMap<KtModule, FirIdeLibrariesSession> = ConcurrentHashMap()
|
||||||
) {
|
) {
|
||||||
fun cached(
|
fun cached(
|
||||||
moduleSourceInfo: KtSourceModule,
|
module: KtModule,
|
||||||
create: (KtSourceModule) -> FirIdeLibrariesSession
|
create: (KtModule) -> FirIdeLibrariesSession
|
||||||
): 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 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.DiagnosticCheckerFilter
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.DiagnosticsCollector
|
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.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.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.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.KtLibraryModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
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.diagnostics.KtPsiDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
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.*
|
|
||||||
|
|
||||||
internal class FirSourceModuleResolveState(
|
internal class FirSourceModuleResolveState(
|
||||||
override val project: Project,
|
override val project: Project,
|
||||||
override val module: KtSourceModule,
|
override val module: KtModule,
|
||||||
private val sessionProvider: FirIdeSessionProvider,
|
sessionProvider: FirIdeSessionProvider,
|
||||||
val firFileBuilder: FirFileBuilder,
|
firFileBuilder: FirFileBuilder,
|
||||||
val firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
firLazyDeclarationResolver: FirLazyDeclarationResolver,
|
||||||
) : FirPhysicalModuleResolveState() {
|
) : LLFirResolvableModuleResolveState(sessionProvider, firFileBuilder, firLazyDeclarationResolver) {
|
||||||
override val rootModuleSession: FirIdeSourcesSession get() = sessionProvider.rootModuleSession
|
private val diagnosticsCollector = DiagnosticsCollector(fileStructureCache, cache)
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> =
|
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> =
|
||||||
diagnosticsCollector.getDiagnosticsFor(element, filter)
|
diagnosticsCollector.getDiagnosticsFor(element, filter)
|
||||||
@@ -82,70 +34,12 @@ internal class FirSourceModuleResolveState(
|
|||||||
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> =
|
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> =
|
||||||
diagnosticsCollector.collectDiagnosticsForFile(ktFile, filter)
|
diagnosticsCollector.collectDiagnosticsForFile(ktFile, filter)
|
||||||
|
|
||||||
override fun resolveToFirSymbol(
|
override fun getModuleKind(module: KtModule): ModuleKind {
|
||||||
ktDeclaration: KtDeclaration,
|
return when (module) {
|
||||||
phase: FirResolvePhase
|
is KtSourceModule -> ModuleKind.RESOLVABLE_MODULE
|
||||||
): FirBasedSymbol<*> {
|
is KtLibraryModule -> ModuleKind.BINARY_MODULE
|
||||||
return when (val module = ktDeclaration.getKtModule()) {
|
else -> unexpectedElementError("module", module)
|
||||||
is KtSourceModule -> findSourceFirSymbol(ktDeclaration).also { resolveFirToPhase(it.fir, phase) }
|
|
||||||
is KtLibraryModule -> findFirCompiledSymbol(ktDeclaration)
|
|
||||||
else -> error("unsupported 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.expressions.impl.FirLazyExpression
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
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.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.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.psi.KtFile
|
||||||
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
|
|
||||||
abstract class AbstractFirLazyBodiesCalculatorTest : AbstractLowLevelApiSingleFileTest() {
|
abstract class AbstractFirLazyBodiesCalculatorTest : AbstractLowLevelApiSingleFileTest() {
|
||||||
|
|
||||||
private val lazyChecker = object : FirVisitorVoid() {
|
private val lazyChecker = object : FirVisitorVoid() {
|
||||||
override fun visitElement(element: FirElement) {
|
override fun visitElement(element: FirElement) {
|
||||||
TestCase.assertFalse("${FirLazyBlock::class.qualifiedName} should not present in the tree", element is FirLazyBlock)
|
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) {
|
override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) {
|
||||||
resolveWithClearCaches(ktFile) { resolveState ->
|
resolveWithClearCaches(ktFile) { resolveState ->
|
||||||
val session = resolveState.rootModuleSession
|
val session = resolveState.rootModuleSession
|
||||||
val provider = session.firIdeProvider.kotlinScopeProvider
|
val provider = session.kotlinScopeProvider
|
||||||
|
|
||||||
val laziedFirFile = RawFirBuilder(
|
val laziedFirFile = RawFirBuilder(
|
||||||
session,
|
session,
|
||||||
@@ -59,5 +58,4 @@ abstract class AbstractFirLazyBodiesCalculatorTest : AbstractLowLevelApiSingleFi
|
|||||||
TestCase.assertEquals(laziedFirFileDump, fullFirFileDump)
|
TestCase.assertEquals(laziedFirFileDump, fullFirFileDump)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+1
-1
@@ -43,7 +43,7 @@ abstract class AbstractFirContextCollectionTest : AbstractLowLevelApiSingleFileT
|
|||||||
) { resolveState ->
|
) { resolveState ->
|
||||||
check(resolveState is FirSourceModuleResolveState)
|
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()
|
val allStructureElements = fileStructure.getAllStructureElements()
|
||||||
|
|
||||||
handler.elementsToCheckContext = allStructureElements.map { it.getFirDeclaration() }
|
handler.elementsToCheckContext = allStructureElements.map { it.getFirDeclaration() }
|
||||||
|
|||||||
+1
-1
@@ -88,7 +88,7 @@ abstract class AbstractFileStructureTest : AbstractLowLevelApiSingleFileTest() {
|
|||||||
val moduleResolveState = getResolveState() as FirSourceModuleResolveState
|
val moduleResolveState = getResolveState() as FirSourceModuleResolveState
|
||||||
return moduleResolveState.fileStructureCache.getFileStructure(
|
return moduleResolveState.fileStructureCache.getFileStructure(
|
||||||
ktFile = this,
|
ktFile = this,
|
||||||
moduleFileCache = moduleResolveState.rootModuleSession.cache
|
moduleFileCache = moduleResolveState.cache
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user