From a22514cf8e54a78c39d5a4d9cfa2412fb3989f51 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 13 Oct 2020 22:29:18 +0300 Subject: [PATCH] FIR IDE: separate lazy phase into 3 phases, add contracts phase --- .../body/resolve/FirImplicitBodyResolve.kt | 3 +- .../FirContractResolveTransformer.kt | 2 +- .../idea/fir/low/level/api/FirPhaseRunner.kt | 19 ++++++ .../AbstractFirIdeDiagnosticsCollector.kt | 2 + .../resolve/FirLazyDeclarationResolver.kt | 68 ++++++++++++++----- ...rDesignatedBodyResolveTransformerForIDE.kt | 19 +++--- ...gnatedContractsResolveTransformerForIDE.kt | 30 ++++++++ ...esignatedImplicitTypesTransformerForIDE.kt | 47 +++++++++++++ 8 files changed, 163 insertions(+), 27 deletions(-) rename idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/{element/builder => trasformers}/FirDesignatedBodyResolveTransformerForIDE.kt (80%) create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/trasformers/FirDesignatedContractsResolveTransformerForIDE.kt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/trasformers/FirDesignatedImplicitTypesTransformerForIDE.kt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt index 17e2ee9c908..747ff610fa2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirImplicitBodyResolve.kt @@ -103,6 +103,7 @@ fun > F.runContractAndBodiesResolutionForLocalClass( fun createReturnTypeCalculatorForIDE( session: FirSession, scopeSession: ScopeSession, + implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession, createTransformer: ( designation: Iterator, FirSession, @@ -112,7 +113,7 @@ fun createReturnTypeCalculatorForIDE( BodyResolveContext? ) -> FirDesignatedBodyResolveTransformerForReturnTypeCalculator ): ReturnTypeCalculator = - ReturnTypeCalculatorWithJump(session, scopeSession, ImplicitBodyResolveComputationSession(), createTransformer = createTransformer) + ReturnTypeCalculatorWithJump(session, scopeSession, implicitBodyResolveComputationSession, createTransformer = createTransformer) open class FirImplicitAwareBodyResolveTransformer( session: FirSession, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirContractResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirContractResolveTransformer.kt index 9972a94325d..a3029da24a2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirContractResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/contracts/FirContractResolveTransformer.kt @@ -31,7 +31,7 @@ import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.name.Name -class FirContractResolveTransformer( +open class FirContractResolveTransformer( session: FirSession, scopeSession: ScopeSession, outerBodyResolveContext: BodyResolveContext? = null diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirPhaseRunner.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirPhaseRunner.kt index 5e174e001fe..5e824fc4807 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirPhaseRunner.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirPhaseRunner.kt @@ -28,6 +28,25 @@ internal class FirPhaseRunner(val transformerProvider: FirTransformerProvider) { } } + inline fun runPhaseWithCustomResolve(phase: FirResolvePhase, crossinline resolve: () -> Unit) = when (phase) { + FirResolvePhase.SUPER_TYPES -> superTypesBodyResolveLock.withLock { + runPhaseWithCustomResolveWithoutLock(resolve) + } + FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE -> implicitTypesResolveLock.withLock { + runPhaseWithCustomResolveWithoutLock(resolve) + } + else -> { + runPhaseWithCustomResolveWithoutLock(resolve) + } + } + + private inline fun runPhaseWithCustomResolveWithoutLock(crossinline resolve: () -> Unit) { + executeWithoutPCE { + resolve() + } + } + + private fun runPhaseWithoutLock(firFile: FirFile, phase: FirResolvePhase) { val phaseProcessor = transformerProvider.getTransformerForPhase(firFile.session, phase) executeWithoutPCE { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt index aebf26da64c..bcffaf80017 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic import org.jetbrains.kotlin.fir.resolve.ScopeSession +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.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled @@ -26,6 +27,7 @@ internal abstract class AbstractFirIdeDiagnosticsCollector( returnTypeCalculator = createReturnTypeCalculatorForIDE( session, ScopeSession(), + ImplicitBodyResolveComputationSession(), ::FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator ) ) { 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 30a9860645a..28c4081318a 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 @@ -11,11 +11,13 @@ import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirTowerDataContextCollector -import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirDesignatedBodyResolveTransformerForIDE +import org.jetbrains.kotlin.idea.fir.low.level.api.trasformers.FirDesignatedBodyResolveTransformerForIDE 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.ModuleFileCache import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider +import org.jetbrains.kotlin.idea.fir.low.level.api.trasformers.FirDesignatedContractsResolveTransformerForIDE +import org.jetbrains.kotlin.idea.fir.low.level.api.trasformers.FirDesignatedImplicitTypesTransformerForIDE import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled import org.jetbrains.kotlin.idea.fir.low.level.api.util.executeWithoutPCE import org.jetbrains.kotlin.idea.fir.low.level.api.util.findSourceNonLocalFirDeclaration @@ -41,9 +43,6 @@ internal class FirLazyDeclarationResolver( if (checkPCE) { firFileBuilder.runCustomResolveWithPCECheck(firFile, moduleFileCache) { - executeWithoutPCE { - calculateLazyBodies(declaration) - } runLazyResolveWithoutLock( declaration, moduleFileCache, @@ -58,7 +57,6 @@ internal class FirLazyDeclarationResolver( } else { firFileBuilder.runCustomResolveUnderLock(firFile, moduleFileCache) { executeWithoutPCE { - calculateLazyBodies(declaration) runLazyResolveWithoutLock( declaration, moduleFileCache, @@ -89,7 +87,7 @@ internal class FirLazyDeclarationResolver( checkPCE: Boolean, ) { if (fromPhase >= toPhase) return - val nonLazyPhase = minOf(toPhase, FirResolvePhase.DECLARATIONS) + val nonLazyPhase = minOf(toPhase, LAST_NON_LAZY_PHASE) if (fromPhase < nonLazyPhase) { firFileBuilder.runResolveWithoutLock( containerFirFile, @@ -99,8 +97,25 @@ internal class FirLazyDeclarationResolver( ) } if (toPhase <= nonLazyPhase) return - if (checkPCE) checkCanceled() - runLazyResolvePhase(firDeclarationToResolve, containerFirFile, moduleFileCache, provider, toPhase, towerDataContextCollector) + + executeWithoutPCE { + calculateLazyBodies(firDeclarationToResolve) + } + + var currentPhase = nonLazyPhase + while (currentPhase < toPhase) { + currentPhase = currentPhase.next + if (currentPhase.pluginPhase) continue + if (checkPCE) checkCanceled() + runLazyResolvePhase( + firDeclarationToResolve, + containerFirFile, + moduleFileCache, + provider, + currentPhase, + towerDataContextCollector + ) + } } private fun runLazyResolvePhase( @@ -108,7 +123,7 @@ internal class FirLazyDeclarationResolver( containerFirFile: FirFile, moduleFileCache: ModuleFileCache, provider: FirProvider, - toPhase: FirResolvePhase, + phase: FirResolvePhase, towerDataContextCollector: FirTowerDataContextCollector?, ) { val nonLocalDeclarationToResolve = firDeclarationToResolve.getNonLocalDeclarationToResolve(provider, moduleFileCache) @@ -132,21 +147,36 @@ internal class FirLazyDeclarationResolver( designation += nonLocalDeclarationToResolve } } - if (designation.all { it.resolvePhase >= toPhase }) { + if (designation.all { it.resolvePhase >= phase }) { return } val scopeSession = firFileBuilder.firPhaseRunner.transformerProvider.getScopeSession(containerFirFile.session) - val transformer = FirDesignatedBodyResolveTransformerForIDE( - designation.iterator(), containerFirFile.session, - scopeSession, - toPhase, - towerDataContextCollector - ) - executeWithoutPCE { + val transformer = when (phase) { + FirResolvePhase.CONTRACTS -> FirDesignatedContractsResolveTransformerForIDE( + designation.iterator(), + containerFirFile.session, + scopeSession, + ) + FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE -> FirDesignatedImplicitTypesTransformerForIDE( + designation.iterator(), + containerFirFile.session, + scopeSession, + ) + FirResolvePhase.BODY_RESOLVE -> FirDesignatedBodyResolveTransformerForIDE( + designation.iterator(), + containerFirFile.session, + scopeSession, + towerDataContextCollector + ) + else -> error("Non-lazy phase $phase") + } + + firFileBuilder.firPhaseRunner.runPhaseWithCustomResolve(phase) { containerFirFile.transform(transformer, ResolutionMode.ContextDependent) } } + private fun FirDeclaration.getNonLocalDeclarationToResolve(provider: FirProvider, moduleFileCache: ModuleFileCache): FirDeclaration { if (this is FirFile) return this val ktDeclaration = psi as? KtDeclaration ?: error("FirDeclaration should have a PSI of type KtDeclaration") @@ -155,6 +185,10 @@ internal class FirLazyDeclarationResolver( ?: error("Container for local declaration cannot be null") return nonLocalPsi.findSourceNonLocalFirDeclaration(firFileBuilder, provider.symbolProvider, moduleFileCache) } + + companion object { + private val LAST_NON_LAZY_PHASE = FirResolvePhase.STATUS + } } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/element/builder/FirDesignatedBodyResolveTransformerForIDE.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/trasformers/FirDesignatedBodyResolveTransformerForIDE.kt similarity index 80% rename from idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/element/builder/FirDesignatedBodyResolveTransformerForIDE.kt rename to idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/trasformers/FirDesignatedBodyResolveTransformerForIDE.kt index 5266e83eea4..0458ba0c22c 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/element/builder/FirDesignatedBodyResolveTransformerForIDE.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/trasformers/FirDesignatedBodyResolveTransformerForIDE.kt @@ -3,7 +3,7 @@ * 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.element.builder +package org.jetbrains.kotlin.idea.fir.low.level.api.trasformers import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession @@ -13,32 +13,31 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer +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.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.compose +import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator +import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirTowerDataContextCollector internal class FirDesignatedBodyResolveTransformerForIDE( private val designation: Iterator, session: FirSession, scopeSession: ScopeSession, - phase: FirResolvePhase, private val towerDataContextCollector: FirTowerDataContextCollector? = null ) : FirBodyResolveTransformer( session, - phase = phase, - implicitTypeOnly = phase == FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, + phase = FirResolvePhase.BODY_RESOLVE, + implicitTypeOnly = false, scopeSession = scopeSession, returnTypeCalculator = createReturnTypeCalculatorForIDE( session, scopeSession, + ImplicitBodyResolveComputationSession(), ::FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator ) ) { - override fun onBeforeDeclarationContentResolve(declaration: FirDeclaration) { - towerDataContextCollector?.addDeclarationContext(declaration, context.towerDataContext) - } - override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): CompositeTransformResult { if (designation.hasNext()) { designation.next().visitNoTransform(this, data) @@ -48,6 +47,10 @@ internal class FirDesignatedBodyResolveTransformerForIDE( return super.transformDeclarationContent(declaration, data) } + override fun onBeforeDeclarationContentResolve(declaration: FirDeclaration) { + towerDataContextCollector?.addDeclarationContext(declaration, context.towerDataContext) + } + override fun onBeforeStatementResolution(statement: FirStatement) { towerDataContextCollector?.addStatementContext(statement, context.towerDataContext) } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/trasformers/FirDesignatedContractsResolveTransformerForIDE.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/trasformers/FirDesignatedContractsResolveTransformerForIDE.kt new file mode 100644 index 00000000000..7797053b288 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/trasformers/FirDesignatedContractsResolveTransformerForIDE.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2020 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.trasformers + +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +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.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.compose + +internal class FirDesignatedContractsResolveTransformerForIDE( + private val designation: Iterator, + session: FirSession, + scopeSession: ScopeSession, +) : FirContractResolveTransformer(session, scopeSession) { + + override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): CompositeTransformResult { + if (designation.hasNext()) { + designation.next().visitNoTransform(this, data) + return declaration.compose() + } + return super.transformDeclarationContent(declaration, data) + } +} diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/trasformers/FirDesignatedImplicitTypesTransformerForIDE.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/trasformers/FirDesignatedImplicitTypesTransformerForIDE.kt new file mode 100644 index 00000000000..2b34b72529e --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/trasformers/FirDesignatedImplicitTypesTransformerForIDE.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2020 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.trasformers + +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.resolve.ResolutionMode +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.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.compose +import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator + +internal class FirDesignatedImplicitTypesTransformerForIDE( + private val designation: Iterator, + session: FirSession, + scopeSession: ScopeSession, + implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession = ImplicitBodyResolveComputationSession(), +) : FirImplicitAwareBodyResolveTransformer( + session, + implicitBodyResolveComputationSession = implicitBodyResolveComputationSession, + phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, + implicitTypeOnly = true, + scopeSession = scopeSession, + returnTypeCalculator = createReturnTypeCalculatorForIDE( + session, + scopeSession, + implicitBodyResolveComputationSession, + ::FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator + ) +) { + + override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): CompositeTransformResult { + if (designation.hasNext()) { + designation.next().visitNoTransform(this, data) + return declaration.compose() + } + return super.transformDeclarationContent(declaration, data) + } +}