From 703150e3add052a4a69ccb1dc3546c069f878693 Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Wed, 9 Sep 2020 17:17:57 +0300 Subject: [PATCH] FIR IDE: Refactor `LowLevelFirApiFacade.kt` --- .../fir/low/level/api/LowLevelFirApiFacade.kt | 123 ++++++++++-------- 1 file changed, 71 insertions(+), 52 deletions(-) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt index 388bdc51c82..f581b5ac3b7 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/LowLevelFirApiFacade.kt @@ -8,11 +8,8 @@ package org.jetbrains.kotlin.idea.fir.low.level.api import com.intellij.psi.PsiElement import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirProperty -import org.jetbrains.kotlin.fir.declarations.FirResolvePhase -import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyAccessorCopy import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunctionCopy import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyCopy @@ -24,6 +21,7 @@ import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirTowerDataContextCollector +import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider import org.jetbrains.kotlin.idea.util.getElementTextInContext import org.jetbrains.kotlin.psi.KtProperty @@ -64,34 +62,22 @@ object LowLevelFirApiFacade { fun buildCompletionContextForFunction( firFile: FirFile, - element: KtNamedFunction, + fakeElement: KtNamedFunction, originalElement: KtNamedFunction, state: FirModuleResolveState, phase: FirResolvePhase = FirResolvePhase.BODY_RESOLVE ): FirCompletionContext { val firIdeProvider = firFile.session.firIdeProvider + val originalFunction = state.getOrBuildFirFor(originalElement, phase) as FirSimpleFunction - val builtFunction = firIdeProvider.buildFunctionWithBody(element) + val copyFunction = buildFunctionCopyForCompletion(firIdeProvider, fakeElement, originalFunction, state) + val contextCollector = FirTowerDataContextCollector() - - // right now we can't resolve builtFunction header properly, as it built right in air, - // without file, which is now required for running stages other then body resolve, so we - // take original function header (which is resolved) and copy replacing body with body from builtFunction - val frankensteinFunction = buildSimpleFunctionCopy(originalFunction) { - body = builtFunction.body - symbol = builtFunction.symbol as FirNamedFunctionSymbol - resolvePhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS) - source = builtFunction.source - this.session = state.firIdeSourcesSession - } - - val function = frankensteinFunction.apply { - state.lazyResolveDeclarationForCompletion(this, firFile, firIdeProvider, phase, contextCollector) - state.recordPsiToFirMappingsForCompletionFrom(this, firFile, element.containingKtFile) - } + state.lazyResolveDeclarationForCompletion(copyFunction, firFile, firIdeProvider, phase, contextCollector) + state.recordPsiToFirMappingsForCompletionFrom(copyFunction, firFile, fakeElement.containingKtFile) return FirCompletionContext( - function.session, + copyFunction.session, contextCollector, state ) @@ -99,49 +85,82 @@ object LowLevelFirApiFacade { fun buildCompletionContextForProperty( firFile: FirFile, - element: KtProperty, + fakeElement: KtProperty, originalElement: KtProperty, state: FirModuleResolveState, phase: FirResolvePhase = FirResolvePhase.BODY_RESOLVE ): FirCompletionContext { val firIdeProvider = firFile.session.firIdeProvider - val originalProperty = state.getOrBuildFirFor(originalElement, phase) as FirProperty - val builtProperty = firIdeProvider.buildPropertyWithBody(element) - val contextCollector = FirTowerDataContextCollector() - val frankensteinProperty = buildPropertyCopy(originalProperty) { + val originalProperty = state.getOrBuildFirFor(originalElement, phase) as FirProperty + val copyProperty = buildPropertyCopyForCompletion(firIdeProvider, fakeElement, originalProperty, state) + + val contextCollector = FirTowerDataContextCollector() + state.lazyResolveDeclarationForCompletion(copyProperty, firFile, firIdeProvider, phase, contextCollector) + state.recordPsiToFirMappingsForCompletionFrom(copyProperty, firFile, fakeElement.containingKtFile) + + return FirCompletionContext( + copyProperty.session, + contextCollector, + state + ) + } + + private fun buildFunctionCopyForCompletion( + firIdeProvider: FirIdeProvider, + element: KtNamedFunction, + originalFunction: FirSimpleFunction, + state: FirModuleResolveState + ): FirSimpleFunction { + val builtFunction = firIdeProvider.buildFunctionWithBody(element) + + // right now we can't resolve builtFunction header properly, as it built right in air, + // without file, which is now required for running stages other then body resolve, so we + // take original function header (which is resolved) and copy replacing body with body from builtFunction + return buildSimpleFunctionCopy(originalFunction) { + body = builtFunction.body + symbol = builtFunction.symbol as FirNamedFunctionSymbol + resolvePhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS) + source = builtFunction.source + session = state.firIdeSourcesSession + } + } + + + private fun buildPropertyCopyForCompletion( + firIdeProvider: FirIdeProvider, + element: KtProperty, + originalProperty: FirProperty, + state: FirModuleResolveState + ): FirProperty { + val builtProperty = firIdeProvider.buildPropertyWithBody(element) + + val originalSetter = originalProperty.setter + val builtSetter = builtProperty.setter + + // setter has a header with `value` parameter, and we want it type to be resolved + val copySetter = if (originalSetter != null && builtSetter != null) { + buildPropertyAccessorCopy(originalSetter) { + body = builtSetter.body + symbol = builtSetter.symbol + resolvePhase = minOf(builtSetter.resolvePhase, FirResolvePhase.DECLARATIONS) + source = builtSetter.source + session = state.firIdeSourcesSession + } + } else { + builtSetter + } + + return buildPropertyCopy(originalProperty) { symbol = builtProperty.symbol - // getter does not have parameters to resolve getter = builtProperty.getter - - val originalSetter = setter - val builtSetter = builtProperty.setter - if (originalSetter != null && builtSetter != null) { - setter = buildPropertyAccessorCopy(originalSetter) { - body = builtSetter.body - symbol = builtSetter.symbol - resolvePhase = minOf(builtSetter.resolvePhase, FirResolvePhase.DECLARATIONS) - source = builtSetter.source - session = state.firIdeSourcesSession - } - } + setter = copySetter resolvePhase = minOf(originalProperty.resolvePhase, FirResolvePhase.DECLARATIONS) source = builtProperty.source session = state.firIdeSourcesSession } - - val function = frankensteinProperty.apply { - state.lazyResolveDeclarationForCompletion(this, firFile, firIdeProvider, phase, contextCollector) - state.recordPsiToFirMappingsForCompletionFrom(this, firFile, element.containingKtFile) - } - - return FirCompletionContext( - function.session, - contextCollector, - state - ) } fun getDiagnosticsFor(element: KtElement, resolveState: FirModuleResolveState): Collection {