From cfc0bfd64ac6fc08f0de48f5679ee08743574948 Mon Sep 17 00:00:00 2001 From: Igor Yakovlev Date: Wed, 5 May 2021 20:48:54 +0200 Subject: [PATCH] [FIR IDE] Refactoring of designated IDE transformers --- .../fir/low/level/api/FirDesignationState.kt | 7 +- .../level/api/api/DeclarationCopyBuilder.kt | 1 + .../api/api/FirDeclarationDesignation.kt | 121 ++++++++++-------- .../LowLevelFirApiFacadeForResolveOnAir.kt | 11 +- ...extCollectingDiagnosticCollectorVisitor.kt | 16 +-- .../lazy/resolve/FirLazyBodiesCalculator.kt | 2 +- .../resolve/FirLazyDeclarationResolver.kt | 29 ++--- ...rDesignatedBodyResolveTransformerForIDE.kt | 12 +- ...gnatedContractsResolveTransformerForIDE.kt | 13 +- ...esignatedImplicitTypesTransformerForIDE.kt | 13 +- ...esignatedStatusResolveTransformerForIDE.kt | 45 +++++-- ...natedSupertypeResolverTransformerForIDE.kt | 5 +- ...DesignatedTypeResolverTransformerForIDE.kt | 19 ++- .../transformers/FirDesignationIterator.kt | 30 ----- .../transformers/FirLazyTransformerForIDE.kt | 10 +- .../transformers/IDEDeclarationTransformer.kt | 46 +++---- .../api/fir/renderer/ConeTypeIdeRenderer.kt | 4 +- 17 files changed, 185 insertions(+), 199 deletions(-) delete mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignationIterator.kt diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirDesignationState.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirDesignationState.kt index cf26e9ff416..6da9ba51808 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirDesignationState.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirDesignationState.kt @@ -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.FirFile 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(private val designation: FirDeclarationDesignation, var firFile: FirFile) { +abstract class ContextByDesignationCollector(private val designation: FirDeclarationDesignation) { private var context: C? = null - private val designationState = FirDesignationState(designation, firFile) + private val designationState = FirDesignationState(designation) protected abstract fun getCurrentContext(): C protected abstract fun goToNestedDeclaration(declaration: FirDeclaration) @@ -37,7 +38,7 @@ abstract class ContextByDesignationCollector(private val designation: F } } -private class FirDesignationState(val designation: FirDeclarationDesignation, val firFile: FirFile) { +private class FirDesignationState(val designation: FirDeclarationDesignation) { /** * Holds current declaration index * if `currentIndex in [0, designation.path.lastIndex]` then current declaration is in path diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/DeclarationCopyBuilder.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/DeclarationCopyBuilder.kt index 6e2a8c9e7f6..f114d20f00f 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/DeclarationCopyBuilder.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/DeclarationCopyBuilder.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.expressions.FirReturnExpression import org.jetbrains.kotlin.fir.moduleData 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.util.getContainingFile import org.jetbrains.kotlin.idea.util.getElementTextInContext import org.jetbrains.kotlin.psi.* diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/FirDeclarationDesignation.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/FirDeclarationDesignation.kt index 22cebf04553..80503a1eaa9 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/FirDeclarationDesignation.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/FirDeclarationDesignation.kt @@ -12,71 +12,86 @@ import org.jetbrains.kotlin.fir.renderWithType import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.toFirRegularClass -class FirDeclarationDesignation( +class FirDeclarationDesignationWithFile( + path: List, + declaration: FirDeclaration, + isLocalDesignation: Boolean, + val firFile: FirFile +) : FirDeclarationDesignation( + path, + declaration, + isLocalDesignation +) { + fun toSequenceWithFile(includeTarget: Boolean): Sequence = sequence { + yield(firFile) + yieldAll(path) + if (includeTarget) yield(declaration) + } +} + +open class FirDeclarationDesignation( val path: List, val declaration: FirDeclaration, - val isLocalDesignation: Boolean, + val isLocalDesignation: Boolean ) { - @OptIn(ExperimentalStdlibApi::class) - val fullDesignation = buildList { - addAll(path) - add(declaration) + fun toSequence(includeTarget: Boolean): Sequence = sequence { + yieldAll(path) + if (includeTarget) yield(declaration) } } +private fun collectDesignationAndIsLocal(declaration: FirDeclaration): Pair, Boolean> { + val firProvider = declaration.moduleData.session.firProvider -object DeclarationDesignationCollector { - fun collectDesignation(declaration: FirDeclaration): FirDeclarationDesignation { - val firProvider = declaration.moduleData.session.firProvider + val containingClass = when (declaration) { + is FirCallableDeclaration<*> -> declaration.containingClass()?.toFirRegularClass(declaration.moduleData.session) + is FirClassLikeDeclaration<*> -> declaration.symbol.classId.outerClassId?.let(firProvider::getFirClassifierByFqName) + else -> error("Invalid declaration ${declaration.renderWithType()}") + } ?: return emptyList() to false - val containingClass = when (declaration) { - is FirCallableDeclaration<*> -> declaration.containingClass()?.toFirRegularClass(declaration.moduleData.session) - 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 - ) + require(containingClass is FirRegularClass) { + "FirRegularClass as containing declaration expected but found ${containingClass.renderWithType()}" } - private fun FirRegularClass.collectForNonLocal(): List> { - require(!isLocal) - val firProvider = moduleData.session.firProvider - var containingClassId = classId.outerClassId - val designation = mutableListOf>(this) - while (containingClassId != null) { - val currentClass = firProvider.getFirClassifierByFqName(containingClassId) ?: break - designation.add(currentClass) - containingClassId = containingClassId.outerClassId - } - return designation - } - - private fun FirRegularClass.collectForLocal(): List> { - require(isLocal) - var containingClassLookUp = containingClassForLocal() - val designation = mutableListOf>(this) - while (containingClassLookUp != null && containingClassLookUp.classId.isLocal) { - val currentClass = containingClassLookUp.toFirRegularClass(moduleData.session) ?: break - designation.add(currentClass) - containingClassLookUp = currentClass.containingClassForLocal() - } - return designation + val path = when { + containingClass.isLocal -> containingClass.collectForLocal() + else -> containingClass.collectForNonLocal() } + return path.reversed() to containingClass.isLocal } +private fun FirRegularClass.collectForNonLocal(): List { + require(!isLocal) + val firProvider = moduleData.session.firProvider + var containingClassId = classId.outerClassId + val designation = mutableListOf(this) + while (containingClassId != null) { + val currentClass = firProvider.getFirClassifierByFqName(containingClassId) ?: break + designation.add(currentClass) + containingClassId = containingClassId.outerClassId + } + return designation +} + +private fun FirRegularClass.collectForLocal(): List> { + require(isLocal) + var containingClassLookUp = containingClassForLocal() + val designation = mutableListOf>(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 = - DeclarationDesignationCollector.collectDesignation(this) + collectDesignationAndIsLocal(this).let { + FirDeclarationDesignation(it.first, this, it.second) + } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/LowLevelFirApiFacadeForResolveOnAir.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/LowLevelFirApiFacadeForResolveOnAir.kt index 90b251658ff..f8886234681 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/LowLevelFirApiFacadeForResolveOnAir.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/LowLevelFirApiFacadeForResolveOnAir.kt @@ -61,16 +61,14 @@ object LowLevelFirApiFacadeForResolveOnAir { } } - private fun onAirResolveElement( + fun onAirResolveElement( state: FirModuleResolveState, place: T, elementToResolve: T, - ): FirModuleResolveState { + ): FirElement { require(state is FirModuleResolveStateImpl) require(place.isPhysical) - require(!elementToResolve.isPhysical) - val collector = FirTowerDataContextAllElementsCollector() val declaration = runResolveBodyResolveOnAir( state = state, replacement = RawFirReplacement(place, elementToResolve), @@ -88,10 +86,9 @@ object LowLevelFirApiFacadeForResolveOnAir { element.acceptChildren(this) } } - declaration.accept(expressionLocator) - val recordedMap = FirElementsRecorder.recordElementsFrom(declaration, FirElementsRecorder()) - return FirModuleResolveStateDepended(state, collector, recordedMap) + declaration.accept(expressionLocator) + return expressionLocator.result ?: error("Resolved on-air element was not found in containing declaration") } fun onAirGetTowerContextProvider( diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/fir/ContextCollectingDiagnosticCollectorVisitor.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/fir/ContextCollectingDiagnosticCollectorVisitor.kt index 839726efa93..ae93f5f7499 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/fir/ContextCollectingDiagnosticCollectorVisitor.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/fir/ContextCollectingDiagnosticCollectorVisitor.kt @@ -13,16 +13,16 @@ import org.jetbrains.kotlin.fir.renderWithType 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.api.FirDeclarationDesignation +import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirDeclarationDesignationWithFile import org.jetbrains.kotlin.idea.fir.low.level.api.api.collectDesignation private class ContextCollectingDiagnosticCollectorVisitor private constructor( sessionHolder: SessionHolder, - designation: FirDeclarationDesignation, - firFile: FirFile, + designation: FirDeclarationDesignationWithFile, ) : AbstractDiagnosticCollectorVisitor( PersistentCheckerContextFactory.createEmptyPersistenceCheckerContext(sessionHolder) ) { - private val contextCollector = object : ContextByDesignationCollector(designation, firFile) { + private val contextCollector = object : ContextByDesignationCollector(designation) { override fun getCurrentContext(): PersistentCheckerContext = context override fun goToNestedDeclaration(declaration: FirDeclaration) { @@ -41,9 +41,9 @@ private class ContextCollectingDiagnosticCollectorVisitor private constructor( override fun checkElement(element: FirElement) {} companion object { - fun collect(sessionHolder: SessionHolder, firFile: FirFile, designation: FirDeclarationDesignation): PersistentCheckerContext { - val visitor = ContextCollectingDiagnosticCollectorVisitor(sessionHolder, designation, firFile) - firFile.accept(visitor, null) + fun collect(sessionHolder: SessionHolder, designation: FirDeclarationDesignationWithFile): PersistentCheckerContext { + val visitor = ContextCollectingDiagnosticCollectorVisitor(sessionHolder, designation) + designation.firFile.accept(visitor, null) return visitor.contextCollector.getCollectedContext() } } @@ -63,10 +63,10 @@ internal object PersistenceContextCollector { require(!isLocal) { "Cannot collect context for local declaration ${declaration.renderWithType()}" } - val designation = declaration.collectDesignation() + val designation = declaration.collectDesignation(firFile) check(!designation.isLocalDesignation) { "Designation should not local for ${declaration.renderWithType()}" } - return ContextCollectingDiagnosticCollectorVisitor.collect(sessionHolder, firFile, designation) + return ContextCollectingDiagnosticCollectorVisitor.collect(sessionHolder, designation) } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyBodiesCalculator.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyBodiesCalculator.kt index 601ac422769..b402b4328b8 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyBodiesCalculator.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyBodiesCalculator.kt @@ -24,7 +24,7 @@ internal object FirLazyBodiesCalculator { fun calculateLazyBodiesInside(element: FirElement, designation: FirDeclarationDesignation) { element.transform>( FirLazyBodiesCalculatorTransformer, - designation.fullDesignation.toMutableList() + designation.toSequence(includeTarget = true).toMutableList() ) } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt index 685ce0e701d..375226d95f1 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt @@ -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.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 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.file.builder.FirFileBuilder @@ -143,7 +144,7 @@ internal class FirLazyDeclarationResolver( resolveFileAnnotations(containerFirFile, moduleFileCache, scopeSession) val nonLocalDeclarationToResolve = firDeclarationToResolve.getNonLocalDeclarationToResolve(provider, moduleFileCache) - val designation = nonLocalDeclarationToResolve.collectDesignation() + val designation = nonLocalDeclarationToResolve.collectDesignation(containerFirFile) executeWithoutPCE { calculateLazyBodies(firDeclarationToResolve, designation) @@ -156,7 +157,6 @@ internal class FirLazyDeclarationResolver( if (currentPhase.pluginPhase) continue if (checkPCE) checkCanceled() runLazyResolvePhase( - containerFirFile, currentPhase, scopeSession, towerDataContextCollector, @@ -167,20 +167,18 @@ internal class FirLazyDeclarationResolver( } private fun runLazyResolvePhase( - containerFirFile: FirFile, phase: FirResolvePhase, scopeSession: ScopeSession, towerDataContextCollector: FirTowerDataContextCollector?, firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?, - designation: FirDeclarationDesignation + designation: FirDeclarationDesignationWithFile ) { - if (designation.fullDesignation.all { it.resolvePhase >= phase }) { + if (designation.toSequence(includeTarget = true).all { it.resolvePhase >= phase }) { return } val transformer = phase.createLazyTransformer( designation, - containerFirFile, scopeSession, towerDataContextCollector, firProviderInterceptor, @@ -192,46 +190,41 @@ internal class FirLazyDeclarationResolver( } private fun FirResolvePhase.createLazyTransformer( - designation: FirDeclarationDesignation, - containerFirFile: FirFile, + designation: FirDeclarationDesignationWithFile, scopeSession: ScopeSession, towerDataContextCollector: FirTowerDataContextCollector?, firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?, ): FirLazyTransformerForIDE = when (this) { FirResolvePhase.SUPER_TYPES -> FirDesignatedSupertypeResolverTransformerForIDE( designation, - containerFirFile.moduleData.session, + designation.firFile.moduleData.session, scopeSession, firProviderInterceptor, ) FirResolvePhase.SEALED_CLASS_INHERITORS -> FirLazyTransformerForIDE.EMPTY FirResolvePhase.TYPES -> FirDesignatedTypeResolverTransformerForIDE( - containerFirFile, designation, - containerFirFile.moduleData.session, + designation.firFile.moduleData.session, scopeSession, ) FirResolvePhase.STATUS -> FirDesignatedStatusResolveTransformerForIDE( designation, - containerFirFile.moduleData.session, + designation.firFile.moduleData.session, scopeSession ) FirResolvePhase.CONTRACTS -> FirDesignatedContractsResolveTransformerForIDE( - containerFirFile, designation, - containerFirFile.moduleData.session, + designation.firFile.moduleData.session, scopeSession, ) FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE -> FirDesignatedImplicitTypesTransformerForIDE( - containerFirFile, designation, - containerFirFile.moduleData.session, + designation.firFile.moduleData.session, scopeSession ) FirResolvePhase.BODY_RESOLVE -> FirDesignatedBodyResolveTransformerForIDE( - containerFirFile, designation, - containerFirFile.moduleData.session, + designation.firFile.moduleData.session, scopeSession, towerDataContextCollector, firProviderInterceptor diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedBodyResolveTransformerForIDE.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedBodyResolveTransformerForIDE.kt index 3529e590d96..dd81a650648 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedBodyResolveTransformerForIDE.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedBodyResolveTransformerForIDE.kt @@ -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.body.resolve.* 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 internal class FirDesignatedBodyResolveTransformerForIDE( - private val firFile: FirFile, - designation: FirDeclarationDesignation, + private val designation: FirDeclarationDesignationWithFile, session: FirSession, scopeSession: ScopeSession, towerDataContextCollector: FirTowerDataContextCollector? = null, @@ -37,19 +37,19 @@ internal class FirDesignatedBodyResolveTransformerForIDE( firTowerDataContextCollector = towerDataContextCollector, firProviderInterceptor = firProviderInterceptor, ) { - private val ideDeclarationTransformer = IDEDeclarationTransformer(designation.toDesignationIterator()) + private val ideDeclarationTransformer = IDEDeclarationTransformer(designation) @Suppress("NAME_SHADOWING") override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration = - ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) { declaration, data -> + ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) { super.transformDeclarationContent(declaration, data) } override fun needReplacePhase(firDeclaration: FirDeclaration): Boolean = - ideDeclarationTransformer.needReplacePhase(firDeclaration) + ideDeclarationTransformer.needReplacePhase override fun transformDeclaration() { - firFile.transform(this, ResolutionMode.ContextDependent) + designation.firFile.transform(this, ResolutionMode.ContextDependent) } } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedContractsResolveTransformerForIDE.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedContractsResolveTransformerForIDE.kt index 9f931798650..188392ce5c6 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedContractsResolveTransformerForIDE.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedContractsResolveTransformerForIDE.kt @@ -11,26 +11,25 @@ import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession 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( - private val firFile: FirFile, - designation: FirDeclarationDesignation, + private val designation: FirDeclarationDesignationWithFile, session: FirSession, scopeSession: ScopeSession, ) : FirLazyTransformerForIDE, FirContractResolveTransformer(session, scopeSession) { - private val ideDeclarationTransformer = IDEDeclarationTransformer(designation.toDesignationIterator()) + private val ideDeclarationTransformer = IDEDeclarationTransformer(designation) @Suppress("NAME_SHADOWING") override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration = - ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) { declaration, data -> + ideDeclarationTransformer.transformDeclarationContent(this, 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() { - firFile.transform(this, ResolutionMode.ContextDependent) + designation.firFile.transform(this, ResolutionMode.ContextDependent) } } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedImplicitTypesTransformerForIDE.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedImplicitTypesTransformerForIDE.kt index d0312f284ec..2a5f73a90f7 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedImplicitTypesTransformerForIDE.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedImplicitTypesTransformerForIDE.kt @@ -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.ImplicitBodyResolveComputationSession 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 internal class FirDesignatedImplicitTypesTransformerForIDE( - private val firFile: FirFile, - designation: FirDeclarationDesignation, + private val designation: FirDeclarationDesignationWithFile, session: FirSession, scopeSession: ScopeSession, implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession = ImplicitBodyResolveComputationSession(), @@ -36,17 +35,17 @@ internal class FirDesignatedImplicitTypesTransformerForIDE( ::FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator ) ) { - private val ideDeclarationTransformer = IDEDeclarationTransformer(designation.toDesignationIterator()) + private val ideDeclarationTransformer = IDEDeclarationTransformer(designation) @Suppress("NAME_SHADOWING") override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration = - ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) { declaration, data -> + ideDeclarationTransformer.transformDeclarationContent(this, 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() { - firFile.transform(this, ResolutionMode.ContextDependent) + designation.firFile.transform(this, ResolutionMode.ContextDependent) } } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedStatusResolveTransformerForIDE.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedStatusResolveTransformerForIDE.kt index 344680ae47e..f255f41850d 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedStatusResolveTransformerForIDE.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedStatusResolveTransformerForIDE.kt @@ -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.StatusComputationSession 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 class FirDesignatedStatusResolveTransformerForIDE( - private val designation: FirDeclarationDesignation, + 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.fullDesignation.iterator(), + designation = designation.toSequence(includeTarget = true).iterator(), targetClass = targetClass, statusComputationSession = StatusComputationSession.Regular(), designationMapForLocalClasses = emptyMap(), - scopeForLocalClass = null) + scopeForLocalClass = null + ) - val firstClass = designation.fullDesignation.first() - firstClass.transformSingle(transformer, 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 resolveTopLevelMethod(targetCallable: FirCallableDeclaration<*>) { @@ -50,11 +66,12 @@ class FirDesignatedStatusResolveTransformerForIDE( val transformer = object : FirDesignatedStatusResolveTransformer( session = session, scopeSession = scopeSession, - designation = designation.fullDesignation.iterator(), + designation = designation.toSequence(includeTarget = true).iterator(), targetClass = containingClass, statusComputationSession = StatusComputationSession.Regular(), designationMapForLocalClasses = emptyMap(), - scopeForLocalClass = null) { + scopeForLocalClass = null + ) { override fun > transformClass( klass: FirClass, @@ -66,25 +83,25 @@ class FirDesignatedStatusResolveTransformerForIDE( } } - val firstClass = designation.fullDesignation.first() - firstClass.transformSingle(transformer, null) + firstItemInDesignation.transformSingle(transformer, null) } override fun transformDeclaration() { - designation.ensurePhase(FirResolvePhase.STATUS, exceptLast = true) - when(val resolveTarget = designation.declaration) { + designation.ensurePhase(FirResolvePhase.STATUS, exceptTarget = true) + when (val resolveTarget = designation.declaration) { is FirClass<*> -> resolveClass(resolveTarget) + is FirTypeAlias -> resolveTypeAlias(resolveTarget) is FirCallableDeclaration<*> -> { val containingClass = designation.path.lastOrNull() 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) } else { check(containingClass is FirClass<*>) { "Invalid designation - the parent of callable is not a class" } 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}") } } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedSupertypeResolverTransformerForIDE.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedSupertypeResolverTransformerForIDE.kt index 8bb1ab8c4e7..4880ae4474f 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedSupertypeResolverTransformerForIDE.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedSupertypeResolverTransformerForIDE.kt @@ -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.SupertypeComputationSession 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 internal class FirDesignatedSupertypeResolverTransformerForIDE( - private val designation: FirDeclarationDesignation, + private val designation: FirDeclarationDesignationWithFile, private val session: FirSession, private val scopeSession: ScopeSession, private val firProviderInterceptor: FirProviderInterceptorForSupertypeResolver?, @@ -26,7 +27,7 @@ internal class FirDesignatedSupertypeResolverTransformerForIDE( private val supertypeComputationSession = SupertypeComputationSession() override fun transformDeclaration() { - designation.ensurePhase(FirResolvePhase.SUPER_TYPES, exceptLast = true) + designation.ensurePhase(FirResolvePhase.SUPER_TYPES, exceptTarget = true) val resolver = FirSupertypeResolverVisitor( session = session, diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedTypeResolverTransformerForIDE.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedTypeResolverTransformerForIDE.kt index 8a081dbd991..c7c4c0ff32f 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedTypeResolverTransformerForIDE.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignatedTypeResolverTransformerForIDE.kt @@ -10,34 +10,33 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.ScopeSession 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 class FirDesignatedTypeResolverTransformerForIDE( - private val originalFile: FirFile, - private val designation: FirDeclarationDesignation, + private val designation: FirDeclarationDesignationWithFile, session: FirSession, 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") override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): FirStatement { - return ideDeclarationTransformer.transformDeclarationContent(this, regularClass, data) { klass, data -> - super.transformRegularClass(klass, data) as FirRegularClass + return ideDeclarationTransformer.transformDeclarationContent(this, regularClass, data) { + super.transformRegularClass(regularClass, data) as FirRegularClass } } @Suppress("NAME_SHADOWING") 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 } } override fun transformDeclaration() { - designation.ensurePhase(FirResolvePhase.TYPES, exceptLast = true) - originalFile.transform(this, null) + designation.ensurePhase(FirResolvePhase.TYPES, exceptTarget = true) + designation.firFile.transform(this, null) } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignationIterator.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignationIterator.kt deleted file mode 100644 index 15fb274dd85..00000000000 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirDesignationIterator.kt +++ /dev/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) { - 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() - } - } -} \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirLazyTransformerForIDE.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirLazyTransformerForIDE.kt index afe5d5d5a1b..b6747288c6c 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirLazyTransformerForIDE.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/FirLazyTransformerForIDE.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.transformers 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 { fun transformDeclaration() @@ -16,10 +16,10 @@ internal interface FirLazyTransformerForIDE { override fun transformDeclaration() = Unit } - fun FirDeclarationDesignation.ensurePhase(firResolvePhase: FirResolvePhase, exceptLast: Boolean) { - val designationList = if (exceptLast) path else fullDesignation - designationList.forEach { firDeclaration -> - check (firDeclaration.resolvePhase >= firResolvePhase) { + fun FirDeclarationDesignationWithFile.ensurePhase(firResolvePhase: FirResolvePhase, exceptTarget: Boolean) { + val designationIterator = toSequence(includeTarget = !exceptTarget) + designationIterator.forEach { firDeclaration -> + check(firDeclaration.resolvePhase >= firResolvePhase) { "Designation element phase required to be $firResolvePhase but element resolved to ${firDeclaration.resolvePhase}" } } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/IDEDeclarationTransformer.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/IDEDeclarationTransformer.kt index eb37c6f9532..9184dfde83f 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/IDEDeclarationTransformer.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/transformers/IDEDeclarationTransformer.kt @@ -6,49 +6,41 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.transformers import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.transformers.FirAbstractPhaseTransformer 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 inline fun insideTargetDeclaration(insideCurrent: Boolean, action: () -> R): R { - val oldValue = isInsideTargetDeclaration - isInsideTargetDeclaration = insideCurrent - try { - return action() - } finally { - isInsideTargetDeclaration = oldValue - } - } - inline fun transformDeclarationContent( transformer: FirAbstractPhaseTransformer, declaration: K, data: D, - transformDeclaration: (K, D) -> K + defaultCallTransform: () -> K ): K { - return if (designationIterator.canGoNext()) { - val declarationToTransform = designationIterator.currentDeclaration - val isTargetDeclaration = designationIterator.isTargetDeclaration() - designationIterator.goNext() - insideTargetDeclaration(isTargetDeclaration) { - declarationToTransform.visitNoTransform(transformer, data) - } - declaration + + if (isInsideTargetDeclaration) { + return defaultCallTransform() + } + + if (designationWithoutTargetIterator.hasNext()) { + designationWithoutTargetIterator.next().visitNoTransform(transformer, data) } else { - if (isInsideTargetDeclaration) { - transformDeclaration(declaration, data) - } else { - declaration + try { + isInsideTargetDeclaration = true + designation.declaration.visitNoTransform(transformer, data) + } finally { + isInsideTargetDeclaration = false } } + + return declaration } - fun needReplacePhase(firDeclaration: FirDeclaration): Boolean = - isInsideTargetDeclaration + val needReplacePhase: Boolean get() = isInsideTargetDeclaration } private fun FirElement.visitNoTransform(transformer: FirTransformer, data: D) { diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/renderer/ConeTypeIdeRenderer.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/renderer/ConeTypeIdeRenderer.kt index 4608944f934..c830c1932c5 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/renderer/ConeTypeIdeRenderer.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/renderer/ConeTypeIdeRenderer.kt @@ -196,7 +196,9 @@ internal class ConeTypeIdeRenderer( } val classToRender = classSymbolToRender.fir - val designation = classToRender.collectDesignation().fullDesignation + val designation = classToRender.collectDesignation() + .toSequence(includeTarget = true) + .toList() var typeParametersLeft = type.typeArguments.count() fun needToRenderTypeParameters(index: Int): Boolean {