[FIR IDE] LowLevel api refactoring
This commit is contained in:
committed by
TeamCityServer
parent
445f13d1bf
commit
633e03b710
+3
-3
@@ -43,7 +43,7 @@ class FirSupertypeResolverProcessor(session: FirSession, scopeSession: ScopeSess
|
||||
/**
|
||||
* Interceptor needed by IDE to resolve in-air created declarations.
|
||||
*/
|
||||
interface FirProviderInterceptorForSupertypeResolver {
|
||||
interface FirProviderInterceptor {
|
||||
fun getFirClassifierContainerFileIfAny(symbol: FirClassLikeSymbol<*>): FirFile?
|
||||
fun getFirClassifierByFqName(classId: ClassId): FirClassLikeDeclaration<*>?
|
||||
}
|
||||
@@ -74,7 +74,7 @@ fun <F : FirClassLikeDeclaration<F>> F.runSupertypeResolvePhaseForLocalClass(
|
||||
scopeSession: ScopeSession,
|
||||
currentScopeList: List<FirScope>,
|
||||
localClassesNavigationInfo: LocalClassesNavigationInfo,
|
||||
firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?,
|
||||
firProviderInterceptor: FirProviderInterceptor?,
|
||||
): F {
|
||||
val supertypeComputationSession = SupertypeComputationSession()
|
||||
val supertypeResolverVisitor = FirSupertypeResolverVisitor(
|
||||
@@ -189,7 +189,7 @@ class FirSupertypeResolverVisitor(
|
||||
private val scopeSession: ScopeSession,
|
||||
private val scopeForLocalClass: PersistentList<FirScope>? = null,
|
||||
private val localClassesNavigationInfo: LocalClassesNavigationInfo? = null,
|
||||
private val firProviderInterceptor: FirProviderInterceptorForSupertypeResolver? = null,
|
||||
private val firProviderInterceptor: FirProviderInterceptor? = null,
|
||||
) : FirDefaultVisitor<Unit, Any?>() {
|
||||
private val supertypeGenerationExtensions = session.extensionService.supertypeGenerators
|
||||
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowAnalyzerContext
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptorForSupertypeResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve
|
||||
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
|
||||
@@ -33,7 +33,7 @@ open class FirBodyResolveTransformer(
|
||||
val returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve(),
|
||||
outerBodyResolveContext: BodyResolveContext? = null,
|
||||
val firTowerDataContextCollector: FirTowerDataContextCollector? = null,
|
||||
val firProviderInterceptor: FirProviderInterceptorForSupertypeResolver? = null,
|
||||
val firProviderInterceptor: FirProviderInterceptor? = null,
|
||||
) : FirAbstractBodyResolveTransformer(phase) {
|
||||
|
||||
final override val context: BodyResolveContext =
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptorForSupertypeResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.runStatusResolveForLocalClass
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.runSupertypeResolvePhaseForLocalClass
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.runTypeResolvePhaseForLocalClass
|
||||
@@ -20,7 +20,7 @@ fun <F : FirClassLikeDeclaration<F>> F.runAllPhasesForLocalClass(
|
||||
components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents,
|
||||
resolutionMode: ResolutionMode,
|
||||
firTowerDataContextCollector: FirTowerDataContextCollector?,
|
||||
firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?,
|
||||
firProviderInterceptor: FirProviderInterceptor?,
|
||||
): F {
|
||||
if (this.resolvePhase > FirResolvePhase.RAW_FIR) return this
|
||||
if (this is FirRegularClass) {
|
||||
|
||||
+5
-5
@@ -58,13 +58,13 @@ internal class FirModuleResolveStateDepended(
|
||||
)
|
||||
}
|
||||
|
||||
override fun getFirFile(ktFile: KtFile): FirFile =
|
||||
originalState.getFirFile(ktFile)
|
||||
override fun getOrBuildFirFile(ktFile: KtFile): FirFile =
|
||||
originalState.getOrBuildFirFile(ktFile)
|
||||
|
||||
override fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D =
|
||||
originalState.resolvedFirToPhase(declaration, toPhase)
|
||||
override fun <D : FirDeclaration> resolveFirToPhase(declaration: D, toPhase: FirResolvePhase): D =
|
||||
originalState.resolveFirToPhase(declaration, toPhase)
|
||||
|
||||
override fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? {
|
||||
override fun tryGetCachedFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? {
|
||||
val ktFile = declaration.containingKtFileIfAny ?: return null
|
||||
cache.getCachedFirFile(ktFile)?.let { return it }
|
||||
ktFile.originalKtFile?.let(cache::getCachedFirFile)?.let { return it }
|
||||
|
||||
+5
-12
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.idea.fir.low.level.api
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||
@@ -60,20 +59,18 @@ internal class FirModuleResolveStateImpl(
|
||||
override fun getOrBuildFirFor(element: KtElement): FirElement =
|
||||
elementBuilder.getOrBuildFirFor(element, firFileBuilder, rootModuleSession.cache, fileStructureCache)
|
||||
|
||||
override fun getFirFile(ktFile: KtFile): FirFile =
|
||||
override fun getOrBuildFirFile(ktFile: KtFile): FirFile =
|
||||
firFileBuilder.buildRawFirFileWithCaching(ktFile, rootModuleSession.cache, lazyBodiesMode = false)
|
||||
|
||||
override fun tryGetCachedFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? =
|
||||
cache.getContainerFirFile(declaration)
|
||||
|
||||
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<FirPsiDiagnostic<*>> =
|
||||
diagnosticsCollector.getDiagnosticsFor(element, filter)
|
||||
|
||||
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic<*>> =
|
||||
diagnosticsCollector.collectDiagnosticsForFile(ktFile, filter)
|
||||
|
||||
internal fun getBuiltFirFileOrNull(ktFile: KtFile): FirFile? {
|
||||
val cache = sessionProvider.getModuleCache(ktFile.getModuleInfo() as ModuleSourceInfo)
|
||||
return firFileBuilder.getBuiltFirFileOrNull(ktFile, cache)
|
||||
}
|
||||
|
||||
@OptIn(InternalForInline::class)
|
||||
override fun findSourceFirDeclaration(ktDeclaration: KtDeclaration): FirDeclaration =
|
||||
findSourceFirDeclarationByExpression(ktDeclaration)
|
||||
@@ -117,7 +114,7 @@ internal class FirModuleResolveStateImpl(
|
||||
?: error("FirDeclaration was not found for\n${ktDeclaration.getElementTextInContext()}")
|
||||
}
|
||||
|
||||
override fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D {
|
||||
override fun <D : FirDeclaration> resolveFirToPhase(declaration: D, toPhase: FirResolvePhase): D {
|
||||
val fileCache = when (val session = declaration.moduleData.session) {
|
||||
is FirIdeSourcesSession -> session.cache
|
||||
else -> return declaration
|
||||
@@ -127,11 +124,7 @@ internal class FirModuleResolveStateImpl(
|
||||
fileCache,
|
||||
toPhase,
|
||||
checkPCE = true,
|
||||
towerDataContextCollector = null,
|
||||
)
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? =
|
||||
cache.getContainerFirFile(declaration)
|
||||
}
|
||||
+5
-12
@@ -58,11 +58,11 @@ object DeclarationCopyBuilder {
|
||||
val originalFunction = rootNonLocalDeclaration.getOrBuildFirOfType<FirSimpleFunction>(state)
|
||||
val builtFunction = createCopy(rootNonLocalDeclaration, originalFunction, replacement)
|
||||
|
||||
//TODO Check do we really need this optimisation? Maybe it is not optimisation at all because of Kt travers?
|
||||
val functionBlock = rootNonLocalDeclaration.bodyBlockExpression
|
||||
if (functionBlock == null || !PsiTreeUtil.isAncestor(functionBlock, replacement.from, true)) {
|
||||
return builtFunction
|
||||
}
|
||||
//TODO Check do we really need this optimisation? Maybe it is not optimisation at all because of Kt travers?
|
||||
|
||||
// right now we can't resolve builtFunction header properly, as it built right in air,
|
||||
// without file, which is now required for running stages other then body resolve, so we
|
||||
@@ -82,11 +82,11 @@ object DeclarationCopyBuilder {
|
||||
val originalFirClass = rootNonLocalDeclaration.getOrBuildFirOfType<FirRegularClass>(state)
|
||||
val builtClass = createCopy(rootNonLocalDeclaration, originalFirClass, replacement)
|
||||
|
||||
//TODO Check do we really need this optimisation? Maybe it is not optimisation at all because of Kt travers?
|
||||
val classBody = rootNonLocalDeclaration.body
|
||||
if (classBody == null || !PsiTreeUtil.isAncestor(classBody, replacement.from, true)) {
|
||||
return builtClass
|
||||
}
|
||||
//TODO Check do we really need this optimisation? Maybe it is not optimisation at all because of Kt travers?
|
||||
|
||||
return buildRegularClassCopy(originalFirClass) {
|
||||
declarations.clear()
|
||||
@@ -102,16 +102,8 @@ object DeclarationCopyBuilder {
|
||||
state: FirModuleResolveState,
|
||||
replacement: RawFirReplacement<T>,
|
||||
): FirTypeAlias {
|
||||
|
||||
val originalFirTypeAlias = rootNonLocalDeclaration.getOrBuildFirOfType<FirTypeAlias>(state)
|
||||
val builtTypeAlias = createCopy(rootNonLocalDeclaration, originalFirTypeAlias, replacement)
|
||||
return builtTypeAlias
|
||||
|
||||
// return buildTypeAliasCopy(originalFirTypeAlias) {
|
||||
// expandedTypeRef = builtTypeAlias.expandedTypeRef
|
||||
// symbol = builtTypeAlias.symbol
|
||||
// initDeclaration(originalFirTypeAlias, builtTypeAlias, state)
|
||||
// }
|
||||
return createCopy(rootNonLocalDeclaration, originalFirTypeAlias, replacement)
|
||||
}
|
||||
|
||||
private fun <T : KtElement> createPropertyCopy(
|
||||
@@ -122,7 +114,6 @@ object DeclarationCopyBuilder {
|
||||
val originalProperty = rootNonLocalDeclaration.getOrBuildFirOfType<FirProperty>(state)
|
||||
val builtProperty = createCopy(rootNonLocalDeclaration, originalProperty, replacement)
|
||||
|
||||
//TODO Check do we really need this optimisation? Maybe it is not optimisation at all because of Kt travers?
|
||||
val insideGetterBody = rootNonLocalDeclaration.getter?.bodyBlockExpression?.let {
|
||||
PsiTreeUtil.isAncestor(it, replacement.from, true)
|
||||
} ?: false
|
||||
@@ -133,6 +124,8 @@ object DeclarationCopyBuilder {
|
||||
|
||||
if (!insideSetterBody) return builtProperty
|
||||
}
|
||||
//TODO Check do we really need this optimisation? Maybe it is not optimisation at all because of Kt travers?
|
||||
|
||||
|
||||
val originalSetter = originalProperty.setter
|
||||
val builtSetter = builtProperty.setter
|
||||
|
||||
+17
-8
@@ -29,9 +29,22 @@ abstract class FirModuleResolveState {
|
||||
|
||||
internal abstract fun getSessionFor(moduleInfo: IdeaModuleInfo): FirSession
|
||||
|
||||
/**
|
||||
* Build fully resolved FIR node for requested element.
|
||||
* This operation could be performance affective, use
|
||||
* @see tryGetCachedFirFile to get [FirFile] in undefined phase
|
||||
*/
|
||||
internal abstract fun getOrBuildFirFor(element: KtElement): FirElement
|
||||
|
||||
internal abstract fun getFirFile(ktFile: KtFile): FirFile
|
||||
/**
|
||||
* Get or build or get cached [FirFile] for requested file in undefined phase
|
||||
*/
|
||||
internal abstract fun getOrBuildFirFile(ktFile: KtFile): FirFile
|
||||
|
||||
/**
|
||||
* Try get [FirFile] from the cache in undefined phase
|
||||
*/
|
||||
internal abstract fun tryGetCachedFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile?
|
||||
|
||||
internal abstract fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<FirPsiDiagnostic<*>>
|
||||
|
||||
@@ -41,11 +54,9 @@ abstract class FirModuleResolveState {
|
||||
val originalDeclaration = (declaration as? FirCallableDeclaration<*>)?.unwrapFakeOverrides() ?: declaration
|
||||
val session = originalDeclaration.moduleData.session
|
||||
return when {
|
||||
originalDeclaration.origin == FirDeclarationOrigin.Source
|
||||
&& session is FirIdeSourcesSession
|
||||
-> {
|
||||
originalDeclaration.origin == FirDeclarationOrigin.Source && session is FirIdeSourcesSession -> {
|
||||
val cache = session.cache
|
||||
val file = getFirFile(declaration, cache)
|
||||
val file = tryGetCachedFirFile(declaration, cache)
|
||||
?: error("Fir file was not found for\n${declaration.render()}\n${(declaration.psi as? KtElement)?.getElementTextInContext()}")
|
||||
cache.firFileLockProvider.withLock(file, declarationLockType) { action(declaration) }
|
||||
}
|
||||
@@ -63,7 +74,5 @@ abstract class FirModuleResolveState {
|
||||
ktDeclaration: KtLambdaExpression,
|
||||
): FirDeclaration
|
||||
|
||||
internal abstract fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D
|
||||
|
||||
internal abstract fun getFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile?
|
||||
internal abstract fun <D : FirDeclaration> resolveFirToPhase(declaration: D, toPhase: FirResolvePhase): D
|
||||
}
|
||||
+8
-8
@@ -8,15 +8,10 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.api
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
|
||||
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.FirIdeResolveStateService
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.InternalForInline
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSourcesSession
|
||||
import org.jetbrains.kotlin.idea.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -118,12 +113,14 @@ fun <D : FirDeclaration, R> D.withFirDeclarationInWriteLock(
|
||||
|
||||
/**
|
||||
* Returns a list of Diagnostics compiler finds for given [KtElement]
|
||||
* This operation could be performance affective
|
||||
*/
|
||||
fun KtElement.getDiagnostics(resolveState: FirModuleResolveState, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic<*>> =
|
||||
resolveState.getDiagnostics(this, filter)
|
||||
|
||||
/**
|
||||
* Returns a list of Diagnostics compiler finds for given [KtFile]
|
||||
* This operation could be performance affective
|
||||
*/
|
||||
fun KtFile.collectDiagnosticsForFile(
|
||||
resolveState: FirModuleResolveState,
|
||||
@@ -140,12 +137,13 @@ fun <D : FirDeclaration> D.resolvedFirToPhase(
|
||||
phase: FirResolvePhase,
|
||||
resolveState: FirModuleResolveState
|
||||
): D =
|
||||
resolveState.resolvedFirToPhase(this, phase)
|
||||
resolveState.resolveFirToPhase(this, phase)
|
||||
|
||||
|
||||
/**
|
||||
* Get a [FirElement] which was created by [KtElement]
|
||||
* Returned [FirElement] is guaranteed to be resolved to [FirResolvePhase.BODY_RESOLVE] phase
|
||||
* This operation could be performance affective
|
||||
*/
|
||||
fun KtElement.getOrBuildFir(
|
||||
resolveState: FirModuleResolveState,
|
||||
@@ -154,6 +152,7 @@ fun KtElement.getOrBuildFir(
|
||||
/**
|
||||
* Get a [FirElement] which was created by [KtElement], but only if it is subtype of [E], `null` otherwise
|
||||
* Returned [FirElement] is guaranteed to be resolved to [FirResolvePhase.BODY_RESOLVE] phase
|
||||
* This operation could be performance affective
|
||||
*/
|
||||
inline fun <reified E : FirElement> KtElement.getOrBuildFirSafe(
|
||||
resolveState: FirModuleResolveState,
|
||||
@@ -162,6 +161,7 @@ inline fun <reified E : FirElement> KtElement.getOrBuildFirSafe(
|
||||
/**
|
||||
* Get a [FirElement] which was created by [KtElement], but only if it is subtype of [E], throws [InvalidFirElementTypeException] otherwise
|
||||
* Returned [FirElement] is guaranteed to be resolved to [FirResolvePhase.BODY_RESOLVE] phase
|
||||
* This operation could be performance affective
|
||||
*/
|
||||
inline fun <reified E : FirElement> KtElement.getOrBuildFirOfType(
|
||||
resolveState: FirModuleResolveState,
|
||||
@@ -175,8 +175,8 @@ inline fun <reified E : FirElement> KtElement.getOrBuildFirOfType(
|
||||
* Get a [FirFile] which was created by [KtElement]
|
||||
* Returned [FirFile] can be resolved to any phase from [FirResolvePhase.RAW_FIR] to [FirResolvePhase.BODY_RESOLVE]
|
||||
*/
|
||||
fun KtFile.getFirFile(resolveState: FirModuleResolveState): FirFile =
|
||||
resolveState.getFirFile(this)
|
||||
fun KtFile.getOrBuildFirFile(resolveState: FirModuleResolveState): FirFile =
|
||||
resolveState.getOrBuildFirFile(this)
|
||||
|
||||
class InvalidFirElementTypeException(
|
||||
ktElement: KtElement,
|
||||
|
||||
+26
-30
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.api
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.psi.util.parentsOfType
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirFragmentForLazyBodiesBuilder
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirReplacement
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.realPsi
|
||||
@@ -24,7 +25,6 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FileTowerProv
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.file.structure.FirElementsRecorder
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSourcesSession
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirProviderInterceptorForIDE
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.originalDeclaration
|
||||
import org.jetbrains.kotlin.idea.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -72,8 +72,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
val declaration = runBodyResolveOnAir(
|
||||
state = state,
|
||||
replacement = RawFirReplacement(place, elementToResolve),
|
||||
collector = null,
|
||||
useFirProviderInterceptor = true
|
||||
isOnAirResolve = true,
|
||||
)
|
||||
|
||||
val expressionLocator = object : FirVisitorVoid() {
|
||||
@@ -101,8 +100,17 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
return if (place is KtFile) {
|
||||
FileTowerProvider(place, onAirGetTowerContextForFile(state, place))
|
||||
} else {
|
||||
val validPlace = PsiTreeUtil.findFirstParent(place, false) {
|
||||
RawFirFragmentForLazyBodiesBuilder.elementIsApplicable(it as KtElement)
|
||||
} as KtElement
|
||||
|
||||
FirTowerDataContextAllElementsCollector().also {
|
||||
runBodyResolveOnAir(state, collector = it, replacement = RawFirReplacement(place, place))
|
||||
runBodyResolveOnAir(
|
||||
state = state,
|
||||
collector = it,
|
||||
replacement = RawFirReplacement(validPlace, validPlace),
|
||||
isOnAirResolve = false //isOnAirResolve can be little faster because node resolved in it's context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,9 +162,9 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
val collector = FirTowerDataContextAllElementsCollector()
|
||||
val copiedFirDeclaration = runBodyResolveOnAir(
|
||||
originalState,
|
||||
collector = collector,
|
||||
replacement = RawFirReplacement(sameDeclarationInOriginalFile, dependencyNonLocalDeclaration),
|
||||
useFirProviderInterceptor = true
|
||||
isOnAirResolve = true,
|
||||
collector = collector,
|
||||
)
|
||||
|
||||
val recordedMap = FirElementsRecorder.recordElementsFrom(copiedFirDeclaration, FirElementsRecorder())
|
||||
@@ -166,8 +174,8 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
private fun <T : KtElement> runBodyResolveOnAir(
|
||||
state: FirModuleResolveStateImpl,
|
||||
replacement: RawFirReplacement<T>,
|
||||
isOnAirResolve: Boolean,
|
||||
collector: FirTowerDataContextCollector? = null,
|
||||
useFirProviderInterceptor: Boolean = false
|
||||
): FirDeclaration {
|
||||
|
||||
val nonLocalDeclaration = findEnclosingNonLocalDeclaration(replacement.from)
|
||||
@@ -179,30 +187,18 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
replacement = replacement,
|
||||
)
|
||||
|
||||
val originalFirFile = state.getBuiltFirFileOrNull(replacement.from.containingKtFile)
|
||||
?: error("Original fir file should be already built")
|
||||
val originalFirFile = state.getOrBuildFirFile(nonLocalDeclaration.containingKtFile)
|
||||
|
||||
val firProviderInterceptor =
|
||||
if (useFirProviderInterceptor) FirProviderInterceptorForIDE.createForFirElement(
|
||||
session = originalFirFile.declarationSiteSession,
|
||||
firFile = originalFirFile,
|
||||
element = copiedFirDeclaration
|
||||
) else null
|
||||
|
||||
state.firFileBuilder.runCustomResolveWithPCECheck(originalFirFile, state.rootModuleSession.cache) {
|
||||
state.firLazyDeclarationResolver.runLazyResolveWithoutLock(
|
||||
copiedFirDeclaration,
|
||||
state.rootModuleSession.cache,
|
||||
originalFirFile,
|
||||
originalFirFile.declarationSiteSession.firIdeProvider,
|
||||
fromPhase = copiedFirDeclaration.resolvePhase,
|
||||
toPhase = FirResolvePhase.BODY_RESOLVE,
|
||||
towerDataContextCollector = collector,
|
||||
checkPCE = true,
|
||||
lastNonLazyPhase = FirResolvePhase.IMPORTS,
|
||||
firProviderInterceptor = firProviderInterceptor,
|
||||
)
|
||||
}
|
||||
state.firLazyDeclarationResolver.lazyDesignatedResolveDeclaration(
|
||||
firDeclarationToResolve = copiedFirDeclaration,
|
||||
moduleFileCache = state.rootModuleSession.cache,
|
||||
containerFirFile = originalFirFile,
|
||||
provider = originalFirFile.declarationSiteSession.firIdeProvider,
|
||||
toPhase = FirResolvePhase.BODY_RESOLVE,
|
||||
checkPCE = true,
|
||||
isOnAirResolve = isOnAirResolve,
|
||||
towerDataContextCollector = collector,
|
||||
)
|
||||
|
||||
return copiedFirDeclaration
|
||||
}
|
||||
|
||||
+2
-2
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
|
||||
|
||||
internal object FirLazyBodiesCalculator {
|
||||
fun calculateLazyBodiesInside(element: FirElement, designation: FirDeclarationDesignation) {
|
||||
element.transform<FirElement, MutableList<FirDeclaration>>(
|
||||
fun calculateLazyBodiesInside(designation: FirDeclarationDesignation) {
|
||||
designation.declaration.transform<FirElement, MutableList<FirDeclaration>>(
|
||||
FirLazyBodiesCalculatorTransformer,
|
||||
designation.toSequence(includeTarget = true).toMutableList()
|
||||
)
|
||||
|
||||
+197
-58
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptorForSupertypeResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
|
||||
@@ -24,34 +24,39 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.*
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.*
|
||||
import org.jetbrains.kotlin.idea.util.ifTrue
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
|
||||
internal class FirLazyDeclarationResolver(
|
||||
private val firFileBuilder: FirFileBuilder
|
||||
) {
|
||||
/**
|
||||
* Fully resolve file annotations (synchronized)
|
||||
* @see resolveFileAnnotationsWithoutLock not synchronized
|
||||
*/
|
||||
fun resolveFileAnnotations(
|
||||
firFile: FirFile,
|
||||
moduleFileCache: ModuleFileCache,
|
||||
scopeSession: ScopeSession,
|
||||
) {
|
||||
check(firFile.resolvePhase >= FirResolvePhase.IMPORTS)
|
||||
firFileBuilder.runCustomResolveUnderLock(firFile, moduleFileCache) {
|
||||
val transformer = FirFileAnnotationsResolveTransformer(firFile.moduleData.session, scopeSession)
|
||||
firFile.accept(transformer, ResolutionMode.ContextDependent)
|
||||
}
|
||||
) = firFileBuilder.runCustomResolveUnderLock(firFile, moduleFileCache) {
|
||||
resolveFileAnnotationsWithoutLock(firFile, scopeSession)
|
||||
}
|
||||
|
||||
fun lazyResolveDeclaration(
|
||||
declaration: FirDeclaration,
|
||||
moduleFileCache: ModuleFileCache,
|
||||
toPhase: FirResolvePhase,
|
||||
towerDataContextCollector: FirTowerDataContextCollector? = null,
|
||||
checkPCE: Boolean = false,
|
||||
reresolveFile: Boolean = false,
|
||||
/**
|
||||
* Fully resolve file annotations (not synchronized)
|
||||
* @see resolveFileAnnotations synchronized version
|
||||
*/
|
||||
private fun resolveFileAnnotationsWithoutLock(
|
||||
firFile: FirFile,
|
||||
scopeSession: ScopeSession,
|
||||
) {
|
||||
if (declaration.resolvePhase >= toPhase) return
|
||||
check(firFile.resolvePhase >= FirResolvePhase.IMPORTS)
|
||||
val transformer = FirFileAnnotationsResolveTransformer(firFile.moduleData.session, scopeSession)
|
||||
firFile.accept(transformer, ResolutionMode.ContextDependent)
|
||||
}
|
||||
|
||||
private fun getResolvableDeclaration(declaration: FirDeclaration, moduleFileCache: ModuleFileCache): FirDeclaration {
|
||||
if (declaration is FirPropertyAccessor || declaration is FirTypeParameter || declaration is FirValueParameter) {
|
||||
val ktContainingResolvableDeclaration = when (val psi = declaration.psi) {
|
||||
is KtPropertyAccessor -> psi.property
|
||||
@@ -66,74 +71,105 @@ internal class FirLazyDeclarationResolver(
|
||||
null -> error("Cannot find containing declaration for KtParameter")
|
||||
else -> error("Invalid source of property accessor ${psi::class}")
|
||||
}
|
||||
val containingProperty = ktContainingResolvableDeclaration
|
||||
.findSourceNonLocalFirDeclaration(firFileBuilder, declaration.moduleData.session.symbolProvider, moduleFileCache)
|
||||
return lazyResolveDeclaration(containingProperty, moduleFileCache, toPhase, towerDataContextCollector)
|
||||
return ktContainingResolvableDeclaration.findSourceNonLocalFirDeclaration(
|
||||
firFileBuilder = firFileBuilder,
|
||||
firSymbolProvider = declaration.moduleData.session.symbolProvider,
|
||||
moduleFileCache = moduleFileCache
|
||||
)
|
||||
}
|
||||
|
||||
val firFile = declaration.getContainingFile()
|
||||
?: error("FirFile was not found for\n${declaration.render()}")
|
||||
return declaration
|
||||
}
|
||||
|
||||
/**
|
||||
* Run partially designated resolve that resolve declaration into last file-wise resolve and then resolve a designation (synchronized)
|
||||
* @see LAST_NON_LAZY_PHASE is the last file-wise resolve
|
||||
* @see lazyDesignatedResolveDeclaration designated resolve
|
||||
* @see runLazyResolveWithoutLock (not synchronized)
|
||||
*/
|
||||
fun lazyResolveDeclaration(
|
||||
declaration: FirDeclaration,
|
||||
moduleFileCache: ModuleFileCache,
|
||||
toPhase: FirResolvePhase,
|
||||
checkPCE: Boolean = false,
|
||||
reresolveFile: Boolean = false,
|
||||
) {
|
||||
if (declaration.resolvePhase >= toPhase) return
|
||||
|
||||
val resolvableDeclaration = getResolvableDeclaration(declaration, moduleFileCache)
|
||||
|
||||
val firFile = resolvableDeclaration.getContainingFile()
|
||||
?: error("FirFile was not found for\n${resolvableDeclaration.render()}")
|
||||
val provider = firFile.moduleData.session.firIdeProvider
|
||||
|
||||
// Lazy since we want to read the resolve phase inside the lock. Otherwise, we may run the same resolve phase multiple times. See
|
||||
// KT-45121
|
||||
val fromPhase: FirResolvePhase by lazy(LazyThreadSafetyMode.NONE) {
|
||||
if (reresolveFile) declaration.resolvePhase else minOf(firFile.resolvePhase, declaration.resolvePhase)
|
||||
if (reresolveFile) resolvableDeclaration.resolvePhase else minOf(firFile.resolvePhase, resolvableDeclaration.resolvePhase)
|
||||
}
|
||||
|
||||
if (checkPCE) {
|
||||
firFileBuilder.runCustomResolveWithPCECheck(firFile, moduleFileCache) {
|
||||
runLazyResolveWithoutLock(
|
||||
declaration,
|
||||
moduleFileCache,
|
||||
firFile,
|
||||
provider,
|
||||
fromPhase,
|
||||
toPhase,
|
||||
towerDataContextCollector,
|
||||
checkPCE = true
|
||||
firDeclarationToResolve = declaration,
|
||||
moduleFileCache = moduleFileCache,
|
||||
containerFirFile = firFile,
|
||||
provider = provider,
|
||||
fromPhase = fromPhase,
|
||||
toPhase = toPhase,
|
||||
checkPCE = true,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
firFileBuilder.runCustomResolveUnderLock(firFile, moduleFileCache) {
|
||||
executeWithoutPCE {
|
||||
runLazyResolveWithoutLock(
|
||||
declaration,
|
||||
moduleFileCache,
|
||||
firFile,
|
||||
provider,
|
||||
fromPhase,
|
||||
toPhase,
|
||||
towerDataContextCollector,
|
||||
checkPCE = false
|
||||
firDeclarationToResolve = declaration,
|
||||
moduleFileCache = moduleFileCache,
|
||||
containerFirFile = firFile,
|
||||
provider = provider,
|
||||
fromPhase = fromPhase,
|
||||
toPhase = toPhase,
|
||||
checkPCE = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateLazyBodies(firDeclaration: FirDeclaration, designation: FirDeclarationDesignation) {
|
||||
FirLazyBodiesCalculator.calculateLazyBodiesInside(firDeclaration, designation)
|
||||
private fun createLazyBodiesCalculator(designation: FirDeclarationDesignation): (FirResolvePhase) -> Unit {
|
||||
var calculated = false
|
||||
return { phase: FirResolvePhase ->
|
||||
if (!calculated && phase >= FirResolvePhase.CONTRACTS) {
|
||||
executeWithoutPCE {
|
||||
FirLazyBodiesCalculator.calculateLazyBodiesInside(designation)
|
||||
}
|
||||
calculated = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun runLazyResolveWithoutLock(
|
||||
/**
|
||||
* Designated resolve (not synchronized)
|
||||
* @see runLazyDesignatedResolveWithoutLock for designated resolve
|
||||
* @see lazyResolveDeclaration synchronized version
|
||||
*/
|
||||
private fun runLazyResolveWithoutLock(
|
||||
firDeclarationToResolve: FirDeclaration,
|
||||
moduleFileCache: ModuleFileCache,
|
||||
containerFirFile: FirFile,
|
||||
provider: FirProvider,
|
||||
fromPhase: FirResolvePhase,
|
||||
toPhase: FirResolvePhase,
|
||||
towerDataContextCollector: FirTowerDataContextCollector? = null,
|
||||
checkPCE: Boolean,
|
||||
lastNonLazyPhase: FirResolvePhase = LAST_NON_LAZY_PHASE,
|
||||
firProviderInterceptor: FirProviderInterceptorForSupertypeResolver? = null
|
||||
) {
|
||||
if (fromPhase >= toPhase) return
|
||||
val nonLazyPhase = minOf(toPhase, lastNonLazyPhase)
|
||||
val nonLazyPhase = minOf(toPhase, LAST_NON_LAZY_PHASE)
|
||||
|
||||
val scopeSession = ScopeSession()
|
||||
if (fromPhase < nonLazyPhase) {
|
||||
firFileBuilder.runResolveWithoutLock(
|
||||
containerFirFile,
|
||||
firFile = containerFirFile,
|
||||
fromPhase = fromPhase,
|
||||
toPhase = nonLazyPhase,
|
||||
scopeSession = scopeSession,
|
||||
@@ -141,27 +177,130 @@ internal class FirLazyDeclarationResolver(
|
||||
)
|
||||
}
|
||||
if (toPhase <= nonLazyPhase) return
|
||||
resolveFileAnnotations(containerFirFile, moduleFileCache, scopeSession)
|
||||
resolveFileAnnotationsWithoutLock(containerFirFile, scopeSession)
|
||||
|
||||
runLazyDesignatedResolveWithoutLock(
|
||||
firDeclarationToResolve = firDeclarationToResolve,
|
||||
moduleFileCache = moduleFileCache,
|
||||
containerFirFile = containerFirFile,
|
||||
provider = provider,
|
||||
fromPhase = LAST_NON_LAZY_PHASE,
|
||||
toPhase = toPhase,
|
||||
checkPCE = checkPCE,
|
||||
isOnAirResolve = false
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Run designated resolve only designation with fully resolved path (synchronized).
|
||||
* Suitable for body resolve or/and on-air resolve.
|
||||
* @see lazyResolveDeclaration for ordinary resolve
|
||||
* @param firDeclarationToResolve target non-local declaration
|
||||
* @param isOnAirResolve should be true when node does not belong to it's true designation (OnAir resolve in custom context)
|
||||
*/
|
||||
fun lazyDesignatedResolveDeclaration(
|
||||
firDeclarationToResolve: FirDeclaration,
|
||||
moduleFileCache: ModuleFileCache,
|
||||
containerFirFile: FirFile,
|
||||
provider: FirProvider,
|
||||
toPhase: FirResolvePhase,
|
||||
checkPCE: Boolean,
|
||||
isOnAirResolve: Boolean,
|
||||
towerDataContextCollector: FirTowerDataContextCollector? = null,
|
||||
) {
|
||||
// Lazy since we want to read the resolve phase inside the lock. Otherwise, we may run the same resolve phase multiple times. See
|
||||
// KT-45121
|
||||
val fromPhase: FirResolvePhase by lazy(LazyThreadSafetyMode.NONE) {
|
||||
minOf(containerFirFile.resolvePhase, firDeclarationToResolve.resolvePhase)
|
||||
}
|
||||
|
||||
if (checkPCE) {
|
||||
firFileBuilder.runCustomResolveWithPCECheck(containerFirFile, moduleFileCache) {
|
||||
runLazyDesignatedResolveWithoutLock(
|
||||
firDeclarationToResolve = firDeclarationToResolve,
|
||||
moduleFileCache = moduleFileCache,
|
||||
containerFirFile = containerFirFile,
|
||||
provider = provider,
|
||||
fromPhase = fromPhase,
|
||||
toPhase = toPhase,
|
||||
checkPCE = checkPCE,
|
||||
isOnAirResolve = isOnAirResolve,
|
||||
towerDataContextCollector = towerDataContextCollector,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
firFileBuilder.runCustomResolveUnderLock(containerFirFile, moduleFileCache) {
|
||||
runLazyDesignatedResolveWithoutLock(
|
||||
firDeclarationToResolve = firDeclarationToResolve,
|
||||
moduleFileCache = moduleFileCache,
|
||||
containerFirFile = containerFirFile,
|
||||
provider = provider,
|
||||
fromPhase = fromPhase,
|
||||
toPhase = toPhase,
|
||||
checkPCE = checkPCE,
|
||||
isOnAirResolve = isOnAirResolve,
|
||||
towerDataContextCollector = towerDataContextCollector,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Designated resolve (not synchronized)
|
||||
* @see runLazyResolveWithoutLock for ordinary resolve
|
||||
* @see lazyDesignatedResolveDeclaration synchronized version
|
||||
*/
|
||||
private fun runLazyDesignatedResolveWithoutLock(
|
||||
firDeclarationToResolve: FirDeclaration,
|
||||
moduleFileCache: ModuleFileCache,
|
||||
containerFirFile: FirFile,
|
||||
provider: FirProvider,
|
||||
fromPhase: FirResolvePhase,
|
||||
toPhase: FirResolvePhase,
|
||||
checkPCE: Boolean,
|
||||
isOnAirResolve: Boolean,
|
||||
towerDataContextCollector: FirTowerDataContextCollector? = null
|
||||
) {
|
||||
var currentPhase = fromPhase
|
||||
runLazyResolveWithoutLock(
|
||||
firDeclarationToResolve = firDeclarationToResolve,
|
||||
moduleFileCache = moduleFileCache,
|
||||
containerFirFile = containerFirFile,
|
||||
provider = provider,
|
||||
fromPhase = currentPhase,
|
||||
toPhase = FirResolvePhase.IMPORTS,
|
||||
checkPCE = checkPCE
|
||||
)
|
||||
currentPhase = maxOf(fromPhase, FirResolvePhase.IMPORTS)
|
||||
if (currentPhase >= toPhase) return
|
||||
|
||||
val nonLocalDeclarationToResolve = firDeclarationToResolve.getNonLocalDeclarationToResolve(provider, moduleFileCache)
|
||||
val designation = nonLocalDeclarationToResolve.collectDesignation(containerFirFile)
|
||||
check(!designation.isLocalDesignation) { "Could not resolve local designation" }
|
||||
|
||||
executeWithoutPCE {
|
||||
calculateLazyBodies(firDeclarationToResolve, designation)
|
||||
val lazyBodiesCalculator = createLazyBodiesCalculator(designation)
|
||||
val scopeSession = ScopeSession()
|
||||
|
||||
//This needed to override standard symbol resolve in supertype transformer with adding on-air created symbols
|
||||
val firProviderInterceptor = isOnAirResolve.ifTrue {
|
||||
FirProviderInterceptorForIDE.createForFirElement(
|
||||
session = designation.firFile.moduleData.session,
|
||||
firFile = designation.firFile,
|
||||
element = designation.declaration
|
||||
)
|
||||
}
|
||||
|
||||
var currentPhase = nonLazyPhase
|
||||
|
||||
while (currentPhase < toPhase) {
|
||||
currentPhase = currentPhase.next
|
||||
if (currentPhase.pluginPhase) continue
|
||||
if (checkPCE) checkCanceled()
|
||||
lazyBodiesCalculator(currentPhase)
|
||||
runLazyResolvePhase(
|
||||
currentPhase,
|
||||
scopeSession,
|
||||
towerDataContextCollector,
|
||||
firProviderInterceptor,
|
||||
designation,
|
||||
phase = currentPhase,
|
||||
scopeSession = scopeSession,
|
||||
designation = designation,
|
||||
towerDataContextCollector = towerDataContextCollector,
|
||||
firProviderInterceptor = firProviderInterceptor
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -169,9 +308,9 @@ internal class FirLazyDeclarationResolver(
|
||||
private fun runLazyResolvePhase(
|
||||
phase: FirResolvePhase,
|
||||
scopeSession: ScopeSession,
|
||||
designation: FirDeclarationDesignationWithFile,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?,
|
||||
designation: FirDeclarationDesignationWithFile
|
||||
firProviderInterceptor: FirProviderInterceptor?
|
||||
) {
|
||||
if (designation.declaration.resolvePhase >= phase) return
|
||||
|
||||
@@ -191,7 +330,7 @@ internal class FirLazyDeclarationResolver(
|
||||
designation: FirDeclarationDesignationWithFile,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?,
|
||||
firProviderInterceptor: FirProviderInterceptor?,
|
||||
): FirLazyTransformerForIDE = when (this) {
|
||||
FirResolvePhase.SUPER_TYPES -> FirDesignatedSupertypeResolverTransformerForIDE(
|
||||
designation,
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptorForSupertypeResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.*
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator
|
||||
@@ -23,7 +23,7 @@ internal class FirDesignatedBodyResolveTransformerForIDE(
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector? = null,
|
||||
firProviderInterceptor: FirProviderInterceptorForSupertypeResolver? = null,
|
||||
firProviderInterceptor: FirProviderInterceptor? = null,
|
||||
) : FirLazyTransformerForIDE, FirBodyResolveTransformer(
|
||||
session,
|
||||
phase = FirResolvePhase.BODY_RESOLVE,
|
||||
|
||||
+6
-35
@@ -17,42 +17,12 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensurePathPhase
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensureTargetPhase
|
||||
|
||||
class FirDesignatedStatusResolveTransformerForIDE(
|
||||
internal class FirDesignatedStatusResolveTransformerForIDE(
|
||||
private val designation: FirDeclarationDesignationWithFile,
|
||||
private val session: FirSession,
|
||||
private val scopeSession: ScopeSession,
|
||||
) : FirLazyTransformerForIDE {
|
||||
|
||||
private val firstItemInDesignation = designation.path.firstOrNull() ?: designation.declaration
|
||||
|
||||
private fun resolveClass(targetClass: FirClass<*>) {
|
||||
val transformer = FirDesignatedStatusResolveTransformer(
|
||||
session = session,
|
||||
scopeSession = scopeSession,
|
||||
designation = designation.toSequence(includeTarget = true).iterator(),
|
||||
targetClass = targetClass,
|
||||
statusComputationSession = StatusComputationSession.Regular(),
|
||||
designationMapForLocalClasses = emptyMap(),
|
||||
scopeForLocalClass = null
|
||||
)
|
||||
|
||||
firstItemInDesignation.transformSingle(transformer, null)
|
||||
}
|
||||
|
||||
private fun resolveTypeAlias(targetClass: FirTypeAlias) {
|
||||
val transformer = FirDesignatedStatusResolveTransformer(
|
||||
session = session,
|
||||
scopeSession = scopeSession,
|
||||
designation = designation.toSequence(includeTarget = true).iterator(),
|
||||
targetClass = targetClass,
|
||||
statusComputationSession = StatusComputationSession.Regular(),
|
||||
designationMapForLocalClasses = emptyMap(),
|
||||
scopeForLocalClass = null
|
||||
)
|
||||
|
||||
firstItemInDesignation.transformSingle(transformer, null)
|
||||
}
|
||||
|
||||
private fun resolveTopLevelDeclaration(declaration: FirDeclaration) {
|
||||
val transformer = FirStatusResolveTransformer(
|
||||
session = session,
|
||||
@@ -62,13 +32,13 @@ class FirDesignatedStatusResolveTransformerForIDE(
|
||||
declaration.transformSingle(transformer, null)
|
||||
}
|
||||
|
||||
private fun resolveClassMember(containingClass: FirClass<*>, targetCallable: FirDeclaration) {
|
||||
private fun resolveClassMember(containingClass: FirClass<*>, targetDeclaration: FirDeclaration) {
|
||||
|
||||
val transformer = object : FirDesignatedStatusResolveTransformer(
|
||||
session = session,
|
||||
scopeSession = scopeSession,
|
||||
designation = designation.toSequence(includeTarget = true).iterator(),
|
||||
targetClass = if (targetCallable is FirRegularClass) targetCallable else containingClass,
|
||||
targetClass = if (targetDeclaration is FirRegularClass) targetDeclaration else containingClass,
|
||||
statusComputationSession = StatusComputationSession.Regular(),
|
||||
designationMapForLocalClasses = emptyMap(),
|
||||
scopeForLocalClass = null
|
||||
@@ -77,12 +47,13 @@ class FirDesignatedStatusResolveTransformerForIDE(
|
||||
override fun <F : FirClass<F>> transformClass(klass: FirClass<F>, data: FirResolvedDeclarationStatus?): FirStatement {
|
||||
if (klass != containingClass) return super.transformClass(klass, data)
|
||||
val result = storeClass(klass) {
|
||||
targetCallable.transformSingle(this, data)
|
||||
targetDeclaration.transformSingle(this, data)
|
||||
}
|
||||
return result as FirStatement
|
||||
}
|
||||
}
|
||||
|
||||
val firstItemInDesignation = designation.path.firstOrNull() ?: designation.declaration
|
||||
firstItemInDesignation.transformSingle(transformer, null)
|
||||
}
|
||||
|
||||
@@ -95,7 +66,7 @@ class FirDesignatedStatusResolveTransformerForIDE(
|
||||
if (containingClass == null) {
|
||||
resolveTopLevelDeclaration(designation.declaration)
|
||||
} else {
|
||||
check(containingClass is FirClass<*>) { "Invalid designation - the parent is a class" }
|
||||
check(containingClass is FirClass<*>) { "Invalid designation - the parent is not a class" }
|
||||
resolveClassMember(containingClass, designation.declaration)
|
||||
}
|
||||
|
||||
|
||||
+4
-5
@@ -10,27 +10,26 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirApplySupertypesTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptorForSupertypeResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.SupertypeComputationSession
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensurePathPhase
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensureTargetPhase
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensureTargetPhaseIfClass
|
||||
|
||||
internal class FirDesignatedSupertypeResolverTransformerForIDE(
|
||||
private val designation: FirDeclarationDesignationWithFile,
|
||||
private val session: FirSession,
|
||||
private val scopeSession: ScopeSession,
|
||||
private val firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?,
|
||||
private val firProviderInterceptor: FirProviderInterceptor?
|
||||
) : FirLazyTransformerForIDE {
|
||||
|
||||
private val supertypeComputationSession = SupertypeComputationSession()
|
||||
|
||||
override fun transformDeclaration() {
|
||||
if (designation.declaration.resolvePhase >= FirResolvePhase.SUPER_TYPES) return
|
||||
designation.ensurePathPhase(FirResolvePhase.SUPER_TYPES)
|
||||
|
||||
val supertypeComputationSession = SupertypeComputationSession()
|
||||
|
||||
val resolver = FirSupertypeResolverVisitor(
|
||||
session = session,
|
||||
supertypeComputationSession = supertypeComputationSession,
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransform
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensureTargetPhase
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensureTargetPhaseIfClass
|
||||
|
||||
class FirDesignatedTypeResolverTransformerForIDE(
|
||||
internal class FirDesignatedTypeResolverTransformerForIDE(
|
||||
private val designation: FirDeclarationDesignationWithFile,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
|
||||
+4
-10
@@ -6,7 +6,7 @@
|
||||
package org.jetbrains.kotlin.idea.fir.low.level.api.transformers
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation
|
||||
|
||||
internal interface FirLazyTransformerForIDE {
|
||||
fun transformDeclaration()
|
||||
@@ -16,7 +16,7 @@ internal interface FirLazyTransformerForIDE {
|
||||
override fun transformDeclaration() = Unit
|
||||
}
|
||||
|
||||
fun FirDeclarationDesignationWithFile.ensurePathPhase(firResolvePhase: FirResolvePhase) {
|
||||
fun FirDeclarationDesignation.ensurePathPhase(firResolvePhase: FirResolvePhase) {
|
||||
toSequence(includeTarget = false).forEach { firDeclaration ->
|
||||
check(firDeclaration.resolvePhase >= firResolvePhase) {
|
||||
"Designation element phase required to be $firResolvePhase but element resolved to ${firDeclaration.resolvePhase}"
|
||||
@@ -24,19 +24,13 @@ internal interface FirLazyTransformerForIDE {
|
||||
}
|
||||
}
|
||||
|
||||
fun FirDeclarationDesignationWithFile.ensureTargetPhase(firResolvePhase: FirResolvePhase) =
|
||||
fun FirDeclarationDesignation.ensureTargetPhase(firResolvePhase: FirResolvePhase) =
|
||||
check(declaration.resolvePhase >= firResolvePhase) { "Expected $firResolvePhase but found ${declaration.resolvePhase}" }
|
||||
|
||||
fun FirDeclarationDesignationWithFile.ensureTargetPhaseIfClass(firResolvePhase: FirResolvePhase) = when (declaration) {
|
||||
fun FirDeclarationDesignation.ensureTargetPhaseIfClass(firResolvePhase: FirResolvePhase) = when (declaration) {
|
||||
is FirProperty, is FirSimpleFunction -> Unit
|
||||
is FirClass<*>, is FirTypeAlias -> ensureTargetPhase(firResolvePhase)
|
||||
else -> error("Unexpected target")
|
||||
}
|
||||
|
||||
fun FirDeclarationDesignationWithFile.ensureTargetPhaseIfMember(firResolvePhase: FirResolvePhase) = when (declaration) {
|
||||
is FirProperty, is FirSimpleFunction -> ensureTargetPhase(firResolvePhase)
|
||||
is FirClass<*>, is FirTypeAlias -> Unit
|
||||
else -> error("Unexpected target")
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.resolve.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptorForSupertypeResolver
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptor
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
@@ -20,7 +20,7 @@ internal class FirProviderInterceptorForIDE private constructor(
|
||||
private val session: FirSession,
|
||||
private val symbolSet: Set<FirClassLikeSymbol<*>>,
|
||||
private val classIdToElementMap: Map<ClassId, FirClassLikeDeclaration<*>>
|
||||
) : FirProviderInterceptorForSupertypeResolver {
|
||||
) : FirProviderInterceptor {
|
||||
|
||||
override fun getFirClassifierContainerFileIfAny(symbol: FirClassLikeSymbol<*>): FirFile? =
|
||||
if (symbolSet.contains(symbol)) firFile else session.firProvider.getFirClassifierContainerFileIfAny(symbol)
|
||||
@@ -29,7 +29,7 @@ internal class FirProviderInterceptorForIDE private constructor(
|
||||
classIdToElementMap[classId] ?: session.firProvider.getFirClassifierByFqName(classId)
|
||||
|
||||
companion object {
|
||||
fun createForFirElement(session: FirSession, firFile: FirFile, element: FirElement): FirProviderInterceptorForSupertypeResolver {
|
||||
fun createForFirElement(session: FirSession, firFile: FirFile, element: FirElement): FirProviderInterceptor {
|
||||
val nodeInfoCollector = object : FirVisitorVoid() {
|
||||
val symbolSet = mutableSetOf<FirClassLikeSymbol<*>>()
|
||||
val classIdToElementMap = mutableMapOf<ClassId, FirClassLikeDeclaration<*>>()
|
||||
|
||||
+3
-1
@@ -10,6 +10,8 @@ import com.intellij.testFramework.LightProjectDescriptor
|
||||
import org.jetbrains.kotlin.fir.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclaration
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
@@ -41,7 +43,7 @@ abstract class AbstractFirLazyDeclarationResolveTest : KotlinLightCodeInsightFix
|
||||
firModuleResolveState,
|
||||
FirResolvePhase.BODY_RESOLVE
|
||||
) @Suppress("UNUSED_ANONYMOUS_PARAMETER") { firDeclaration ->
|
||||
val firFile = firModuleResolveState.getBuiltFirFileOrNull(ktFile)!!
|
||||
val firFile = firModuleResolveState.getOrBuildFirFile(ktFile)
|
||||
firFile.render(FirRenderer.RenderMode.WithResolvePhases)
|
||||
}
|
||||
val expectedFileName = testDataFile.name.replace(".kt", ".txt")
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getFirFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.createResolveStateForNoCaching
|
||||
import org.jetbrains.kotlin.idea.project.withLanguageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.test.*
|
||||
@@ -76,7 +76,7 @@ abstract class AbstractCompilerBasedTest : KotlinLightCodeInsightFixtureTestCase
|
||||
val resolveState = createResolveState(moduleInfo, module.languageVersionSettings)
|
||||
val allFirFiles = files.mapNotNull { (testFile, psiFile) ->
|
||||
if (psiFile !is KtFile) return@mapNotNull null
|
||||
testFile to psiFile.getFirFile(resolveState)
|
||||
testFile to psiFile.getOrBuildFirFile(resolveState)
|
||||
}.toMap()
|
||||
|
||||
val diagnosticCheckerFilter = if (FirDiagnosticsDirectives.WITH_EXTENDED_CHECKERS in module.directives) {
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveStateImpl
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getDiagnostics
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getFirFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.createResolveStateForNoCaching
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.BeforeElementDiagnosticCollectionHandler
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.fir.PersistenceContextCollector
|
||||
@@ -45,7 +45,7 @@ abstract class AbstractFirContextCollectionTest : KotlinLightCodeInsightFixtureT
|
||||
val fileStructure = resolveState.fileStructureCache.getFileStructure(ktFile, resolveState.rootModuleSession.cache)
|
||||
val allStructureElements = fileStructure.getAllStructureElements()
|
||||
handler.elementsToCheckContext = allStructureElements.map { it.getFirDeclaration() }
|
||||
handler.firFile = ktFile.getFirFile(resolveState)
|
||||
handler.firFile = ktFile.getOrBuildFirFile(resolveState)
|
||||
ktFile.getDiagnostics(resolveState, DiagnosticCheckerFilter.ONLY_COMMON_CHECKERS)
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacadeForResolveOnAir.getTowerContextProvider
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getFirFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirOfType
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.resolver.ResolutionParameters
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.resolver.SingleCandidateResolutionMode
|
||||
@@ -61,7 +61,7 @@ internal class KtFirCompletionCandidateChecker(
|
||||
nameExpression: KtSimpleNameExpression,
|
||||
possibleExplicitReceiver: KtExpression?,
|
||||
): Boolean {
|
||||
val file = originalFile.getFirFile(firResolveState)
|
||||
val file = originalFile.getOrBuildFirFile(firResolveState)
|
||||
val explicitReceiverExpression = possibleExplicitReceiver?.getOrBuildFirOfType<FirExpression>(firResolveState)
|
||||
val resolver = SingleCandidateResolver(firResolveState.rootModuleSession, file)
|
||||
val implicitReceivers = getImplicitReceivers(originalFile, file, nameExpression)
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.fir.renderWithType
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getFirFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirOfType
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclarationOfType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||
@@ -41,7 +41,7 @@ internal class KtFirSymbolProvider(
|
||||
}
|
||||
|
||||
override fun getFileSymbol(psi: KtFile): KtFileSymbol = withValidityAssertion {
|
||||
firSymbolBuilder.buildFileSymbol(psi.getFirFile(resolveState))
|
||||
firSymbolBuilder.buildFileSymbol(psi.getOrBuildFirFile(resolveState))
|
||||
}
|
||||
|
||||
override fun getFunctionLikeSymbol(psi: KtNamedFunction): KtFunctionLikeSymbol = withValidityAssertion {
|
||||
|
||||
Reference in New Issue
Block a user