[FIR IDE] Refactoring of designated IDE transformers

This commit is contained in:
Igor Yakovlev
2021-05-05 20:48:54 +02:00
committed by TeamCityServer
parent 384b2ad048
commit cfc0bfd64a
17 changed files with 185 additions and 199 deletions
@@ -8,10 +8,11 @@ package org.jetbrains.kotlin.idea.fir.low.level.api
import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
abstract class ContextByDesignationCollector<C : Any>(private val designation: FirDeclarationDesignation, var firFile: FirFile) { abstract class ContextByDesignationCollector<C : Any>(private val designation: FirDeclarationDesignation) {
private var context: C? = null private var context: C? = null
private val designationState = FirDesignationState(designation, firFile) private val designationState = FirDesignationState(designation)
protected abstract fun getCurrentContext(): C protected abstract fun getCurrentContext(): C
protected abstract fun goToNestedDeclaration(declaration: FirDeclaration) protected abstract fun goToNestedDeclaration(declaration: FirDeclaration)
@@ -37,7 +38,7 @@ abstract class ContextByDesignationCollector<C : Any>(private val designation: F
} }
} }
private class FirDesignationState(val designation: FirDeclarationDesignation, val firFile: FirFile) { private class FirDesignationState(val designation: FirDeclarationDesignation) {
/** /**
* Holds current declaration index * Holds current declaration index
* if `currentIndex in [0, designation.path.lastIndex]` then current declaration is in path * if `currentIndex in [0, designation.path.lastIndex]` then current declaration is in path
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider
import org.jetbrains.kotlin.idea.fir.low.level.api.util.getContainingFile
import org.jetbrains.kotlin.idea.util.getElementTextInContext import org.jetbrains.kotlin.idea.util.getElementTextInContext
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -12,71 +12,86 @@ import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
class FirDeclarationDesignation( class FirDeclarationDesignationWithFile(
path: List<FirDeclaration>,
declaration: FirDeclaration,
isLocalDesignation: Boolean,
val firFile: FirFile
) : FirDeclarationDesignation(
path,
declaration,
isLocalDesignation
) {
fun toSequenceWithFile(includeTarget: Boolean): Sequence<FirDeclaration> = sequence {
yield(firFile)
yieldAll(path)
if (includeTarget) yield(declaration)
}
}
open class FirDeclarationDesignation(
val path: List<FirDeclaration>, val path: List<FirDeclaration>,
val declaration: FirDeclaration, val declaration: FirDeclaration,
val isLocalDesignation: Boolean, val isLocalDesignation: Boolean
) { ) {
@OptIn(ExperimentalStdlibApi::class) fun toSequence(includeTarget: Boolean): Sequence<FirDeclaration> = sequence {
val fullDesignation = buildList { yieldAll(path)
addAll(path) if (includeTarget) yield(declaration)
add(declaration)
} }
} }
private fun collectDesignationAndIsLocal(declaration: FirDeclaration): Pair<List<FirDeclaration>, Boolean> {
val firProvider = declaration.moduleData.session.firProvider
object DeclarationDesignationCollector { val containingClass = when (declaration) {
fun collectDesignation(declaration: FirDeclaration): FirDeclarationDesignation { is FirCallableDeclaration<*> -> declaration.containingClass()?.toFirRegularClass(declaration.moduleData.session)
val firProvider = declaration.moduleData.session.firProvider is FirClassLikeDeclaration<*> -> declaration.symbol.classId.outerClassId?.let(firProvider::getFirClassifierByFqName)
else -> error("Invalid declaration ${declaration.renderWithType()}")
} ?: return emptyList<FirDeclaration>() to false
val containingClass = when (declaration) { require(containingClass is FirRegularClass) {
is FirCallableDeclaration<*> -> declaration.containingClass()?.toFirRegularClass(declaration.moduleData.session) "FirRegularClass as containing declaration expected but found ${containingClass.renderWithType()}"
is FirClassLikeDeclaration<*> -> declaration.symbol.classId.outerClassId?.let(firProvider::getFirClassifierByFqName)
else -> error("Invalid declaration ${declaration.renderWithType()}")
} ?: return FirDeclarationDesignation(emptyList(), declaration, isLocalDesignation = false)
require(containingClass is FirRegularClass) {
"FirRegularClass as containing declaration expected but found ${containingClass.renderWithType()}"
}
val path = when {
containingClass.isLocal -> containingClass.collectForLocal()
else -> containingClass.collectForNonLocal()
}
return FirDeclarationDesignation(
path.reversed(),
declaration,
isLocalDesignation = false
)
} }
private fun FirRegularClass.collectForNonLocal(): List<FirClassLikeDeclaration<*>> { val path = when {
require(!isLocal) containingClass.isLocal -> containingClass.collectForLocal()
val firProvider = moduleData.session.firProvider else -> containingClass.collectForNonLocal()
var containingClassId = classId.outerClassId
val designation = mutableListOf<FirClassLikeDeclaration<*>>(this)
while (containingClassId != null) {
val currentClass = firProvider.getFirClassifierByFqName(containingClassId) ?: break
designation.add(currentClass)
containingClassId = containingClassId.outerClassId
}
return designation
}
private fun FirRegularClass.collectForLocal(): List<FirClassLikeDeclaration<*>> {
require(isLocal)
var containingClassLookUp = containingClassForLocal()
val designation = mutableListOf<FirClassLikeDeclaration<*>>(this)
while (containingClassLookUp != null && containingClassLookUp.classId.isLocal) {
val currentClass = containingClassLookUp.toFirRegularClass(moduleData.session) ?: break
designation.add(currentClass)
containingClassLookUp = currentClass.containingClassForLocal()
}
return designation
} }
return path.reversed() to containingClass.isLocal
} }
private fun FirRegularClass.collectForNonLocal(): List<FirDeclaration> {
require(!isLocal)
val firProvider = moduleData.session.firProvider
var containingClassId = classId.outerClassId
val designation = mutableListOf<FirDeclaration>(this)
while (containingClassId != null) {
val currentClass = firProvider.getFirClassifierByFqName(containingClassId) ?: break
designation.add(currentClass)
containingClassId = containingClassId.outerClassId
}
return designation
}
private fun FirRegularClass.collectForLocal(): List<FirClassLikeDeclaration<*>> {
require(isLocal)
var containingClassLookUp = containingClassForLocal()
val designation = mutableListOf<FirClassLikeDeclaration<*>>(this)
while (containingClassLookUp != null && containingClassLookUp.classId.isLocal) {
val currentClass = containingClassLookUp.toFirRegularClass(moduleData.session) ?: break
designation.add(currentClass)
containingClassLookUp = currentClass.containingClassForLocal()
}
return designation
}
fun FirDeclaration.collectDesignation(firFile: FirFile): FirDeclarationDesignationWithFile =
collectDesignationAndIsLocal(this).let {
FirDeclarationDesignationWithFile(it.first, this, it.second, firFile)
}
fun FirDeclaration.collectDesignation(): FirDeclarationDesignation = fun FirDeclaration.collectDesignation(): FirDeclarationDesignation =
DeclarationDesignationCollector.collectDesignation(this) collectDesignationAndIsLocal(this).let {
FirDeclarationDesignation(it.first, this, it.second)
}
@@ -61,16 +61,14 @@ object LowLevelFirApiFacadeForResolveOnAir {
} }
} }
private fun <T : KtElement> onAirResolveElement( fun <T : KtElement> onAirResolveElement(
state: FirModuleResolveState, state: FirModuleResolveState,
place: T, place: T,
elementToResolve: T, elementToResolve: T,
): FirModuleResolveState { ): FirElement {
require(state is FirModuleResolveStateImpl) require(state is FirModuleResolveStateImpl)
require(place.isPhysical) require(place.isPhysical)
require(!elementToResolve.isPhysical)
val collector = FirTowerDataContextAllElementsCollector()
val declaration = runResolveBodyResolveOnAir( val declaration = runResolveBodyResolveOnAir(
state = state, state = state,
replacement = RawFirReplacement(place, elementToResolve), replacement = RawFirReplacement(place, elementToResolve),
@@ -88,10 +86,9 @@ object LowLevelFirApiFacadeForResolveOnAir {
element.acceptChildren(this) element.acceptChildren(this)
} }
} }
declaration.accept(expressionLocator)
val recordedMap = FirElementsRecorder.recordElementsFrom(declaration, FirElementsRecorder()) declaration.accept(expressionLocator)
return FirModuleResolveStateDepended(state, collector, recordedMap) return expressionLocator.result ?: error("Resolved on-air element was not found in containing declaration")
} }
fun onAirGetTowerContextProvider( fun onAirGetTowerContextProvider(
@@ -13,16 +13,16 @@ import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.SessionHolder import org.jetbrains.kotlin.fir.resolve.SessionHolder
import org.jetbrains.kotlin.idea.fir.low.level.api.ContextByDesignationCollector import org.jetbrains.kotlin.idea.fir.low.level.api.ContextByDesignationCollector
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.idea.fir.low.level.api.api.collectDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.collectDesignation
private class ContextCollectingDiagnosticCollectorVisitor private constructor( private class ContextCollectingDiagnosticCollectorVisitor private constructor(
sessionHolder: SessionHolder, sessionHolder: SessionHolder,
designation: FirDeclarationDesignation, designation: FirDeclarationDesignationWithFile,
firFile: FirFile,
) : AbstractDiagnosticCollectorVisitor( ) : AbstractDiagnosticCollectorVisitor(
PersistentCheckerContextFactory.createEmptyPersistenceCheckerContext(sessionHolder) PersistentCheckerContextFactory.createEmptyPersistenceCheckerContext(sessionHolder)
) { ) {
private val contextCollector = object : ContextByDesignationCollector<PersistentCheckerContext>(designation, firFile) { private val contextCollector = object : ContextByDesignationCollector<PersistentCheckerContext>(designation) {
override fun getCurrentContext(): PersistentCheckerContext = context override fun getCurrentContext(): PersistentCheckerContext = context
override fun goToNestedDeclaration(declaration: FirDeclaration) { override fun goToNestedDeclaration(declaration: FirDeclaration) {
@@ -41,9 +41,9 @@ private class ContextCollectingDiagnosticCollectorVisitor private constructor(
override fun checkElement(element: FirElement) {} override fun checkElement(element: FirElement) {}
companion object { companion object {
fun collect(sessionHolder: SessionHolder, firFile: FirFile, designation: FirDeclarationDesignation): PersistentCheckerContext { fun collect(sessionHolder: SessionHolder, designation: FirDeclarationDesignationWithFile): PersistentCheckerContext {
val visitor = ContextCollectingDiagnosticCollectorVisitor(sessionHolder, designation, firFile) val visitor = ContextCollectingDiagnosticCollectorVisitor(sessionHolder, designation)
firFile.accept(visitor, null) designation.firFile.accept(visitor, null)
return visitor.contextCollector.getCollectedContext() return visitor.contextCollector.getCollectedContext()
} }
} }
@@ -63,10 +63,10 @@ internal object PersistenceContextCollector {
require(!isLocal) { require(!isLocal) {
"Cannot collect context for local declaration ${declaration.renderWithType()}" "Cannot collect context for local declaration ${declaration.renderWithType()}"
} }
val designation = declaration.collectDesignation() val designation = declaration.collectDesignation(firFile)
check(!designation.isLocalDesignation) { check(!designation.isLocalDesignation) {
"Designation should not local for ${declaration.renderWithType()}" "Designation should not local for ${declaration.renderWithType()}"
} }
return ContextCollectingDiagnosticCollectorVisitor.collect(sessionHolder, firFile, designation) return ContextCollectingDiagnosticCollectorVisitor.collect(sessionHolder, designation)
} }
} }
@@ -24,7 +24,7 @@ internal object FirLazyBodiesCalculator {
fun calculateLazyBodiesInside(element: FirElement, designation: FirDeclarationDesignation) { fun calculateLazyBodiesInside(element: FirElement, designation: FirDeclarationDesignation) {
element.transform<FirElement, MutableList<FirDeclaration>>( element.transform<FirElement, MutableList<FirDeclaration>>(
FirLazyBodiesCalculatorTransformer, FirLazyBodiesCalculatorTransformer,
designation.fullDesignation.toMutableList() designation.toSequence(includeTarget = true).toMutableList()
) )
} }
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptorForSupertypeResolver import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptorForSupertypeResolver
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector 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.FirDeclarationDesignation
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.idea.fir.low.level.api.api.collectDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.collectDesignation
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.getNonLocalContainingOrThisDeclaration import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.getNonLocalContainingOrThisDeclaration
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder
@@ -143,7 +144,7 @@ internal class FirLazyDeclarationResolver(
resolveFileAnnotations(containerFirFile, moduleFileCache, scopeSession) resolveFileAnnotations(containerFirFile, moduleFileCache, scopeSession)
val nonLocalDeclarationToResolve = firDeclarationToResolve.getNonLocalDeclarationToResolve(provider, moduleFileCache) val nonLocalDeclarationToResolve = firDeclarationToResolve.getNonLocalDeclarationToResolve(provider, moduleFileCache)
val designation = nonLocalDeclarationToResolve.collectDesignation() val designation = nonLocalDeclarationToResolve.collectDesignation(containerFirFile)
executeWithoutPCE { executeWithoutPCE {
calculateLazyBodies(firDeclarationToResolve, designation) calculateLazyBodies(firDeclarationToResolve, designation)
@@ -156,7 +157,6 @@ internal class FirLazyDeclarationResolver(
if (currentPhase.pluginPhase) continue if (currentPhase.pluginPhase) continue
if (checkPCE) checkCanceled() if (checkPCE) checkCanceled()
runLazyResolvePhase( runLazyResolvePhase(
containerFirFile,
currentPhase, currentPhase,
scopeSession, scopeSession,
towerDataContextCollector, towerDataContextCollector,
@@ -167,20 +167,18 @@ internal class FirLazyDeclarationResolver(
} }
private fun runLazyResolvePhase( private fun runLazyResolvePhase(
containerFirFile: FirFile,
phase: FirResolvePhase, phase: FirResolvePhase,
scopeSession: ScopeSession, scopeSession: ScopeSession,
towerDataContextCollector: FirTowerDataContextCollector?, towerDataContextCollector: FirTowerDataContextCollector?,
firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?, firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?,
designation: FirDeclarationDesignation designation: FirDeclarationDesignationWithFile
) { ) {
if (designation.fullDesignation.all { it.resolvePhase >= phase }) { if (designation.toSequence(includeTarget = true).all { it.resolvePhase >= phase }) {
return return
} }
val transformer = phase.createLazyTransformer( val transformer = phase.createLazyTransformer(
designation, designation,
containerFirFile,
scopeSession, scopeSession,
towerDataContextCollector, towerDataContextCollector,
firProviderInterceptor, firProviderInterceptor,
@@ -192,46 +190,41 @@ internal class FirLazyDeclarationResolver(
} }
private fun FirResolvePhase.createLazyTransformer( private fun FirResolvePhase.createLazyTransformer(
designation: FirDeclarationDesignation, designation: FirDeclarationDesignationWithFile,
containerFirFile: FirFile,
scopeSession: ScopeSession, scopeSession: ScopeSession,
towerDataContextCollector: FirTowerDataContextCollector?, towerDataContextCollector: FirTowerDataContextCollector?,
firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?, firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?,
): FirLazyTransformerForIDE = when (this) { ): FirLazyTransformerForIDE = when (this) {
FirResolvePhase.SUPER_TYPES -> FirDesignatedSupertypeResolverTransformerForIDE( FirResolvePhase.SUPER_TYPES -> FirDesignatedSupertypeResolverTransformerForIDE(
designation, designation,
containerFirFile.moduleData.session, designation.firFile.moduleData.session,
scopeSession, scopeSession,
firProviderInterceptor, firProviderInterceptor,
) )
FirResolvePhase.SEALED_CLASS_INHERITORS -> FirLazyTransformerForIDE.EMPTY FirResolvePhase.SEALED_CLASS_INHERITORS -> FirLazyTransformerForIDE.EMPTY
FirResolvePhase.TYPES -> FirDesignatedTypeResolverTransformerForIDE( FirResolvePhase.TYPES -> FirDesignatedTypeResolverTransformerForIDE(
containerFirFile,
designation, designation,
containerFirFile.moduleData.session, designation.firFile.moduleData.session,
scopeSession, scopeSession,
) )
FirResolvePhase.STATUS -> FirDesignatedStatusResolveTransformerForIDE( FirResolvePhase.STATUS -> FirDesignatedStatusResolveTransformerForIDE(
designation, designation,
containerFirFile.moduleData.session, designation.firFile.moduleData.session,
scopeSession scopeSession
) )
FirResolvePhase.CONTRACTS -> FirDesignatedContractsResolveTransformerForIDE( FirResolvePhase.CONTRACTS -> FirDesignatedContractsResolveTransformerForIDE(
containerFirFile,
designation, designation,
containerFirFile.moduleData.session, designation.firFile.moduleData.session,
scopeSession, scopeSession,
) )
FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE -> FirDesignatedImplicitTypesTransformerForIDE( FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE -> FirDesignatedImplicitTypesTransformerForIDE(
containerFirFile,
designation, designation,
containerFirFile.moduleData.session, designation.firFile.moduleData.session,
scopeSession scopeSession
) )
FirResolvePhase.BODY_RESOLVE -> FirDesignatedBodyResolveTransformerForIDE( FirResolvePhase.BODY_RESOLVE -> FirDesignatedBodyResolveTransformerForIDE(
containerFirFile,
designation, designation,
containerFirFile.moduleData.session, designation.firFile.moduleData.session,
scopeSession, scopeSession,
towerDataContextCollector, towerDataContextCollector,
firProviderInterceptor firProviderInterceptor
@@ -14,11 +14,11 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptorForSupertypeResolver import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptorForSupertypeResolver
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.* import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.*
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator
internal class FirDesignatedBodyResolveTransformerForIDE( internal class FirDesignatedBodyResolveTransformerForIDE(
private val firFile: FirFile, private val designation: FirDeclarationDesignationWithFile,
designation: FirDeclarationDesignation,
session: FirSession, session: FirSession,
scopeSession: ScopeSession, scopeSession: ScopeSession,
towerDataContextCollector: FirTowerDataContextCollector? = null, towerDataContextCollector: FirTowerDataContextCollector? = null,
@@ -37,19 +37,19 @@ internal class FirDesignatedBodyResolveTransformerForIDE(
firTowerDataContextCollector = towerDataContextCollector, firTowerDataContextCollector = towerDataContextCollector,
firProviderInterceptor = firProviderInterceptor, firProviderInterceptor = firProviderInterceptor,
) { ) {
private val ideDeclarationTransformer = IDEDeclarationTransformer(designation.toDesignationIterator()) private val ideDeclarationTransformer = IDEDeclarationTransformer(designation)
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration = override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration =
ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) { declaration, data -> ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) {
super.transformDeclarationContent(declaration, data) super.transformDeclarationContent(declaration, data)
} }
override fun needReplacePhase(firDeclaration: FirDeclaration): Boolean = override fun needReplacePhase(firDeclaration: FirDeclaration): Boolean =
ideDeclarationTransformer.needReplacePhase(firDeclaration) ideDeclarationTransformer.needReplacePhase
override fun transformDeclaration() { override fun transformDeclaration() {
firFile.transform<FirFile, ResolutionMode>(this, ResolutionMode.ContextDependent) designation.firFile.transform<FirFile, ResolutionMode>(this, ResolutionMode.ContextDependent)
} }
} }
@@ -11,26 +11,25 @@ import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractResolveTransformer
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
internal class FirDesignatedContractsResolveTransformerForIDE( internal class FirDesignatedContractsResolveTransformerForIDE(
private val firFile: FirFile, private val designation: FirDeclarationDesignationWithFile,
designation: FirDeclarationDesignation,
session: FirSession, session: FirSession,
scopeSession: ScopeSession, scopeSession: ScopeSession,
) : FirLazyTransformerForIDE, FirContractResolveTransformer(session, scopeSession) { ) : FirLazyTransformerForIDE, FirContractResolveTransformer(session, scopeSession) {
private val ideDeclarationTransformer = IDEDeclarationTransformer(designation.toDesignationIterator()) private val ideDeclarationTransformer = IDEDeclarationTransformer(designation)
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration = override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration =
ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) { declaration, data -> ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) {
super.transformDeclarationContent(declaration, data) super.transformDeclarationContent(declaration, data)
} }
override fun needReplacePhase(firDeclaration: FirDeclaration): Boolean = ideDeclarationTransformer.needReplacePhase(firDeclaration) override fun needReplacePhase(firDeclaration: FirDeclaration): Boolean = ideDeclarationTransformer.needReplacePhase
override fun transformDeclaration() { override fun transformDeclaration() {
firFile.transform<FirFile, ResolutionMode>(this, ResolutionMode.ContextDependent) designation.firFile.transform<FirFile, ResolutionMode>(this, ResolutionMode.ContextDependent)
} }
} }
@@ -14,12 +14,11 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitAwareBodyResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitAwareBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator
internal class FirDesignatedImplicitTypesTransformerForIDE( internal class FirDesignatedImplicitTypesTransformerForIDE(
private val firFile: FirFile, private val designation: FirDeclarationDesignationWithFile,
designation: FirDeclarationDesignation,
session: FirSession, session: FirSession,
scopeSession: ScopeSession, scopeSession: ScopeSession,
implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession = ImplicitBodyResolveComputationSession(), implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession = ImplicitBodyResolveComputationSession(),
@@ -36,17 +35,17 @@ internal class FirDesignatedImplicitTypesTransformerForIDE(
::FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator ::FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator
) )
) { ) {
private val ideDeclarationTransformer = IDEDeclarationTransformer(designation.toDesignationIterator()) private val ideDeclarationTransformer = IDEDeclarationTransformer(designation)
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration = override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration =
ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) { declaration, data -> ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) {
super.transformDeclarationContent(declaration, data) super.transformDeclarationContent(declaration, data)
} }
override fun needReplacePhase(firDeclaration: FirDeclaration): Boolean = ideDeclarationTransformer.needReplacePhase(firDeclaration) override fun needReplacePhase(firDeclaration: FirDeclaration): Boolean = ideDeclarationTransformer.needReplacePhase
override fun transformDeclaration() { override fun transformDeclaration() {
firFile.transform<FirFile, ResolutionMode>(this, ResolutionMode.ContextDependent) designation.firFile.transform<FirFile, ResolutionMode>(this, ResolutionMode.ContextDependent)
} }
} }
@@ -13,27 +13,43 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirDesignatedStatusResolveT
import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.StatusComputationSession import org.jetbrains.kotlin.fir.resolve.transformers.StatusComputationSession
import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensurePhase import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensurePhase
class FirDesignatedStatusResolveTransformerForIDE( class FirDesignatedStatusResolveTransformerForIDE(
private val designation: FirDeclarationDesignation, private val designation: FirDeclarationDesignationWithFile,
private val session: FirSession, private val session: FirSession,
private val scopeSession: ScopeSession, private val scopeSession: ScopeSession,
): FirLazyTransformerForIDE { ): FirLazyTransformerForIDE {
private val firstItemInDesignation = designation.path.firstOrNull() ?: designation.declaration
private fun resolveClass(targetClass: FirClass<*>) { private fun resolveClass(targetClass: FirClass<*>) {
val transformer = FirDesignatedStatusResolveTransformer( val transformer = FirDesignatedStatusResolveTransformer(
session = session, session = session,
scopeSession = scopeSession, scopeSession = scopeSession,
designation = designation.fullDesignation.iterator(), designation = designation.toSequence(includeTarget = true).iterator(),
targetClass = targetClass, targetClass = targetClass,
statusComputationSession = StatusComputationSession.Regular(), statusComputationSession = StatusComputationSession.Regular(),
designationMapForLocalClasses = emptyMap(), designationMapForLocalClasses = emptyMap(),
scopeForLocalClass = null) scopeForLocalClass = null
)
val firstClass = designation.fullDesignation.first() firstItemInDesignation.transformSingle(transformer, null)
firstClass.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 resolveTopLevelMethod(targetCallable: FirCallableDeclaration<*>) { private fun resolveTopLevelMethod(targetCallable: FirCallableDeclaration<*>) {
@@ -50,11 +66,12 @@ class FirDesignatedStatusResolveTransformerForIDE(
val transformer = object : FirDesignatedStatusResolveTransformer( val transformer = object : FirDesignatedStatusResolveTransformer(
session = session, session = session,
scopeSession = scopeSession, scopeSession = scopeSession,
designation = designation.fullDesignation.iterator(), designation = designation.toSequence(includeTarget = true).iterator(),
targetClass = containingClass, targetClass = containingClass,
statusComputationSession = StatusComputationSession.Regular(), statusComputationSession = StatusComputationSession.Regular(),
designationMapForLocalClasses = emptyMap(), designationMapForLocalClasses = emptyMap(),
scopeForLocalClass = null) { scopeForLocalClass = null
) {
override fun <F : FirClass<F>> transformClass( override fun <F : FirClass<F>> transformClass(
klass: FirClass<F>, klass: FirClass<F>,
@@ -66,25 +83,25 @@ class FirDesignatedStatusResolveTransformerForIDE(
} }
} }
val firstClass = designation.fullDesignation.first() firstItemInDesignation.transformSingle(transformer, null)
firstClass.transformSingle(transformer, null)
} }
override fun transformDeclaration() { override fun transformDeclaration() {
designation.ensurePhase(FirResolvePhase.STATUS, exceptLast = true) designation.ensurePhase(FirResolvePhase.STATUS, exceptTarget = true)
when(val resolveTarget = designation.declaration) { when (val resolveTarget = designation.declaration) {
is FirClass<*> -> resolveClass(resolveTarget) is FirClass<*> -> resolveClass(resolveTarget)
is FirTypeAlias -> resolveTypeAlias(resolveTarget)
is FirCallableDeclaration<*> -> { is FirCallableDeclaration<*> -> {
val containingClass = designation.path.lastOrNull() val containingClass = designation.path.lastOrNull()
if (containingClass == null) { if (containingClass == null) {
check(designation.fullDesignation.size == 1) { "Invalid designation - should be single element designation for top level declaration" } check(designation.path.isEmpty()) { "Invalid designation - should be single element designation for top level declaration" }
resolveTopLevelMethod(resolveTarget) resolveTopLevelMethod(resolveTarget)
} else { } else {
check(containingClass is FirClass<*>) { "Invalid designation - the parent of callable is not a class" } check(containingClass is FirClass<*>) { "Invalid designation - the parent of callable is not a class" }
resolveClassMember(containingClass, resolveTarget) resolveClassMember(containingClass, resolveTarget)
} }
} }
else -> error("Declaration should be ${FirClass::class.simpleName} but given ${resolveTarget::class.simpleName}") else -> error("Unexpected declaration to resolve ${resolveTarget::class.simpleName}")
} }
} }
} }
@@ -14,10 +14,11 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptorForSu
import org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor import org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor
import org.jetbrains.kotlin.fir.resolve.transformers.SupertypeComputationSession import org.jetbrains.kotlin.fir.resolve.transformers.SupertypeComputationSession
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensurePhase import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensurePhase
internal class FirDesignatedSupertypeResolverTransformerForIDE( internal class FirDesignatedSupertypeResolverTransformerForIDE(
private val designation: FirDeclarationDesignation, private val designation: FirDeclarationDesignationWithFile,
private val session: FirSession, private val session: FirSession,
private val scopeSession: ScopeSession, private val scopeSession: ScopeSession,
private val firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?, private val firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?,
@@ -26,7 +27,7 @@ internal class FirDesignatedSupertypeResolverTransformerForIDE(
private val supertypeComputationSession = SupertypeComputationSession() private val supertypeComputationSession = SupertypeComputationSession()
override fun transformDeclaration() { override fun transformDeclaration() {
designation.ensurePhase(FirResolvePhase.SUPER_TYPES, exceptLast = true) designation.ensurePhase(FirResolvePhase.SUPER_TYPES, exceptTarget = true)
val resolver = FirSupertypeResolverVisitor( val resolver = FirSupertypeResolverVisitor(
session = session, session = session,
@@ -10,34 +10,33 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.resolve.ScopeSession 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.idea.fir.low.level.api.api.FirDeclarationDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensurePhase import org.jetbrains.kotlin.idea.fir.low.level.api.transformers.FirLazyTransformerForIDE.Companion.ensurePhase
class FirDesignatedTypeResolverTransformerForIDE( class FirDesignatedTypeResolverTransformerForIDE(
private val originalFile: FirFile, private val designation: FirDeclarationDesignationWithFile,
private val designation: FirDeclarationDesignation,
session: FirSession, session: FirSession,
scopeSession: ScopeSession, scopeSession: ScopeSession,
): FirLazyTransformerForIDE, FirTypeResolveTransformer(session, scopeSession) { ) : FirLazyTransformerForIDE, FirTypeResolveTransformer(session, scopeSession) {
private val ideDeclarationTransformer = IDEDeclarationTransformer(FirDesignationIterator(designation.fullDesignation)) private val ideDeclarationTransformer = IDEDeclarationTransformer(designation)
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): FirStatement { override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): FirStatement {
return ideDeclarationTransformer.transformDeclarationContent(this, regularClass, data) { klass, data -> return ideDeclarationTransformer.transformDeclarationContent(this, regularClass, data) {
super.transformRegularClass(klass, data) as FirRegularClass super.transformRegularClass(regularClass, data) as FirRegularClass
} }
} }
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
override fun transformAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): FirStatement { override fun transformAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): FirStatement {
return ideDeclarationTransformer.transformDeclarationContent(this, anonymousObject, data) { anonymousObject, data -> return ideDeclarationTransformer.transformDeclarationContent(this, anonymousObject, data) {
super.transformAnonymousObject(anonymousObject, data) as FirAnonymousObject super.transformAnonymousObject(anonymousObject, data) as FirAnonymousObject
} }
} }
override fun transformDeclaration() { override fun transformDeclaration() {
designation.ensurePhase(FirResolvePhase.TYPES, exceptLast = true) designation.ensurePhase(FirResolvePhase.TYPES, exceptTarget = true)
originalFile.transform<FirFile, Any?>(this, null) designation.firFile.transform<FirFile, Any?>(this, null)
} }
} }
@@ -1,30 +0,0 @@
/*
* Copyright 2010-2021 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.idea.fir.low.level.api.transformers
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation
internal fun FirDeclarationDesignation.toDesignationIterator() =
FirDesignationIterator(fullDesignation)
internal class FirDesignationIterator(val designation: List<FirDeclaration>) {
private var currentIndex = 0
fun canGoNext(): Boolean = currentIndex <= designation.lastIndex
fun isTargetDeclaration(): Boolean = currentIndex == designation.lastIndex
val currentDeclaration get() = designation[currentIndex]
fun goNext() {
if (canGoNext()) {
currentIndex++
} else {
throw IndexOutOfBoundsException()
}
}
}
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.idea.fir.low.level.api.transformers package org.jetbrains.kotlin.idea.fir.low.level.api.transformers
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile
internal interface FirLazyTransformerForIDE { internal interface FirLazyTransformerForIDE {
fun transformDeclaration() fun transformDeclaration()
@@ -16,10 +16,10 @@ internal interface FirLazyTransformerForIDE {
override fun transformDeclaration() = Unit override fun transformDeclaration() = Unit
} }
fun FirDeclarationDesignation.ensurePhase(firResolvePhase: FirResolvePhase, exceptLast: Boolean) { fun FirDeclarationDesignationWithFile.ensurePhase(firResolvePhase: FirResolvePhase, exceptTarget: Boolean) {
val designationList = if (exceptLast) path else fullDesignation val designationIterator = toSequence(includeTarget = !exceptTarget)
designationList.forEach { firDeclaration -> designationIterator.forEach { firDeclaration ->
check (firDeclaration.resolvePhase >= firResolvePhase) { check(firDeclaration.resolvePhase >= firResolvePhase) {
"Designation element phase required to be $firResolvePhase but element resolved to ${firDeclaration.resolvePhase}" "Designation element phase required to be $firResolvePhase but element resolved to ${firDeclaration.resolvePhase}"
} }
} }
@@ -6,49 +6,41 @@
package org.jetbrains.kotlin.idea.fir.low.level.api.transformers package org.jetbrains.kotlin.idea.fir.low.level.api.transformers
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.transformers.FirAbstractPhaseTransformer import org.jetbrains.kotlin.fir.resolve.transformers.FirAbstractPhaseTransformer
import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignation
internal class IDEDeclarationTransformer(private val designationIterator: FirDesignationIterator) { internal class IDEDeclarationTransformer(private val designation: FirDeclarationDesignation) {
private val designationWithoutTargetIterator = designation.toSequence(includeTarget = false).iterator()
private var isInsideTargetDeclaration: Boolean = false private var isInsideTargetDeclaration: Boolean = false
private inline fun <R> insideTargetDeclaration(insideCurrent: Boolean, action: () -> R): R {
val oldValue = isInsideTargetDeclaration
isInsideTargetDeclaration = insideCurrent
try {
return action()
} finally {
isInsideTargetDeclaration = oldValue
}
}
inline fun <K, D> transformDeclarationContent( inline fun <K, D> transformDeclarationContent(
transformer: FirAbstractPhaseTransformer<D>, transformer: FirAbstractPhaseTransformer<D>,
declaration: K, declaration: K,
data: D, data: D,
transformDeclaration: (K, D) -> K defaultCallTransform: () -> K
): K { ): K {
return if (designationIterator.canGoNext()) {
val declarationToTransform = designationIterator.currentDeclaration if (isInsideTargetDeclaration) {
val isTargetDeclaration = designationIterator.isTargetDeclaration() return defaultCallTransform()
designationIterator.goNext() }
insideTargetDeclaration(isTargetDeclaration) {
declarationToTransform.visitNoTransform(transformer, data) if (designationWithoutTargetIterator.hasNext()) {
} designationWithoutTargetIterator.next().visitNoTransform(transformer, data)
declaration
} else { } else {
if (isInsideTargetDeclaration) { try {
transformDeclaration(declaration, data) isInsideTargetDeclaration = true
} else { designation.declaration.visitNoTransform(transformer, data)
declaration } finally {
isInsideTargetDeclaration = false
} }
} }
return declaration
} }
fun needReplacePhase(firDeclaration: FirDeclaration): Boolean = val needReplacePhase: Boolean get() = isInsideTargetDeclaration
isInsideTargetDeclaration
} }
private fun <D> FirElement.visitNoTransform(transformer: FirTransformer<D>, data: D) { private fun <D> FirElement.visitNoTransform(transformer: FirTransformer<D>, data: D) {
@@ -196,7 +196,9 @@ internal class ConeTypeIdeRenderer(
} }
val classToRender = classSymbolToRender.fir val classToRender = classSymbolToRender.fir
val designation = classToRender.collectDesignation().fullDesignation val designation = classToRender.collectDesignation()
.toSequence(includeTarget = true)
.toList()
var typeParametersLeft = type.typeArguments.count() var typeParametersLeft = type.typeArguments.count()
fun needToRenderTypeParameters(index: Int): Boolean { fun needToRenderTypeParameters(index: Int): Boolean {