From 93a3c232926930941cc75e8fff9e1724b760d71a Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 22 Oct 2019 15:59:13 +0300 Subject: [PATCH] [FIR] Split `FirBodyResolveTransformer` to separate transformers --- .../jetbrains/kotlin/fir/FirCallResolver.kt | 17 +- .../kotlin/fir/FirQualifiedNameResolver.kt | 2 +- .../kotlin/fir/resolve/ResolveUtils.kt | 2 +- .../kotlin/fir/resolve/calls/Arguments.kt | 2 +- .../fir/resolve/calls/CandidateCollector.kt | 2 +- .../fir/resolve/dfa/FirDataFlowAnalyzer.kt | 6 +- .../dfa/cfg/ControlFlowGraphBuilder.kt | 2 +- .../fir/resolve/inference/FirCallCompleter.kt | 17 +- .../FirAbstractPhaseTransformer.kt | 2 +- .../transformers/FirBodyResolveTransformer.kt | 1098 ----------------- ...rCallCompletionResultsWriterTransformer.kt | 1 + .../transformers/FirSyntheticCallGenerator.kt | 6 +- .../resolve/transformers/ResolvePhaseUtils.kt | 2 + .../transformers/ReturnTypeCalculator.kt | 1 + .../body/resolve/BodyResolveUtils.kt | 62 + .../FirAbstractBodyResolveTransfromer.kt | 118 ++ .../body/resolve/FirBodyResolveTransformer.kt | 220 ++++ .../FirBodyResolveTransformerAdapters.kt | 98 ++ ...ControlFlowStatementsResolveTransformer.kt | 175 +++ .../FirDeclarationsResolveTransformer.kt | 421 +++++++ .../FirExpressionsResolveTransformer.kt | 352 ++++++ .../FirPartialBodyResolveTransformer.kt | 26 + .../kotlin/fir/types/ConeTypeContext.kt | 2 +- .../kotlin/idea/fir/FirResolutionApi.kt | 2 +- 24 files changed, 1513 insertions(+), 1123 deletions(-) delete mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransfromer.kt create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformerAdapters.kt create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirPartialBodyResolveTransformer.kt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt index 0aee8d653aa..afe95acefef 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -12,7 +12,8 @@ import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedQualifierImpl -import org.jetbrains.kotlin.fir.references.* +import org.jetbrains.kotlin.fir.references.FirNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference import org.jetbrains.kotlin.fir.references.impl.FirBackingFieldReferenceImpl import org.jetbrains.kotlin.fir.references.impl.FirErrorNamedReferenceImpl import org.jetbrains.kotlin.fir.references.impl.FirResolvedCallableReferenceImpl @@ -20,7 +21,11 @@ import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.ImplicitReceiverStack import org.jetbrains.kotlin.fir.resolve.calls.* -import org.jetbrains.kotlin.fir.resolve.transformers.* +import org.jetbrains.kotlin.fir.resolve.transformers.StoreNameReference +import org.jetbrains.kotlin.fir.resolve.transformers.StoreReceiver +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType +import org.jetbrains.kotlin.fir.resolve.transformers.phasedFir import org.jetbrains.kotlin.fir.resolve.typeForQualifier import org.jetbrains.kotlin.fir.resolve.typeFromCallee import org.jetbrains.kotlin.fir.scopes.FirScope @@ -32,12 +37,12 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator class FirCallResolver( - private val transformer: FirBodyResolveTransformer, + private val transformer: FirExpressionsResolveTransformer, topLevelScopes: List, localScopes: List, override val implicitReceiverStack: ImplicitReceiverStack, private val qualifiedResolver: FirQualifiedNameResolver -) : BodyResolveComponents by transformer { +) : BodyResolveComponents by transformer.components { private val towerResolver = FirTowerResolver( returnTypeCalculator, this, resolutionStageRunner, @@ -66,7 +71,7 @@ class FirCallResolver( typeArguments, session, file, - transformer.container + transformer.components.container ) { it.resultType } towerResolver.reset() @@ -155,7 +160,7 @@ class FirCallResolver( emptyList(), session, file, - transformer.container + transformer.components.container ) { it.resultType } towerResolver.reset() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirQualifiedNameResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirQualifiedNameResolver.kt index 3d6ceab5a24..915de8bb1c8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirQualifiedNameResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirQualifiedNameResolver.kt @@ -13,8 +13,8 @@ import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.transformers.PackageOrClass +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.transformers.resolveToPackageOrClass -import org.jetbrains.kotlin.fir.resolve.transformers.resultType import org.jetbrains.kotlin.fir.resolve.typeForQualifier import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index a201b24735a..69c4d503c94 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference import org.jetbrains.kotlin.fir.references.FirThisReference import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor -import org.jetbrains.kotlin.fir.resolve.transformers.resultType +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScopeProvider import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType import org.jetbrains.kotlin.fir.symbols.* diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index ec5d2820857..f8a59fba0d6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.expressions.* -import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.resolve.withNullability import org.jetbrains.kotlin.fir.returnExpressions import org.jetbrains.kotlin.fir.types.* diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt index de17d0ecb86..0344e6fc86b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateCollector.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents -import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.util.OperatorNameConventions diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt index dce2c9c39e5..ff8e367ff3b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.ImplicitReceiverStackImpl import org.jetbrains.kotlin.fir.resolve.dfa.Condition.* import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* -import org.jetbrains.kotlin.fir.resolve.transformers.FirBodyResolveTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol @@ -32,13 +32,13 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.safeAs -class FirDataFlowAnalyzer(transformer: FirBodyResolveTransformer) : BodyResolveComponents by transformer { +class FirDataFlowAnalyzer(components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents) : BodyResolveComponents by components { companion object { private val KOTLIN_BOOLEAN_NOT = CallableId(FqName("kotlin"), FqName("Boolean"), Name.identifier("not")) } private val context: DataFlowInferenceContext get() = inferenceComponents.ctx as DataFlowInferenceContext - private val receiverStack: ImplicitReceiverStackImpl = transformer.implicitReceiverStack + private val receiverStack: ImplicitReceiverStackImpl = components.implicitReceiverStack as ImplicitReceiverStackImpl private val graphBuilder = ControlFlowGraphBuilder() private val logicSystem: LogicSystem = LogicSystemImpl(context) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt index 837d4d11711..c034cebe54f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.dfa.* -import org.jetbrains.kotlin.fir.resolve.transformers.resultType +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.types.isNothing class ControlFlowGraphBuilder { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt index 42e61241e28..52f9574e5b4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/FirCallCompleter.kt @@ -14,8 +14,13 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor -import org.jetbrains.kotlin.fir.resolve.transformers.* +import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer import org.jetbrains.kotlin.fir.resolve.transformers.MapArguments +import org.jetbrains.kotlin.fir.resolve.transformers.StoreType +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.typeFromCallee import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype import org.jetbrains.kotlin.fir.returnExpressions @@ -29,16 +34,16 @@ import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.components.InferenceSession import org.jetbrains.kotlin.resolve.calls.inference.buildAbstractResultingSubstitutor -import org.jetbrains.kotlin.resolve.calls.inference.components.EmptySubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition import org.jetbrains.kotlin.types.model.StubTypeMarker import org.jetbrains.kotlin.types.model.TypeVariableMarker class FirCallCompleter( - private val transformer: FirBodyResolveTransformer -) : BodyResolveComponents by transformer { - private val completer = ConstraintSystemCompleter(inferenceComponents) + private val transformer: FirBodyResolveTransformer, + components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents +) : BodyResolveComponents by components { + private val completer = ConstraintSystemCompleter(components.inferenceComponents) fun completeCall(call: T, expectedTypeRef: FirTypeRef?): T where T : FirResolvable, T : FirStatement { @@ -127,7 +132,7 @@ class FirCallCompleter( ) replacements[lambdaArgument] = - newLambdaExpression.transformSingle(transformer, FirBodyResolveTransformer.LambdaResolution(expectedReturnTypeRef)) + newLambdaExpression.transformSingle(transformer, FirDeclarationsResolveTransformer.LambdaResolution(expectedReturnTypeRef)) return (newLambdaExpression.body?.returnExpressions() ?: emptyList()) to InferenceSession.default } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirAbstractPhaseTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirAbstractPhaseTransformer.kt index 953b2731cc9..eed625d4423 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirAbstractPhaseTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirAbstractPhaseTransformer.kt @@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer abstract class FirAbstractPhaseTransformer( - protected val transformerPhase: FirResolvePhase + val transformerPhase: FirResolvePhase ) : FirDefaultTransformer() { abstract val session: FirSession diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt deleted file mode 100644 index 2989e69a63d..00000000000 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt +++ /dev/null @@ -1,1098 +0,0 @@ -/* - * Copyright 2010-2019 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.fir.resolve.transformers - -import org.jetbrains.kotlin.contracts.description.InvocationKind -import org.jetbrains.kotlin.fir.* -import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor -import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl -import org.jetbrains.kotlin.fir.expressions.* -import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition -import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock -import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionWithSmartcastImpl -import org.jetbrains.kotlin.fir.references.* -import org.jetbrains.kotlin.fir.references.impl.FirExplicitThisReference -import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference -import org.jetbrains.kotlin.fir.resolve.* -import org.jetbrains.kotlin.fir.resolve.calls.* -import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowInferenceContext -import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer -import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter -import org.jetbrains.kotlin.fir.scopes.FirScope -import org.jetbrains.kotlin.fir.scopes.addImportingScopes -import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope -import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType -import org.jetbrains.kotlin.fir.symbols.* -import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol -import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.fir.types.impl.* -import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult -import org.jetbrains.kotlin.fir.visitors.FirTransformer -import org.jetbrains.kotlin.fir.visitors.compose -import org.jetbrains.kotlin.fir.visitors.transformSingle -import org.jetbrains.kotlin.ir.expressions.IrConstKind -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.model.KotlinTypeMarker -import org.jetbrains.kotlin.types.model.SimpleTypeMarker -import org.jetbrains.kotlin.types.model.TypeConstructorMarker -import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate -import org.jetbrains.kotlin.utils.addIfNotNull - -open class FirBodyResolveTransformer( - final override val session: FirSession, - phase: FirResolvePhase, - implicitTypeOnly: Boolean, - final override val scopeSession: ScopeSession = ScopeSession() -) : FirAbstractPhaseTransformer(phase), BodyResolveComponents { - var implicitTypeOnly: Boolean = implicitTypeOnly - private set - - final override val returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorWithJump(session, scopeSession) - final override val noExpectedType = FirImplicitTypeRefImpl(null) - private inline val builtinTypes: BuiltinTypes get() = session.builtinTypes - - final override val symbolProvider = session.firSymbolProvider - - private var packageFqName = FqName.ROOT - final override lateinit var file: FirFile - private set - - private var _container: FirDeclaration? = null - final override var container: FirDeclaration - get() = _container!! - private set(value) { - _container = value - } - - private val localScopes = mutableListOf() - private val topLevelScopes = mutableListOf() - final override val implicitReceiverStack: ImplicitReceiverStackImpl = ImplicitReceiverStackImpl() - final override val inferenceComponents = inferenceComponents(session, returnTypeCalculator, scopeSession) - final override val samResolver: FirSamResolver = FirSamResolverImpl(session, scopeSession) - - private var primaryConstructorParametersScope: FirLocalScope? = null - - private val callCompleter: FirCallCompleter = FirCallCompleter(this) - private val qualifiedResolver: FirQualifiedNameResolver = FirQualifiedNameResolver(this) - final override val resolutionStageRunner: ResolutionStageRunner = ResolutionStageRunner(inferenceComponents) - private val callResolver: FirCallResolver = FirCallResolver( - this, - topLevelScopes, - localScopes, - implicitReceiverStack, - qualifiedResolver - ) - - private val syntheticCallGenerator: FirSyntheticCallGenerator = FirSyntheticCallGenerator(this) - private val dataFlowAnalyzer: FirDataFlowAnalyzer = FirDataFlowAnalyzer(this) - private val whenExhaustivenessTransformer = FirWhenExhaustivenessTransformer(this) - - override val AbstractFirBasedSymbol.phasedFir: D where D : FirDeclaration, D : FirSymbolOwner - get() { - val requiredPhase = transformerPhase.prev - return phasedFir(session, requiredPhase) - } - - override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult { - packageFqName = file.packageFqName - this.file = file - return withScopeCleanup(topLevelScopes) { - topLevelScopes.addImportingScopes(file, session, scopeSession) - super.transformFile(file, data) as CompositeTransformResult - } - } - - override fun transformElement(element: E, data: Any?): CompositeTransformResult { - @Suppress("UNCHECKED_CAST") - return (element.transformChildren(this, data) as E).compose() - } - - override fun transformConstructor(constructor: FirConstructor, data: Any?): CompositeTransformResult { - if (implicitTypeOnly) return constructor.compose() - return transformFunction(constructor, data) as CompositeTransformResult - } - - override fun transformAnonymousInitializer( - anonymousInitializer: FirAnonymousInitializer, - data: Any? - ): CompositeTransformResult { - if (implicitTypeOnly) return anonymousInitializer.compose() - return withScopeCleanup(localScopes) { - dataFlowAnalyzer.enterInitBlock(anonymousInitializer) - localScopes.addIfNotNull(primaryConstructorParametersScope) - transformDeclaration(anonymousInitializer, data).also { - dataFlowAnalyzer.exitInitBlock(it.single as FirAnonymousInitializer) - } - } - } - - override fun transformTypeRef(typeRef: FirTypeRef, data: Any?): CompositeTransformResult { - return typeRef.compose() - } - - override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: Any?): CompositeTransformResult { - if (data == null) - return implicitTypeRef.compose() - require(data is FirTypeRef) - return data.compose() - } - - override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): CompositeTransformResult { - localScopes.lastOrNull()?.storeDeclaration(valueParameter) - if (valueParameter.returnTypeRef is FirImplicitTypeRef) { - valueParameter.replaceResolvePhase(transformerPhase) - return valueParameter.compose() // TODO - } - return (transformDeclaration(valueParameter, valueParameter.returnTypeRef).single as FirStatement).compose() - } - - override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult { - val oldConstructorScope = primaryConstructorParametersScope - primaryConstructorParametersScope = null - val type = regularClass.defaultType() - val result = withLabelAndReceiverType(regularClass.name, regularClass, type) { - val constructor = regularClass.declarations.firstOrNull() as? FirConstructor - if (constructor?.isPrimary == true) { - primaryConstructorParametersScope = FirLocalScope().apply { - constructor.valueParameters.forEach { this.storeDeclaration(it) } - } - } - transformDeclaration(regularClass, data) - } - primaryConstructorParametersScope = oldConstructorScope - return result as CompositeTransformResult - } - - override fun transformTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Any?): CompositeTransformResult { - val symbolProvider = session.firSymbolProvider - val resolved = transformExpression(typeOperatorCall, data).single - when ((resolved as FirTypeOperatorCall).operation) { - FirOperation.IS, FirOperation.NOT_IS -> { - resolved.resultType = FirResolvedTypeRefImpl( - null, - StandardClassIds.Boolean(symbolProvider).constructType(emptyArray(), isNullable = false) - ) - } - FirOperation.AS -> { - resolved.resultType = resolved.conversionTypeRef - } - FirOperation.SAFE_AS -> { - resolved.resultType = - resolved.conversionTypeRef.withReplacedConeType( - resolved.conversionTypeRef.coneTypeUnsafe().withNullability(ConeNullability.NULLABLE) - ) - } - else -> error("Unknown type operator") - } - dataFlowAnalyzer.exitTypeOperatorCall(typeOperatorCall) - return resolved.compose() - } - - override fun transformQualifiedAccessExpression( - qualifiedAccessExpression: FirQualifiedAccessExpression, - data: Any? - ): CompositeTransformResult { - - var result = when (val callee = qualifiedAccessExpression.calleeReference) { - is FirExplicitThisReference -> { - val labelName = callee.labelName - val implicitReceiver = implicitReceiverStack[labelName] - implicitReceiver?.boundSymbol?.let { - callee.replaceBoundSymbol(it) - } - qualifiedAccessExpression.resultType = FirResolvedTypeRefImpl( - null, implicitReceiver?.type ?: ConeKotlinErrorType("Unresolved this@$labelName") - ) - qualifiedAccessExpression - } - is FirSuperReference -> { - if (callee.superTypeRef is FirResolvedTypeRef) { - qualifiedAccessExpression.resultType = callee.superTypeRef - } else { - val superTypeRef = implicitReceiverStack.lastDispatchReceiver() - ?.boundSymbol?.phasedFir?.superTypeRefs?.firstOrNull() - ?: FirErrorTypeRefImpl(qualifiedAccessExpression.psi, "No super type") - qualifiedAccessExpression.resultType = superTypeRef - callee.replaceSuperTypeRef(superTypeRef) - } - qualifiedAccessExpression - } - is FirDelegateFieldReference -> { - val delegateFieldSymbol = callee.resolvedSymbol - qualifiedAccessExpression.resultType = delegateFieldSymbol.delegate.typeRef - qualifiedAccessExpression - } - is FirResolvedCallableReference -> { - if (qualifiedAccessExpression.typeRef !is FirResolvedTypeRef) { - storeTypeFromCallee(qualifiedAccessExpression) - } - qualifiedAccessExpression - } - else -> { - val transformedCallee = callResolver.resolveVariableAccessAndSelectCandidate(qualifiedAccessExpression, file) - // NB: here we can get raw expression because of dropped qualifiers (see transform callee), - // so candidate existence must be checked before calling completion - if (transformedCallee is FirQualifiedAccessExpression && transformedCallee.candidate() != null) { - callCompleter.completeCall(transformedCallee, data as? FirTypeRef) - } else { - transformedCallee - } - } - } - if (result is FirQualifiedAccessExpression) { - result = transformQualifiedAccessUsingSmartcastInfo(result) - dataFlowAnalyzer.exitQualifiedAccessExpression(result) - } - return result.compose() - } - - override fun transformThisReceiverExpression( - thisReceiverExpression: FirThisReceiverExpression, - data: Any? - ): CompositeTransformResult { - return transformQualifiedAccessExpression(thisReceiverExpression, data) - } - - private fun transformQualifiedAccessUsingSmartcastInfo(qualifiedAccessExpression: FirQualifiedAccessExpression): FirQualifiedAccessExpression { - val typesFromSmartCast = dataFlowAnalyzer.getTypeUsingSmartcastInfo(qualifiedAccessExpression) ?: return qualifiedAccessExpression - val allTypes = typesFromSmartCast.toMutableList().also { - it += qualifiedAccessExpression.resultType.coneTypeUnsafe() - } - val intersectedType = ConeTypeIntersector.intersectTypes(inferenceComponents.ctx as ConeInferenceContext, allTypes) - // TODO: add check that intersectedType is not equal to original type - val intersectedTypeRef = FirResolvedTypeRefImpl(qualifiedAccessExpression.resultType.psi, intersectedType).apply { - annotations += qualifiedAccessExpression.resultType.annotations - } - return FirExpressionWithSmartcastImpl(qualifiedAccessExpression, intersectedTypeRef, typesFromSmartCast) - } - - override fun transformVariableAssignment( - variableAssignment: FirVariableAssignment, - data: Any? - ): CompositeTransformResult { - // val resolvedAssignment = transformCallee(variableAssignment) - val resolvedAssignment = callResolver.resolveVariableAccessAndSelectCandidate(variableAssignment, file) - val result = if (resolvedAssignment is FirVariableAssignment) { - val completeAssignment = callCompleter.completeCall(resolvedAssignment, noExpectedType) - val expectedType = typeFromCallee(completeAssignment) - completeAssignment.transformRValue(this, expectedType) - } else { - // This can happen in erroneous code only - resolvedAssignment - } - // TODO: maybe replace with FirAbstractAssignment for performance? - (result as? FirVariableAssignment)?.let { dataFlowAnalyzer.exitVariableAssignment(it) } - return result.compose() - } - - override fun transformAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: Any?): CompositeTransformResult { - return when (data) { - null -> { - anonymousFunction.compose() - } - is LambdaResolution -> { - transformAnonymousFunctionWithLambdaResolution(anonymousFunction, data).compose() - } - is FirTypeRef -> { - val resolvedLambdaAtom = (data as? FirResolvedTypeRef)?.let { - extractLambdaInfoFromFunctionalType( - it.type, it, anonymousFunction - ) - } - var af = anonymousFunction - val valueParameters = - if (resolvedLambdaAtom == null) af.valueParameters - else { - val singleParameterType = resolvedLambdaAtom.parameters.singleOrNull() - val itParam = when { - af.valueParameters.isEmpty() && singleParameterType != null -> { - val name = Name.identifier("it") - FirValueParameterImpl( - null, - session, - FirResolvedTypeRefImpl(null, singleParameterType), - name, - FirVariableSymbol(name), - defaultValue = null, - isCrossinline = false, - isNoinline = false, - isVararg = false - ) - } - else -> null - } - if (itParam != null) { - listOf(itParam) - } else { - af.valueParameters.mapIndexed { index, param -> - if (param.returnTypeRef is FirResolvedTypeRef) { - param - } else { - param.transformReturnTypeRef( - StoreType, - param.returnTypeRef.resolvedTypeFromPrototype( - resolvedLambdaAtom.parameters[index] - ) - ) - param - } - } - } - - } - val returnTypeRefFromResolvedAtom = resolvedLambdaAtom?.returnType?.let { af.returnTypeRef.resolvedTypeFromPrototype(it) } - af = af.copy( - receiverTypeRef = af.receiverTypeRef?.takeIf { it !is FirImplicitTypeRef } - ?: resolvedLambdaAtom?.receiver?.let { af.receiverTypeRef?.resolvedTypeFromPrototype(it) }, - valueParameters = valueParameters, - returnTypeRef = (af.returnTypeRef as? FirResolvedTypeRef) - ?: returnTypeRefFromResolvedAtom - ?: af.returnTypeRef - ) - af = af.transformValueParameters(ImplicitToErrorTypeTransformer, null) - val bodyExpectedType = returnTypeRefFromResolvedAtom ?: data - af = transformFunction(af, bodyExpectedType).single as FirAnonymousFunction - af = af.copy( - returnTypeRef = af.body?.resultType ?: FirErrorTypeRefImpl(af.psi, "No result type for lambda") - ) - af.replaceTypeRef(af.constructFunctionalTypeRef(session)) - af.compose() - } - else -> { - transformFunction(anonymousFunction, data).single.compose() - } - } - } - - private object ImplicitToErrorTypeTransformer : FirTransformer() { - override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { - return element.compose() - } - - override fun transformValueParameter(valueParameter: FirValueParameter, data: Nothing?): CompositeTransformResult { - if (valueParameter.returnTypeRef is FirImplicitTypeRef) { - valueParameter.transformReturnTypeRef( - StoreType, - valueParameter.returnTypeRef.resolvedTypeFromPrototype(ConeKotlinErrorType("No type for parameter")) - ) - } - return valueParameter.compose() - } - } - - private fun transformAnonymousFunctionWithLambdaResolution( - anonymousFunction: FirAnonymousFunction, lambdaResolution: LambdaResolution - ): FirAnonymousFunction { - val receiverTypeRef = anonymousFunction.receiverTypeRef - fun transform(): FirAnonymousFunction { - val expectedReturnType = - lambdaResolution.expectedReturnTypeRef ?: anonymousFunction.returnTypeRef.takeUnless { it is FirImplicitTypeRef } - val result = transformFunction(anonymousFunction, expectedReturnType).single as FirAnonymousFunction - val body = result.body - return if (result.returnTypeRef is FirImplicitTypeRef && body != null) { - result.transformReturnTypeRef(this, body.resultType) - result - } else { - result - } - } - - val label = anonymousFunction.label - return if (label != null && receiverTypeRef != null) { - withLabelAndReceiverType(Name.identifier(label.name), anonymousFunction, receiverTypeRef.coneTypeUnsafe()) { - transform() - } - } else { - transform() - } - } - - data class LambdaResolution(val expectedReturnTypeRef: FirResolvedTypeRef?) - - - override fun transformCatch(catch: FirCatch, data: Any?): CompositeTransformResult { - dataFlowAnalyzer.enterCatchClause(catch) - return withScopeCleanup(localScopes) { - localScopes += FirLocalScope() - catch.transformParameter(this, noExpectedType) - catch.transformBlock(this, null) - }.also { dataFlowAnalyzer.exitCatchClause(it) }.compose() - } - - override fun transformTryExpression(tryExpression: FirTryExpression, data: Any?): CompositeTransformResult { - if (tryExpression.calleeReference is FirResolvedCallableReference && tryExpression.resultType !is FirImplicitTypeRef) { - return tryExpression.compose() - } - - dataFlowAnalyzer.enterTryExpression(tryExpression) - tryExpression.transformTryBlock(this, null) - dataFlowAnalyzer.exitTryMainBlock(tryExpression) - tryExpression.transformCatches(this, null) - - @Suppress("NAME_SHADOWING") - var result = syntheticCallGenerator.generateCalleeForTryExpression(tryExpression)?.let { - val expectedTypeRef = data as FirTypeRef? - callCompleter.completeCall(it, expectedTypeRef) - } ?: run { - tryExpression.resultType = FirErrorTypeRefImpl(null, "") - tryExpression - } - - result = if (result.finallyBlock != null) { - result.also(dataFlowAnalyzer::enterFinallyBlock) - .transformFinallyBlock(this, noExpectedType) - .also(dataFlowAnalyzer::exitFinallyBlock) - } else { - result - } - dataFlowAnalyzer.exitTryExpression(result) - return result.compose() - } - - override fun transformFunctionCall(functionCall: FirFunctionCall, data: Any?): CompositeTransformResult { - dataFlowAnalyzer.enterFunctionCall(functionCall) - if (functionCall.calleeReference is FirResolvedCallableReference && functionCall.resultType is FirImplicitTypeRef) { - storeTypeFromCallee(functionCall) - } - if (functionCall.calleeReference !is FirSimpleNamedReference) return functionCall.compose() - functionCall.transform(InvocationKindTransformer, null) - val expectedTypeRef = data as FirTypeRef? - val completeInference = - try { - val initialExplicitReceiver = functionCall.explicitReceiver - val resultExpression = callResolver.resolveCallAndSelectCandidate(functionCall, expectedTypeRef, file) - val resultExplicitReceiver = resultExpression.explicitReceiver - if (initialExplicitReceiver !== resultExplicitReceiver && resultExplicitReceiver is FirQualifiedAccess) { - // name.invoke() case - callCompleter.completeCall(resultExplicitReceiver, noExpectedType) - } - callCompleter.completeCall(resultExpression, expectedTypeRef) - } catch (e: Throwable) { - throw RuntimeException("While resolving call ${functionCall.render()}", e) - } - - dataFlowAnalyzer.exitFunctionCall(completeInference) - return completeInference.compose() - - } - - // override fun transformNamedReference(namedReference: FirNamedReference, data: Any?): CompositeTransformResult { -// if (namedReference is FirErrorNamedReference || namedReference is FirResolvedCallableReference) return namedReference.compose() -// val referents = data as? List ?: return namedReference.compose() -// return createResolvedNamedReference(namedReference, referents).compose() -// } - - - override fun transformBlock(block: FirBlock, data: Any?): CompositeTransformResult { - dataFlowAnalyzer.enterBlock(block) - @Suppress("NAME_SHADOWING") - val block = block.transformChildren(this, data) as FirBlock - val statement = block.statements.lastOrNull() - - val resultExpression = when (statement) { - is FirReturnExpression -> statement.result - is FirExpression -> statement - else -> null - } - block.resultType = if (resultExpression == null) { - FirImplicitUnitTypeRef(block.psi) - } else { - (resultExpression.resultType as? FirResolvedTypeRef) ?: FirErrorTypeRefImpl(null, "No type for block") - } - dataFlowAnalyzer.exitBlock(block) - return block.compose() - } - - override fun transformJump(jump: FirJump, data: Any?): CompositeTransformResult { - val result = transformExpression(jump, data) - dataFlowAnalyzer.exitJump(jump) - return result - } - - override fun transformThrowExpression(throwExpression: FirThrowExpression, data: Any?): CompositeTransformResult { - return transformExpression(throwExpression, data).also { - dataFlowAnalyzer.exitThrowExceptionNode(it.single as FirThrowExpression) - } - } - - override fun transformWhenExpression(whenExpression: FirWhenExpression, data: Any?): CompositeTransformResult { - if (whenExpression.calleeReference is FirResolvedCallableReference && whenExpression.resultType !is FirImplicitTypeRef) { - return whenExpression.compose() - } - dataFlowAnalyzer.enterWhenExpression(whenExpression) - return withScopeCleanup(localScopes) with@{ - if (whenExpression.subjectVariable != null) { - localScopes += FirLocalScope() - } - @Suppress("NAME_SHADOWING") - var whenExpression = whenExpression.transformSubject(this, noExpectedType) - - when { - whenExpression.branches.isEmpty() -> {} - whenExpression.isOneBranch() -> { - whenExpression = whenExpression.transformBranches(this, noExpectedType) - whenExpression.resultType = whenExpression.branches.first().result.resultType - } - else -> { - whenExpression = whenExpression.transformBranches(this, null) - - whenExpression = syntheticCallGenerator.generateCalleeForWhenExpression(whenExpression) ?: run { - dataFlowAnalyzer.exitWhenExpression(whenExpression) - whenExpression.resultType = FirErrorTypeRefImpl(null, "") - return@with whenExpression.compose() - } - - val expectedTypeRef = data as FirTypeRef? - whenExpression = callCompleter.completeCall(whenExpression, expectedTypeRef) - } - } - whenExpression = whenExpression.transformSingle(whenExhaustivenessTransformer, null) - dataFlowAnalyzer.exitWhenExpression(whenExpression) - whenExpression = whenExpression.replaceReturnTypeIfNotExhaustive() - whenExpression.compose() - } - } - - private fun FirWhenExpression.replaceReturnTypeIfNotExhaustive(): FirWhenExpression { - if (!isExhaustive) { - resultType = resultType.resolvedTypeFromPrototype(session.builtinTypes.unitType.type) - } - return this - } - - private fun FirWhenExpression.isOneBranch(): Boolean { - if (branches.size == 1) return true - if (branches.size > 2) return false - val lastBranch = branches.last() - return lastBranch.condition is FirElseIfTrueCondition && lastBranch.result is FirEmptyExpressionBlock - } - - override fun transformWhenBranch(whenBranch: FirWhenBranch, data: Any?): CompositeTransformResult { - return whenBranch.also { dataFlowAnalyzer.enterWhenBranchCondition(whenBranch) } - .transformCondition(this, data).also { dataFlowAnalyzer.exitWhenBranchCondition(it) } - .transformResult(this, data).also { dataFlowAnalyzer.exitWhenBranchResult(it) } - .compose() - } - - override fun transformWhenSubjectExpression( - whenSubjectExpression: FirWhenSubjectExpression, - data: Any? - ): CompositeTransformResult { - val parentWhen = whenSubjectExpression.whenSubject.whenExpression - val subjectType = parentWhen.subject?.resultType ?: parentWhen.subjectVariable?.returnTypeRef - if (subjectType != null) { - whenSubjectExpression.resultType = subjectType - } - return whenSubjectExpression.compose() - } - - override fun transformConstExpression(constExpression: FirConstExpression, data: Any?): CompositeTransformResult { - val expectedType = data as FirTypeRef? - - val kind = constExpression.kind - if (expectedType == null || expectedType is FirImplicitTypeRef || - kind == IrConstKind.Null || kind == IrConstKind.Boolean || kind == IrConstKind.Char - ) { - val symbol = when (kind) { - IrConstKind.Null -> StandardClassIds.Nothing(symbolProvider) - IrConstKind.Boolean -> StandardClassIds.Boolean(symbolProvider) - IrConstKind.Char -> StandardClassIds.Char(symbolProvider) - IrConstKind.Byte -> StandardClassIds.Byte(symbolProvider) - IrConstKind.Short -> StandardClassIds.Short(symbolProvider) - IrConstKind.Int -> StandardClassIds.Int(symbolProvider) - IrConstKind.Long -> StandardClassIds.Long(symbolProvider) - IrConstKind.String -> StandardClassIds.String(symbolProvider) - IrConstKind.Float -> StandardClassIds.Float(symbolProvider) - IrConstKind.Double -> StandardClassIds.Double(symbolProvider) - } - - val type = ConeClassTypeImpl(symbol.toLookupTag(), emptyArray(), isNullable = kind == IrConstKind.Null) - - constExpression.resultType = FirResolvedTypeRefImpl(null, type) - } else { - constExpression.resultType = if (kind != IrConstKind.Null) { - expectedType.resolvedTypeFromPrototype( - expectedType.coneTypeUnsafe().withNullability(ConeNullability.NOT_NULL) - ) - } else { - expectedType - } - } - - - return transformExpression(constExpression, data).also { - dataFlowAnalyzer.exitConstExpresion(it.single as FirConstExpression<*>) - } - } - - override fun transformDeclaration(declaration: FirDeclaration, data: Any?): CompositeTransformResult { - return withContainer(declaration) { - super.transformDeclaration(declaration, data) - } - } - - override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: Any?): CompositeTransformResult { - dataFlowAnalyzer.enterAnnotationCall(annotationCall) - return (annotationCall.transformChildren(this, data) as FirAnnotationCall).also { - dataFlowAnalyzer.exitAnnotationCall(it) - }.compose() - } - - override fun > transformFunction(function: FirFunction, data: Any?): CompositeTransformResult { - return withScopeCleanup(localScopes) { - localScopes += FirLocalScope() - dataFlowAnalyzer.enterFunction(function) - transformDeclaration(function, data).also { - val result = it.single as FirFunction<*> - dataFlowAnalyzer.exitFunction(result)?.let { controlFlowGraph -> - result.transformControlFlowGraphReference(ControlFlowGraphReferenceTransformer, controlFlowGraph) - } - } as CompositeTransformResult - } - } - - private fun transformFunctionWithGivenSignature( - function: FirFunction<*>, - returnTypeRef: FirTypeRef, - receiverTypeRef: FirTypeRef? = null - ): CompositeTransformResult { - if (function is FirSimpleFunction) { - localScopes.lastOrNull()?.storeDeclaration(function) - } - val result = transformFunction(function, returnTypeRef).single as FirFunction<*> - val body = result.body - return if (result.returnTypeRef is FirImplicitTypeRef && body != null) { - result.transformReturnTypeRef(this, body.resultType) - result - } else { - result - }.compose() - } - - override fun transformSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): CompositeTransformResult { - val returnTypeRef = simpleFunction.returnTypeRef - if ((returnTypeRef !is FirImplicitTypeRef) && implicitTypeOnly) { - return simpleFunction.compose() - } - return withFullBodyResolve { - if (returnTypeRef is FirImplicitTypeRef) { - simpleFunction.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef) - } - - val receiverTypeRef = simpleFunction.receiverTypeRef - if (receiverTypeRef != null) { - withLabelAndReceiverType(simpleFunction.name, simpleFunction, receiverTypeRef.coneTypeUnsafe()) { - transformFunctionWithGivenSignature(simpleFunction, returnTypeRef, receiverTypeRef) - } - } else { - transformFunctionWithGivenSignature(simpleFunction, returnTypeRef) - } - } - } - - private fun transformAccessor( - accessor: FirPropertyAccessor, - enhancedTypeRef: FirTypeRef, - owner: FirVariable<*> - ) { - if (accessor is FirDefaultPropertyAccessor || accessor.body == null) { - transformFunction(accessor, enhancedTypeRef) - } - val returnTypeRef = accessor.returnTypeRef - if (returnTypeRef is FirImplicitTypeRef && enhancedTypeRef !is FirResolvedTypeRef) { - accessor.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef) - } - val expectedReturnTypeRef = if (enhancedTypeRef is FirResolvedTypeRef && returnTypeRef !is FirResolvedTypeRef) { - enhancedTypeRef - } else { - returnTypeRef - } - val receiverTypeRef = owner.receiverTypeRef - if (receiverTypeRef != null) { - withLabelAndReceiverType(owner.name, owner, receiverTypeRef.coneTypeUnsafe()) { - transformFunctionWithGivenSignature(accessor, expectedReturnTypeRef, receiverTypeRef) - } - } else { - transformFunctionWithGivenSignature(accessor, expectedReturnTypeRef) - } as CompositeTransformResult - } - - private fun storeVariableReturnType(variable: FirVariable<*>) { - val initializer = variable.initializer - if (variable.returnTypeRef is FirImplicitTypeRef) { - when { - initializer != null -> { - variable.transformReturnTypeRef( - this, - when (val resultType = initializer.resultType) { - is FirImplicitTypeRef -> FirErrorTypeRefImpl( - null, - "No result type for initializer" - ) - else -> resultType - } - ) - } - variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> { - variable.transformReturnTypeRef( - this, - when (val resultType = variable.getter?.returnTypeRef) { - is FirImplicitTypeRef -> FirErrorTypeRefImpl( - null, - "No result type for getter" - ) - else -> resultType - } - ) - } - else -> { - variable.transformReturnTypeRef( - this, FirErrorTypeRefImpl(null, "Cannot infer variable type without initializer / getter / delegate") - ) - } - } - if (variable.getter?.returnTypeRef is FirImplicitTypeRef) { - variable.getter?.transformReturnTypeRef(this, variable.returnTypeRef) - } - } - } - - private fun FirProperty.transformChildrenWithoutAccessors(returnTypeRef: FirTypeRef): FirProperty { - return transformReturnTypeRef(this@FirBodyResolveTransformer, returnTypeRef). - transformOtherChildren(this@FirBodyResolveTransformer, returnTypeRef) - } - - private fun > FirVariable.transformAccessors() { - var enhancedTypeRef = returnTypeRef - getter?.let { - transformAccessor(it, enhancedTypeRef, this) - } - if (returnTypeRef is FirImplicitTypeRef) { - storeVariableReturnType(this) - enhancedTypeRef = returnTypeRef - } - setter?.let { - it.valueParameters[0].transformReturnTypeRef(StoreType, enhancedTypeRef) - transformAccessor(it, enhancedTypeRef, this) - } - } - - override fun transformWrappedDelegateExpression( - wrappedDelegateExpression: FirWrappedDelegateExpression, - data: Any? - ): CompositeTransformResult { - transformExpression(wrappedDelegateExpression, data) - with(wrappedDelegateExpression) { - val delegateProviderTypeRef = delegateProvider.typeRef - val useDelegateProvider = delegateProviderTypeRef is FirResolvedTypeRef && - delegateProviderTypeRef !is FirErrorTypeRef && - delegateProviderTypeRef.type !is ConeKotlinErrorType - return if (useDelegateProvider) delegateProvider.compose() else expression.compose() - } - } - - private fun transformLocalVariable(variable: FirProperty, data: Any?): CompositeTransformResult { - assert(variable.isLocal) - variable.transformOtherChildren(this, variable.returnTypeRef) - if (variable.initializer != null) { - storeVariableReturnType(variable) - } - variable.transformAccessors() - localScopes.lastOrNull()?.storeDeclaration(variable) - variable.replaceResolvePhase(transformerPhase) - dataFlowAnalyzer.exitVariableDeclaration(variable) - return variable.compose() - } - - override fun transformProperty(property: FirProperty, data: Any?): CompositeTransformResult { - if (property.isLocal) return transformLocalVariable(property, data) - val returnTypeRef = property.returnTypeRef - if (returnTypeRef !is FirImplicitTypeRef && implicitTypeOnly) return property.compose() - if (property.resolvePhase == transformerPhase) return property.compose() - dataFlowAnalyzer.enterProperty(property) - if (returnTypeRef is FirImplicitTypeRef) { - property.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef) - } - return withFullBodyResolve { - withScopeCleanup(localScopes) { - localScopes.addIfNotNull(primaryConstructorParametersScope) - withContainer(property) { - property.transformChildrenWithoutAccessors(returnTypeRef) - if (property.initializer != null) { - storeVariableReturnType(property) - } - withScopeCleanup(localScopes) { - localScopes.add(FirLocalScope().apply { - storeBackingField(property) - }) - property.transformAccessors() - } - } - property.replaceResolvePhase(transformerPhase) - val controlFlowGraph = dataFlowAnalyzer.exitProperty(property) - property.transformControlFlowGraphReference(ControlFlowGraphReferenceTransformer, controlFlowGraph) - property.compose() - } - } - } - - override fun transformExpression(expression: FirExpression, data: Any?): CompositeTransformResult { - if (expression.resultType is FirImplicitTypeRef && expression !is FirWrappedExpression) { - val type = FirErrorTypeRefImpl(expression.psi, "Type calculating for ${expression::class} is not supported") - expression.resultType = type - } - return (expression.transformChildren(this, data) as FirStatement).compose() - } - - override fun transformGetClassCall(getClassCall: FirGetClassCall, data: Any?): CompositeTransformResult { - val transformedGetClassCall = transformExpression(getClassCall, data).single as FirGetClassCall - val kClassSymbol = ClassId.fromString("kotlin/reflect/KClass")(session.firSymbolProvider) - - val typeOfExpression = when (val lhs = transformedGetClassCall.argument) { - is FirResolvedQualifier -> { - val classId = lhs.classId - if (classId != null) { - val symbol = symbolProvider.getClassLikeSymbolByFqName(classId)!! - // TODO: Unify logic? - symbol.constructType( - Array(symbol.phasedFir.typeParameters.size) { - ConeStarProjection - }, - isNullable = false - ) - } else { - lhs.resultType.coneTypeUnsafe() - } - } - else -> lhs.resultType.coneTypeUnsafe() - } - - transformedGetClassCall.resultType = - FirResolvedTypeRefImpl( - null, - kClassSymbol.constructType(arrayOf(typeOfExpression), false) - ) - return transformedGetClassCall.compose() - } - - override fun transformBinaryLogicExpression( - binaryLogicExpression: FirBinaryLogicExpression, - data: Any? - ): CompositeTransformResult { - val booleanType = builtinTypes.booleanType - return when (binaryLogicExpression.kind) { - LogicOperationKind.AND -> - binaryLogicExpression.also(dataFlowAnalyzer::enterBinaryAnd) - .transformLeftOperand(this, booleanType).also(dataFlowAnalyzer::exitLeftBinaryAndArgument) - .transformRightOperand(this, booleanType).also(dataFlowAnalyzer::exitBinaryAnd) - - LogicOperationKind.OR -> - binaryLogicExpression.also(dataFlowAnalyzer::enterBinaryOr) - .transformLeftOperand(this, booleanType).also(dataFlowAnalyzer::exitLeftBinaryOrArgument) - .transformRightOperand(this, booleanType).also(dataFlowAnalyzer::exitBinaryOr) - }.transformOtherChildren(this, booleanType).also { - it.resultType = booleanType - }.compose() - } - - override fun transformOperatorCall(operatorCall: FirOperatorCall, data: Any?): CompositeTransformResult { - val result = if (operatorCall.operation in FirOperation.BOOLEANS) { - (operatorCall.transformChildren(this, noExpectedType) as FirOperatorCall).also { - it.resultType = builtinTypes.booleanType - } - } else { - transformExpression(operatorCall, data).single - } as FirOperatorCall - dataFlowAnalyzer.exitOperatorCall(result) - return result.compose() - } - - override fun transformWhileLoop(whileLoop: FirWhileLoop, data: Any?): CompositeTransformResult { - return whileLoop.also(dataFlowAnalyzer::enterWhileLoop) - .transformCondition(this, data).also(dataFlowAnalyzer::exitWhileLoopCondition) - .transformBlock(this, data).also(dataFlowAnalyzer::exitWhileLoop) - .transformOtherChildren(this, data).compose() - } - - override fun transformDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: Any?): CompositeTransformResult { - return doWhileLoop.also(dataFlowAnalyzer::enterDoWhileLoop) - .transformBlock(this, data).also(dataFlowAnalyzer::enterDoWhileLoopCondition) - .transformCondition(this, data).also(dataFlowAnalyzer::exitDoWhileLoop) - .transformOtherChildren(this, data).compose() - } - - // ----------------------- Util functions ----------------------- - - private inline fun withLabelAndReceiverType( - labelName: Name, - owner: FirDeclaration, - type: ConeKotlinType, - block: () -> T - ): T { - val implicitReceiverValue = when (owner) { - is FirRegularClass -> { - ImplicitDispatchReceiverValue(owner.symbol, type, symbolProvider, session, scopeSession) - } - is FirFunction<*> -> { - ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) - } - is FirVariable<*> -> { - ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) - } - else -> { - throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}") - } - } - implicitReceiverStack.add(labelName, implicitReceiverValue) - val result = block() - implicitReceiverStack.pop(labelName) - return result - } - - protected inline fun withScopeCleanup(scopes: MutableList<*>, crossinline l: () -> T): T { - val sizeBefore = scopes.size - return try { - l() - } finally { - val size = scopes.size - assert(size >= sizeBefore) - repeat(size - sizeBefore) { - scopes.let { it.removeAt(it.size - 1) } - } - } - } - - private inline fun withFullBodyResolve(crossinline l: () -> T): T { - if (!implicitTypeOnly) return l() - implicitTypeOnly = false - return try { - l() - } finally { - implicitTypeOnly = true - } - } - - internal fun storeTypeFromCallee(access: T) where T : FirQualifiedAccess, T : FirExpression { - access.resultType = callCompleter.typeFromCallee(access) - } - - private fun withContainer(declaration: FirDeclaration, f: () -> T): T { - val prevContainer = _container - _container = declaration - val result = f() - _container = prevContainer - return result - } - - fun FirElement.visitNoTransform(transformer: FirTransformer, data: D) { - val result = this.transform(transformer, data) - require(result.single === this) { "become ${result.single}: `${result.single.render()}`, was ${this}: `${this.render()}`" } - } -} - -private fun inferenceComponents(session: FirSession, returnTypeCalculator: ReturnTypeCalculator, scopeSession: ScopeSession) = - InferenceComponents(object : ConeInferenceContext, TypeSystemInferenceExtensionContextDelegate, DataFlowInferenceContext { - override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List): SimpleTypeMarker? { - // TODO: implement - return null - } - - override fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker { - TODO("not implemented") - } - - override val session: FirSession - get() = session - - override fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker { - return this - } - - override fun TypeConstructorMarker.toErrorType(): SimpleTypeMarker { - require(this is ErrorTypeConstructor) - return ConeClassErrorType(reason) - } - }, session, returnTypeCalculator, scopeSession) - - -class FirDesignatedBodyResolveTransformer( - private val designation: Iterator, - session: FirSession, - scopeSession: ScopeSession = ScopeSession(), - implicitTypeOnly: Boolean = true -) : FirBodyResolveTransformer( - session, - phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, - implicitTypeOnly = implicitTypeOnly, - scopeSession = scopeSession -) { - override fun transformElement(element: E, data: Any?): CompositeTransformResult { - if (designation.hasNext()) { - designation.next().visitNoTransform(this, data) - return element.compose() - } - return super.transformElement(element, data) - } -} - - -@Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")")) -class FirImplicitTypeBodyResolveTransformerAdapter : FirTransformer() { - private val scopeSession = ScopeSession() - - override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { - return element.compose() - } - - override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { - val transformer = FirBodyResolveTransformer( - file.session, - phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, - implicitTypeOnly = true, - scopeSession = scopeSession - ) - return file.transform(transformer, null) - } -} - - -@Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")")) -class FirBodyResolveTransformerAdapter : FirTransformer() { - private val scopeSession = ScopeSession() - - override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { - return element.compose() - } - - override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { - // Despite of real phase is EXPRESSIONS, we state IMPLICIT_TYPES here, because DECLARATIONS previous phase is OK for us - val transformer = FirBodyResolveTransformer( - file.session, - phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, - implicitTypeOnly = false, - scopeSession = scopeSession - ) - return file.transform(transformer, null) - } -} - - -inline fun FirBasedSymbol<*>.firUnsafe(): T { - val fir = this.fir - require(fir is T) { - "Not an expected fir element type = ${T::class}, symbol = ${this}, fir = ${fir.renderWithType()}" - } - return fir -} - -internal inline var FirExpression.resultType: FirTypeRef - get() = typeRef - set(type) { - replaceTypeRef(type) - } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index a5ef4558c27..41040b52c5c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.candidate import org.jetbrains.kotlin.fir.resolve.constructFunctionalTypeRef import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.substituteOrNull +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.withNullability import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType import org.jetbrains.kotlin.fir.types.* diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt index 60d690eedb0..615a5a57daf 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSyntheticCallGenerator.kt @@ -20,6 +20,8 @@ import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.references.impl.FirStubReference import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.calls.* +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.SyntheticCallableId import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol @@ -33,7 +35,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.types.Variance -class FirSyntheticCallGenerator(private val transformer: FirBodyResolveTransformer) : BodyResolveComponents by transformer { +class FirSyntheticCallGenerator(private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents) : BodyResolveComponents by components { private val whenSelectFunction: FirSimpleFunctionImpl = generateSyntheticSelectFunction(SyntheticCallableId.WHEN) private val trySelectFunction: FirSimpleFunctionImpl = generateSyntheticSelectFunction(SyntheticCallableId.TRY) @@ -91,7 +93,7 @@ class FirSyntheticCallGenerator(private val transformer: FirBodyResolveTransform } private fun generateCandidate(callInfo: CallInfo, function: FirSimpleFunctionImpl): Candidate = - CandidateFactory(transformer, callInfo).createCandidate( + CandidateFactory(components, callInfo).createCandidate( symbol = function.symbol, dispatchReceiverValue = null, implicitExtensionReceiverValue = null, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt index 812ba867917..0a4657854a9 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt @@ -7,6 +7,8 @@ package org.jetbrains.kotlin.fir.resolve.transformers import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase.* +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformerAdapter +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitTypeBodyResolveTransformerAdapter import org.jetbrains.kotlin.fir.visitors.FirTransformer // TODO: add FirSession parameter diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculator.kt index e4efc854d6a..a75cc44e388 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculator.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ReturnTypeCalculator.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.firProvider +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDesignatedBodyResolveTransformer import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt new file mode 100644 index 00000000000..4b1a08e7e87 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2019 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.fir.resolve.transformers.body.resolve + +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.renderWithType +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.calls.ConeInferenceContext +import org.jetbrains.kotlin.fir.resolve.calls.InferenceComponents +import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowInferenceContext +import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.types.ConeClassErrorType +import org.jetbrains.kotlin.fir.types.ErrorTypeConstructor +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.SimpleTypeMarker +import org.jetbrains.kotlin.types.model.TypeConstructorMarker +import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate + +inline fun FirBasedSymbol<*>.firUnsafe(): T { + val fir = this.fir + require(fir is T) { + "Not an expected fir element type = ${T::class}, symbol = ${this}, fir = ${fir.renderWithType()}" + } + return fir +} + +internal inline var FirExpression.resultType: FirTypeRef + get() = typeRef + set(type) { + replaceTypeRef(type) + } + +internal fun inferenceComponents(session: FirSession, returnTypeCalculator: ReturnTypeCalculator, scopeSession: ScopeSession) = + InferenceComponents(object : ConeInferenceContext, TypeSystemInferenceExtensionContextDelegate, DataFlowInferenceContext { + override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List): SimpleTypeMarker? { + // TODO: implement + return null + } + + override fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker { + TODO("not implemented") + } + + override val session: FirSession + get() = session + + override fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker { + return this + } + + override fun TypeConstructorMarker.toErrorType(): SimpleTypeMarker { + require(this is ErrorTypeConstructor) + return ConeClassErrorType(reason) + } + }, session, returnTypeCalculator, scopeSession) \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransfromer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransfromer.kt new file mode 100644 index 00000000000..502b8339066 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirAbstractBodyResolveTransfromer.kt @@ -0,0 +1,118 @@ +/* + * Copyright 2010-2019 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.fir.resolve.transformers.body.resolve + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirSymbolOwner +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.resolve.* +import org.jetbrains.kotlin.fir.resolve.calls.InferenceComponents +import org.jetbrains.kotlin.fir.resolve.calls.ResolutionStageRunner +import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer +import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter +import org.jetbrains.kotlin.fir.resolve.transformers.* +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl + +abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAbstractPhaseTransformer(phase) { + abstract val components: BodyResolveTransformerComponents + + abstract var implicitTypeOnly: Boolean + internal set + + final override val session: FirSession get() = components.session + + final override val AbstractFirBasedSymbol.phasedFir: D where D : FirDeclaration, D : FirSymbolOwner + get() { + val requiredPhase = transformerPhase.prev + return phasedFir(session, requiredPhase) + } + + protected inline fun withScopeCleanup(scopes: MutableList<*>, crossinline l: () -> T): T { + val sizeBefore = scopes.size + return try { + l() + } finally { + val size = scopes.size + assert(size >= sizeBefore) + repeat(size - sizeBefore) { + scopes.let { it.removeAt(it.size - 1) } + } + } + } + + internal inline fun withFullBodyResolve(crossinline l: () -> T): T { + if (!implicitTypeOnly) return l() + implicitTypeOnly = false + return try { + l() + } finally { + implicitTypeOnly = true + } + } + + protected inline val topLevelScopes: MutableList get() = components.topLevelScopes + protected inline val localScopes: MutableList get() = components.localScopes + + protected inline val noExpectedType: FirTypeRef get() = components.noExpectedType + + protected inline val symbolProvider: FirSymbolProvider get() = components.symbolProvider + + protected inline val returnTypeCalculator: ReturnTypeCalculator get() = components.returnTypeCalculator + protected inline val implicitReceiverStack: ImplicitReceiverStack get() = components.implicitReceiverStack + protected inline val inferenceComponents: InferenceComponents get() = components.inferenceComponents + protected inline val resolutionStageRunner: ResolutionStageRunner get() = components.resolutionStageRunner + protected inline val samResolver: FirSamResolver get() = components.samResolver + protected inline val callCompleter: FirCallCompleter get() = components.callCompleter + protected inline val dataFlowAnalyzer: FirDataFlowAnalyzer get() = components.dataFlowAnalyzer + protected inline val scopeSession: ScopeSession get() = components.scopeSession + protected inline val file: FirFile get() = components.file + + class BodyResolveTransformerComponents( + override val session: FirSession, + override val scopeSession: ScopeSession, + val transformer: FirBodyResolveTransformer + ) : BodyResolveComponents { + val topLevelScopes: MutableList = mutableListOf() + val localScopes: MutableList = mutableListOf() + + override val noExpectedType: FirTypeRef = FirImplicitTypeRefImpl(null) + + override lateinit var file: FirFile + internal set + + override val symbolProvider: FirSymbolProvider = session.firSymbolProvider + + override val returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorWithJump(session, scopeSession) + override val implicitReceiverStack: ImplicitReceiverStack = ImplicitReceiverStackImpl() + override val inferenceComponents: InferenceComponents = inferenceComponents(session, returnTypeCalculator, scopeSession) + override val resolutionStageRunner: ResolutionStageRunner = ResolutionStageRunner(inferenceComponents) + override val samResolver: FirSamResolver = FirSamResolverImpl(session, scopeSession) + val callCompleter: FirCallCompleter = FirCallCompleter(transformer, this) + val dataFlowAnalyzer: FirDataFlowAnalyzer = FirDataFlowAnalyzer(this) + + internal var _container: FirDeclaration? = null + override var container: FirDeclaration + get() = _container!! + private set(value) { + _container = value + } + + internal inline fun withContainer(declaration: FirDeclaration, crossinline f: () -> T): T { + val prevContainer = _container + _container = declaration + val result = f() + _container = prevContainer + return result + } + } +} + diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt new file mode 100644 index 00000000000..a471334cfc8 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformer.kt @@ -0,0 +1,220 @@ +/* + * Copyright 2010-2019 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.fir.resolve.transformers.body.resolve + +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirTargetElement +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.render +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.scopes.addImportingScopes +import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.FirTransformer +import org.jetbrains.kotlin.fir.visitors.compose +import org.jetbrains.kotlin.name.FqName + +open class FirBodyResolveTransformer( + session: FirSession, + phase: FirResolvePhase, + override var implicitTypeOnly: Boolean, + scopeSession: ScopeSession +) : FirAbstractBodyResolveTransformer(phase) { + private var packageFqName = FqName.ROOT + + override val components: BodyResolveTransformerComponents = BodyResolveTransformerComponents(session, scopeSession, this) + + private val expressionsTransformer = FirExpressionsResolveTransformer(this) + private val declarationsTransformer = FirDeclarationsResolveTransformer(this) + private val controlFlowStatementsTransformer = FirControlFlowStatementsResolveTransformer(this) + + override fun transformFile(file: FirFile, data: Any?): CompositeTransformResult { + packageFqName = file.packageFqName + components.file = file + return withScopeCleanup(components.topLevelScopes) { + components.topLevelScopes.addImportingScopes(file, session, components.scopeSession) + @Suppress("UNCHECKED_CAST") + super.transformFile(file, data) as CompositeTransformResult + } + } + + override fun transformElement(element: E, data: Any?): CompositeTransformResult { + @Suppress("UNCHECKED_CAST") + return (element.transformChildren(this, data) as E).compose() + } + + override fun transformTypeRef(typeRef: FirTypeRef, data: Any?): CompositeTransformResult { + return typeRef.compose() + } + + override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: Any?): CompositeTransformResult { + if (data == null) + return implicitTypeRef.compose() + require(data is FirTypeRef) + return data.compose() + } + + // ------------------------------------- Expressions ------------------------------------- + + override fun transformExpression(expression: FirExpression, data: Any?): CompositeTransformResult { + return expressionsTransformer.transformExpression(expression, data) + } + + override fun transformQualifiedAccessExpression( + qualifiedAccessExpression: FirQualifiedAccessExpression, + data: Any? + ): CompositeTransformResult { + return expressionsTransformer.transformQualifiedAccessExpression(qualifiedAccessExpression, data) + } + + override fun transformFunctionCall(functionCall: FirFunctionCall, data: Any?): CompositeTransformResult { + return expressionsTransformer.transformFunctionCall(functionCall, data) + } + + override fun transformBlock(block: FirBlock, data: Any?): CompositeTransformResult { + return expressionsTransformer.transformBlock(block, data) + } + + override fun transformThisReceiverExpression( + thisReceiverExpression: FirThisReceiverExpression, + data: Any? + ): CompositeTransformResult { + return expressionsTransformer.transformThisReceiverExpression(thisReceiverExpression, data) + } + + override fun transformOperatorCall(operatorCall: FirOperatorCall, data: Any?): CompositeTransformResult { + return expressionsTransformer.transformOperatorCall(operatorCall, data) + } + + override fun transformTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Any?): CompositeTransformResult { + return expressionsTransformer.transformTypeOperatorCall(typeOperatorCall, data) + } + + override fun transformBinaryLogicExpression( + binaryLogicExpression: FirBinaryLogicExpression, + data: Any? + ): CompositeTransformResult { + return expressionsTransformer.transformBinaryLogicExpression(binaryLogicExpression, data) + } + + override fun transformVariableAssignment( + variableAssignment: FirVariableAssignment, + data: Any? + ): CompositeTransformResult { + return expressionsTransformer.transformVariableAssignment(variableAssignment, data) + } + + override fun transformGetClassCall(getClassCall: FirGetClassCall, data: Any?): CompositeTransformResult { + return expressionsTransformer.transformGetClassCall(getClassCall, data) + } + + override fun transformWrappedDelegateExpression( + wrappedDelegateExpression: FirWrappedDelegateExpression, + data: Any? + ): CompositeTransformResult { + return expressionsTransformer.transformWrappedDelegateExpression(wrappedDelegateExpression, data) + } + + override fun transformConstExpression(constExpression: FirConstExpression, data: Any?): CompositeTransformResult { + return expressionsTransformer.transformConstExpression(constExpression, data) + } + + override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: Any?): CompositeTransformResult { + return expressionsTransformer.transformAnnotationCall(annotationCall, data) + } + + // ------------------------------------- Declarations ------------------------------------- + + override fun transformDeclaration(declaration: FirDeclaration, data: Any?): CompositeTransformResult { + return declarationsTransformer.transformDeclaration(declaration, data) + } + + override fun transformProperty(property: FirProperty, data: Any?): CompositeTransformResult { + return declarationsTransformer.transformProperty(property, data) + } + + override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult { + return declarationsTransformer.transformRegularClass(regularClass, data) + } + + override fun transformSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): CompositeTransformResult { + return declarationsTransformer.transformSimpleFunction(simpleFunction, data) + } + + override fun > transformFunction(function: FirFunction, data: Any?): CompositeTransformResult { + return declarationsTransformer.transformFunction(function, data) + } + + override fun transformConstructor(constructor: FirConstructor, data: Any?): CompositeTransformResult { + return declarationsTransformer.transformConstructor(constructor, data) + } + + override fun transformAnonymousInitializer( + anonymousInitializer: FirAnonymousInitializer, + data: Any? + ): CompositeTransformResult { + return declarationsTransformer.transformAnonymousInitializer(anonymousInitializer, data) + } + + override fun transformAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: Any?): CompositeTransformResult { + return declarationsTransformer.transformAnonymousFunction(anonymousFunction, data) + } + + override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): CompositeTransformResult { + return declarationsTransformer.transformValueParameter(valueParameter, data) + } + + // ------------------------------------- Control flow statements ------------------------------------- + + override fun transformWhileLoop(whileLoop: FirWhileLoop, data: Any?): CompositeTransformResult { + return controlFlowStatementsTransformer.transformWhileLoop(whileLoop, data) + } + + override fun transformDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: Any?): CompositeTransformResult { + return controlFlowStatementsTransformer.transformDoWhileLoop(doWhileLoop, data) + } + + override fun transformWhenExpression(whenExpression: FirWhenExpression, data: Any?): CompositeTransformResult { + return controlFlowStatementsTransformer.transformWhenExpression(whenExpression, data) + } + + override fun transformWhenBranch(whenBranch: FirWhenBranch, data: Any?): CompositeTransformResult { + return controlFlowStatementsTransformer.transformWhenBranch(whenBranch, data) + } + + override fun transformWhenSubjectExpression( + whenSubjectExpression: FirWhenSubjectExpression, + data: Any? + ): CompositeTransformResult { + return controlFlowStatementsTransformer.transformWhenSubjectExpression(whenSubjectExpression, data) + } + + override fun transformTryExpression(tryExpression: FirTryExpression, data: Any?): CompositeTransformResult { + return controlFlowStatementsTransformer.transformTryExpression(tryExpression, data) + } + + override fun transformCatch(catch: FirCatch, data: Any?): CompositeTransformResult { + return controlFlowStatementsTransformer.transformCatch(catch, data) + } + + override fun transformJump(jump: FirJump, data: Any?): CompositeTransformResult { + return controlFlowStatementsTransformer.transformJump(jump, data) + } + + override fun transformThrowExpression(throwExpression: FirThrowExpression, data: Any?): CompositeTransformResult { + return controlFlowStatementsTransformer.transformThrowExpression(throwExpression, data) + } + + // -------------------------------------------------------------------------- + + fun FirElement.visitNoTransform(transformer: FirTransformer, data: D) { + val result = this.transform(transformer, data) + require(result.single === this) { "become ${result.single}: `${result.single.render()}`, was ${this}: `${this.render()}`" } + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformerAdapters.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformerAdapters.kt new file mode 100644 index 00000000000..5fc7470b1e7 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirBodyResolveTransformerAdapters.kt @@ -0,0 +1,98 @@ +/* + * Copyright 2010-2019 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.fir.resolve.transformers.body.resolve + +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.FirFile +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.renderWithType +import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.calls.ConeInferenceContext +import org.jetbrains.kotlin.fir.resolve.calls.InferenceComponents +import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowInferenceContext +import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.types.ConeClassErrorType +import org.jetbrains.kotlin.fir.types.ErrorTypeConstructor +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.FirTransformer +import org.jetbrains.kotlin.fir.visitors.compose +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.SimpleTypeMarker +import org.jetbrains.kotlin.types.model.TypeConstructorMarker +import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate + +class FirDesignatedBodyResolveTransformer( + private val designation: Iterator, + session: FirSession, + scopeSession: ScopeSession = ScopeSession(), + implicitTypeOnly: Boolean = true +) : FirBodyResolveTransformer( + session, + phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, + implicitTypeOnly = implicitTypeOnly, + scopeSession = scopeSession +) { + override fun transformElement(element: E, data: Any?): CompositeTransformResult { + if (designation.hasNext()) { + designation.next().visitNoTransform(this, data) + return element.compose() + } + return super.transformElement(element, data) + } + + override fun transformDeclaration(declaration: FirDeclaration, data: Any?): CompositeTransformResult { + return components.withContainer(declaration) { + declaration.replaceResolvePhase(transformerPhase) + transformElement(declaration, data) + } + } +} + + +@Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")")) +class FirImplicitTypeBodyResolveTransformerAdapter : FirTransformer() { + private val scopeSession = ScopeSession() + + override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { + return element.compose() + } + + override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { + val transformer = FirBodyResolveTransformer( + file.session, + phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, + implicitTypeOnly = true, + scopeSession = scopeSession + ) + return file.transform(transformer, null) + } +} + + +@Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")")) +class FirBodyResolveTransformerAdapter : FirTransformer() { + private val scopeSession = ScopeSession() + + override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { + return element.compose() + } + + override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { + // Despite of real phase is EXPRESSIONS, we state IMPLICIT_TYPES here, because DECLARATIONS previous phase is OK for us + val transformer = FirBodyResolveTransformer( + file.session, + phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE, + implicitTypeOnly = false, + scopeSession = scopeSession + ) + return file.transform(transformer, null) + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt new file mode 100644 index 00000000000..262e89dce36 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt @@ -0,0 +1,175 @@ +/* + * Copyright 2010-2019 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.fir.resolve.transformers.body.resolve + +import org.jetbrains.kotlin.fir.FirTargetElement +import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition +import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock +import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference +import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator +import org.jetbrains.kotlin.fir.resolve.transformers.FirWhenExhaustivenessTransformer +import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype +import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope +import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.compose +import org.jetbrains.kotlin.fir.visitors.transformSingle + +class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTransformer) : + FirPartialBodyResolveTransformer(transformer) { + + private val syntheticCallGenerator: FirSyntheticCallGenerator = FirSyntheticCallGenerator(components) + private val whenExhaustivenessTransformer = FirWhenExhaustivenessTransformer(components) + + + // ------------------------------- Loops ------------------------------- + + override fun transformWhileLoop(whileLoop: FirWhileLoop, data: Any?): CompositeTransformResult { + return whileLoop.also(dataFlowAnalyzer::enterWhileLoop) + .transformCondition(transformer, data).also(dataFlowAnalyzer::exitWhileLoopCondition) + .transformBlock(transformer, data).also(dataFlowAnalyzer::exitWhileLoop) + .transformOtherChildren(transformer, data).compose() + } + + override fun transformDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: Any?): CompositeTransformResult { + return doWhileLoop.also(dataFlowAnalyzer::enterDoWhileLoop) + .transformBlock(transformer, data).also(dataFlowAnalyzer::enterDoWhileLoopCondition) + .transformCondition(transformer, data).also(dataFlowAnalyzer::exitDoWhileLoop) + .transformOtherChildren(transformer, data).compose() + } + + // ------------------------------- When expressions ------------------------------- + + override fun transformWhenExpression(whenExpression: FirWhenExpression, data: Any?): CompositeTransformResult { + if (whenExpression.calleeReference is FirResolvedCallableReference && whenExpression.resultType !is FirImplicitTypeRef) { + return whenExpression.compose() + } + dataFlowAnalyzer.enterWhenExpression(whenExpression) + return withScopeCleanup(localScopes) with@{ + if (whenExpression.subjectVariable != null) { + localScopes += FirLocalScope() + } + @Suppress("NAME_SHADOWING") + var whenExpression = whenExpression.transformSubject(transformer, noExpectedType) + + when { + whenExpression.branches.isEmpty() -> { + } + whenExpression.isOneBranch() -> { + whenExpression = whenExpression.transformBranches(transformer, noExpectedType) + whenExpression.resultType = whenExpression.branches.first().result.resultType + } + else -> { + whenExpression = whenExpression.transformBranches(transformer, null) + + whenExpression = syntheticCallGenerator.generateCalleeForWhenExpression(whenExpression) ?: run { + dataFlowAnalyzer.exitWhenExpression(whenExpression) + whenExpression.resultType = FirErrorTypeRefImpl(null, "") + return@with whenExpression.compose() + } + + val expectedTypeRef = data as FirTypeRef? + whenExpression = callCompleter.completeCall(whenExpression, expectedTypeRef) + } + } + whenExpression = whenExpression.transformSingle(whenExhaustivenessTransformer, null) + dataFlowAnalyzer.exitWhenExpression(whenExpression) + whenExpression = whenExpression.replaceReturnTypeIfNotExhaustive() + whenExpression.compose() + } + } + + private fun FirWhenExpression.replaceReturnTypeIfNotExhaustive(): FirWhenExpression { + if (!isExhaustive) { + resultType = resultType.resolvedTypeFromPrototype(session.builtinTypes.unitType.type) + } + return this + } + + private fun FirWhenExpression.isOneBranch(): Boolean { + if (branches.size == 1) return true + if (branches.size > 2) return false + val lastBranch = branches.last() + return lastBranch.condition is FirElseIfTrueCondition && lastBranch.result is FirEmptyExpressionBlock + } + + override fun transformWhenBranch(whenBranch: FirWhenBranch, data: Any?): CompositeTransformResult { + return whenBranch.also { dataFlowAnalyzer.enterWhenBranchCondition(whenBranch) } + .transformCondition(transformer, data).also { dataFlowAnalyzer.exitWhenBranchCondition(it) } + .transformResult(transformer, data).also { dataFlowAnalyzer.exitWhenBranchResult(it) } + .compose() + } + + override fun transformWhenSubjectExpression( + whenSubjectExpression: FirWhenSubjectExpression, + data: Any? + ): CompositeTransformResult { + val parentWhen = whenSubjectExpression.whenSubject.whenExpression + val subjectType = parentWhen.subject?.resultType ?: parentWhen.subjectVariable?.returnTypeRef + if (subjectType != null) { + whenSubjectExpression.resultType = subjectType + } + return whenSubjectExpression.compose() + } + + // ------------------------------- Try/catch expressions ------------------------------- + + override fun transformTryExpression(tryExpression: FirTryExpression, data: Any?): CompositeTransformResult { + if (tryExpression.calleeReference is FirResolvedCallableReference && tryExpression.resultType !is FirImplicitTypeRef) { + return tryExpression.compose() + } + + dataFlowAnalyzer.enterTryExpression(tryExpression) + tryExpression.transformTryBlock(transformer, null) + dataFlowAnalyzer.exitTryMainBlock(tryExpression) + tryExpression.transformCatches(this, null) + + @Suppress("NAME_SHADOWING") + var result = syntheticCallGenerator.generateCalleeForTryExpression(tryExpression)?.let { + val expectedTypeRef = data as FirTypeRef? + callCompleter.completeCall(it, expectedTypeRef) + } ?: run { + tryExpression.resultType = FirErrorTypeRefImpl(null, "") + tryExpression + } + + result = if (result.finallyBlock != null) { + result.also(dataFlowAnalyzer::enterFinallyBlock) + .transformFinallyBlock(transformer, noExpectedType) + .also(dataFlowAnalyzer::exitFinallyBlock) + } else { + result + } + dataFlowAnalyzer.exitTryExpression(result) + return result.compose() + } + + override fun transformCatch(catch: FirCatch, data: Any?): CompositeTransformResult { + dataFlowAnalyzer.enterCatchClause(catch) + return withScopeCleanup(localScopes) { + localScopes += FirLocalScope() + catch.transformParameter(transformer, noExpectedType) + catch.transformBlock(transformer, null) + }.also { dataFlowAnalyzer.exitCatchClause(it) }.compose() + } + + // ------------------------------- Jumps ------------------------------- + + override fun transformJump(jump: FirJump, data: Any?): CompositeTransformResult { + val result = transformer.transformExpression(jump, data) + dataFlowAnalyzer.exitJump(jump) + return result + } + + override fun transformThrowExpression(throwExpression: FirThrowExpression, data: Any?): CompositeTransformResult { + return transformer.transformExpression(throwExpression, data).also { + dataFlowAnalyzer.exitThrowExceptionNode(it.single as FirThrowExpression) + } + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt new file mode 100644 index 00000000000..83d663f0ede --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -0,0 +1,421 @@ +/* + * Copyright 2010-2019 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.fir.resolve.transformers.body.resolve + +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.copy +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor +import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl +import org.jetbrains.kotlin.fir.expressions.FirStatement +import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue +import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue +import org.jetbrains.kotlin.fir.resolve.calls.extractLambdaInfoFromFunctionalType +import org.jetbrains.kotlin.fir.resolve.constructFunctionalTypeRef +import org.jetbrains.kotlin.fir.resolve.defaultType +import org.jetbrains.kotlin.fir.resolve.transformers.ControlFlowGraphReferenceTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.StoreType +import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype +import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope +import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.impl.FirComputingImplicitTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl +import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.FirTransformer +import org.jetbrains.kotlin.fir.visitors.compose +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addIfNotNull + +class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) { + private var primaryConstructorParametersScope: FirLocalScope? = null + + override fun transformDeclaration(declaration: FirDeclaration, data: Any?): CompositeTransformResult { + return components.withContainer(declaration) { + declaration.replaceResolvePhase(transformerPhase) + transformer.transformElement(declaration, data) + } + } + + override fun transformProperty(property: FirProperty, data: Any?): CompositeTransformResult { + if (property.isLocal) return transformLocalVariable(property, data) + val returnTypeRef = property.returnTypeRef + if (returnTypeRef !is FirImplicitTypeRef && implicitTypeOnly) return property.compose() + if (property.resolvePhase == transformerPhase) return property.compose() + dataFlowAnalyzer.enterProperty(property) + if (returnTypeRef is FirImplicitTypeRef) { + property.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef) + } + return withFullBodyResolve { + withScopeCleanup(localScopes) { + localScopes.addIfNotNull(primaryConstructorParametersScope) + components.withContainer(property) { + property.transformChildrenWithoutAccessors(returnTypeRef) + if (property.initializer != null) { + storeVariableReturnType(property) + } + withScopeCleanup(localScopes) { + localScopes.add(FirLocalScope().apply { + storeBackingField(property) + }) + property.transformAccessors() + } + } + property.replaceResolvePhase(transformerPhase) + val controlFlowGraph = dataFlowAnalyzer.exitProperty(property) + property.transformControlFlowGraphReference(ControlFlowGraphReferenceTransformer, controlFlowGraph) + property.compose() + } + } + } + + private fun transformLocalVariable(variable: FirProperty, data: Any?): CompositeTransformResult { + assert(variable.isLocal) + variable.transformOtherChildren(transformer, variable.returnTypeRef) + if (variable.initializer != null) { + storeVariableReturnType(variable) + } + variable.transformAccessors() + localScopes.lastOrNull()?.storeDeclaration(variable) + variable.replaceResolvePhase(transformerPhase) + dataFlowAnalyzer.exitVariableDeclaration(variable) + return variable.compose() + } + + private fun FirProperty.transformChildrenWithoutAccessors(returnTypeRef: FirTypeRef): FirProperty { + return transformReturnTypeRef(transformer, returnTypeRef). + transformOtherChildren(transformer, returnTypeRef) + } + + private fun > FirVariable.transformAccessors() { + var enhancedTypeRef = returnTypeRef + getter?.let { + transformAccessor(it, enhancedTypeRef, this) + } + if (returnTypeRef is FirImplicitTypeRef) { + storeVariableReturnType(this) + enhancedTypeRef = returnTypeRef + } + setter?.let { + it.valueParameters[0].transformReturnTypeRef(StoreType, enhancedTypeRef) + transformAccessor(it, enhancedTypeRef, this) + } + } + + private fun transformAccessor( + accessor: FirPropertyAccessor, + enhancedTypeRef: FirTypeRef, + owner: FirVariable<*> + ) { + if (accessor is FirDefaultPropertyAccessor || accessor.body == null) { + transformFunction(accessor, enhancedTypeRef) + } + val returnTypeRef = accessor.returnTypeRef + if (returnTypeRef is FirImplicitTypeRef && enhancedTypeRef !is FirResolvedTypeRef) { + accessor.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef) + } + val expectedReturnTypeRef = if (enhancedTypeRef is FirResolvedTypeRef && returnTypeRef !is FirResolvedTypeRef) { + enhancedTypeRef + } else { + returnTypeRef + } + val receiverTypeRef = owner.receiverTypeRef + if (receiverTypeRef != null) { + withLabelAndReceiverType(owner.name, owner, receiverTypeRef.coneTypeUnsafe()) { + transformFunctionWithGivenSignature(accessor, expectedReturnTypeRef) + } + } else { + transformFunctionWithGivenSignature(accessor, expectedReturnTypeRef) + } as CompositeTransformResult + } + + override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult { + val oldConstructorScope = primaryConstructorParametersScope + primaryConstructorParametersScope = null + val type = regularClass.defaultType() + val result = withLabelAndReceiverType(regularClass.name, regularClass, type) { + val constructor = regularClass.declarations.firstOrNull() as? FirConstructor + if (constructor?.isPrimary == true) { + primaryConstructorParametersScope = FirLocalScope().apply { + constructor.valueParameters.forEach { this.storeDeclaration(it) } + } + } + transformDeclaration(regularClass, data) + } + primaryConstructorParametersScope = oldConstructorScope + return result as CompositeTransformResult + } + + private fun transformAnonymousFunctionWithLambdaResolution( + anonymousFunction: FirAnonymousFunction, lambdaResolution: LambdaResolution + ): FirAnonymousFunction { + val receiverTypeRef = anonymousFunction.receiverTypeRef + fun transform(): FirAnonymousFunction { + val expectedReturnType = + lambdaResolution.expectedReturnTypeRef ?: anonymousFunction.returnTypeRef.takeUnless { it is FirImplicitTypeRef } + val result = transformFunction(anonymousFunction, expectedReturnType).single as FirAnonymousFunction + val body = result.body + return if (result.returnTypeRef is FirImplicitTypeRef && body != null) { + result.transformReturnTypeRef(transformer, body.resultType) + result + } else { + result + } + } + + val label = anonymousFunction.label + return if (label != null && receiverTypeRef != null) { + withLabelAndReceiverType(Name.identifier(label.name), anonymousFunction, receiverTypeRef.coneTypeUnsafe()) { + transform() + } + } else { + transform() + } + } + + data class LambdaResolution(val expectedReturnTypeRef: FirResolvedTypeRef?) + + override fun transformSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): CompositeTransformResult { + val returnTypeRef = simpleFunction.returnTypeRef + if ((returnTypeRef !is FirImplicitTypeRef) && implicitTypeOnly) { + return simpleFunction.compose() + } + return withFullBodyResolve { + if (returnTypeRef is FirImplicitTypeRef) { + simpleFunction.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef) + } + + val receiverTypeRef = simpleFunction.receiverTypeRef + if (receiverTypeRef != null) { + withLabelAndReceiverType(simpleFunction.name, simpleFunction, receiverTypeRef.coneTypeUnsafe()) { + transformFunctionWithGivenSignature(simpleFunction, returnTypeRef) + } + } else { + transformFunctionWithGivenSignature(simpleFunction, returnTypeRef) + } + } + } + + private fun transformFunctionWithGivenSignature( + function: FirFunction<*>, + returnTypeRef: FirTypeRef + ): CompositeTransformResult { + if (function is FirSimpleFunction) { + localScopes.lastOrNull()?.storeDeclaration(function) + } + val result = transformFunction(function, returnTypeRef).single as FirFunction<*> + val body = result.body + return if (result.returnTypeRef is FirImplicitTypeRef && body != null) { + result.transformReturnTypeRef(transformer, body.resultType) + result + } else { + result + }.compose() + } + + override fun > transformFunction(function: FirFunction, data: Any?): CompositeTransformResult { + return withScopeCleanup(localScopes) { + localScopes += FirLocalScope() + dataFlowAnalyzer.enterFunction(function) + transformDeclaration(function, data).also { + val result = it.single as FirFunction<*> + dataFlowAnalyzer.exitFunction(result)?.let { controlFlowGraph -> + result.transformControlFlowGraphReference(ControlFlowGraphReferenceTransformer, controlFlowGraph) + } + } as CompositeTransformResult + } + } + + override fun transformConstructor(constructor: FirConstructor, data: Any?): CompositeTransformResult { + if (implicitTypeOnly) return constructor.compose() + return transformFunction(constructor, data) as CompositeTransformResult + } + + override fun transformAnonymousInitializer( + anonymousInitializer: FirAnonymousInitializer, + data: Any? + ): CompositeTransformResult { + if (implicitTypeOnly) return anonymousInitializer.compose() + return withScopeCleanup(localScopes) { + dataFlowAnalyzer.enterInitBlock(anonymousInitializer) + localScopes.addIfNotNull(primaryConstructorParametersScope) + transformDeclaration(anonymousInitializer, data).also { + dataFlowAnalyzer.exitInitBlock(it.single as FirAnonymousInitializer) + } + } + } + + override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): CompositeTransformResult { + localScopes.lastOrNull()?.storeDeclaration(valueParameter) + if (valueParameter.returnTypeRef is FirImplicitTypeRef) { + valueParameter.replaceResolvePhase(transformerPhase) + return valueParameter.compose() // TODO + } + return (transformDeclaration(valueParameter, valueParameter.returnTypeRef).single as FirStatement).compose() + } + + override fun transformAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: Any?): CompositeTransformResult { + return when (data) { + null -> { + anonymousFunction.compose() + } + is LambdaResolution -> { + transformAnonymousFunctionWithLambdaResolution(anonymousFunction, data).compose() + } + is FirTypeRef -> { + val resolvedLambdaAtom = (data as? FirResolvedTypeRef)?.let { + extractLambdaInfoFromFunctionalType( + it.type, it, anonymousFunction + ) + } + var af = anonymousFunction + val valueParameters = + if (resolvedLambdaAtom == null) af.valueParameters + else { + val singleParameterType = resolvedLambdaAtom.parameters.singleOrNull() + val itParam = when { + af.valueParameters.isEmpty() && singleParameterType != null -> { + val name = Name.identifier("it") + FirValueParameterImpl( + null, + session, + FirResolvedTypeRefImpl(null, singleParameterType), + name, + FirVariableSymbol(name), + defaultValue = null, + isCrossinline = false, + isNoinline = false, + isVararg = false + ) + } + else -> null + } + if (itParam != null) { + listOf(itParam) + } else { + af.valueParameters.mapIndexed { index, param -> + if (param.returnTypeRef is FirResolvedTypeRef) { + param + } else { + param.transformReturnTypeRef( + StoreType, + param.returnTypeRef.resolvedTypeFromPrototype( + resolvedLambdaAtom.parameters[index] + ) + ) + param + } + } + } + + } + val returnTypeRefFromResolvedAtom = resolvedLambdaAtom?.returnType?.let { af.returnTypeRef.resolvedTypeFromPrototype(it) } + af = af.copy( + receiverTypeRef = af.receiverTypeRef?.takeIf { it !is FirImplicitTypeRef } + ?: resolvedLambdaAtom?.receiver?.let { af.receiverTypeRef?.resolvedTypeFromPrototype(it) }, + valueParameters = valueParameters, + returnTypeRef = (af.returnTypeRef as? FirResolvedTypeRef) + ?: returnTypeRefFromResolvedAtom + ?: af.returnTypeRef + ) + af = af.transformValueParameters(ImplicitToErrorTypeTransformer, null) + val bodyExpectedType = returnTypeRefFromResolvedAtom ?: data + af = transformFunction(af, bodyExpectedType).single as FirAnonymousFunction + af = af.copy( + returnTypeRef = af.body?.resultType ?: FirErrorTypeRefImpl(af.psi, "No result type for lambda") + ) + af.replaceTypeRef(af.constructFunctionalTypeRef(session)) + af.compose() + } + else -> { + transformFunction(anonymousFunction, data).single.compose() + } + } + } + + private inline fun withLabelAndReceiverType( + labelName: Name, + owner: FirDeclaration, + type: ConeKotlinType, + block: () -> T + ): T { + val implicitReceiverValue = when (owner) { + is FirRegularClass -> { + ImplicitDispatchReceiverValue(owner.symbol, type, symbolProvider, session, scopeSession) + } + is FirFunction<*> -> { + ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) + } + is FirVariable<*> -> { + ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) + } + else -> { + throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}") + } + } + implicitReceiverStack.add(labelName, implicitReceiverValue) + val result = block() + implicitReceiverStack.pop(labelName) + return result + } + + private fun storeVariableReturnType(variable: FirVariable<*>) { + val initializer = variable.initializer + if (variable.returnTypeRef is FirImplicitTypeRef) { + when { + initializer != null -> { + variable.transformReturnTypeRef( + transformer, + when (val resultType = initializer.resultType) { + is FirImplicitTypeRef -> FirErrorTypeRefImpl( + null, + "No result type for initializer" + ) + else -> resultType + } + ) + } + variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> { + variable.transformReturnTypeRef( + transformer, + when (val resultType = variable.getter?.returnTypeRef) { + is FirImplicitTypeRef -> FirErrorTypeRefImpl( + null, + "No result type for getter" + ) + else -> resultType + } + ) + } + else -> { + variable.transformReturnTypeRef( + transformer, FirErrorTypeRefImpl(null, "Cannot infer variable type without initializer / getter / delegate") + ) + } + } + if (variable.getter?.returnTypeRef is FirImplicitTypeRef) { + variable.getter?.transformReturnTypeRef(transformer, variable.returnTypeRef) + } + } + } + + private object ImplicitToErrorTypeTransformer : FirTransformer() { + override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { + return element.compose() + } + + override fun transformValueParameter(valueParameter: FirValueParameter, data: Nothing?): CompositeTransformResult { + if (valueParameter.returnTypeRef is FirImplicitTypeRef) { + valueParameter.transformReturnTypeRef( + StoreType, + valueParameter.returnTypeRef.resolvedTypeFromPrototype(ConeKotlinErrorType("No type for parameter")) + ) + } + return valueParameter.compose() + } + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt new file mode 100644 index 00000000000..282dbefe7d5 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -0,0 +1,352 @@ +/* + * Copyright 2010-2019 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.fir.resolve.transformers.body.resolve + +import org.jetbrains.kotlin.contracts.description.InvocationKind +import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.expressions.* +import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionWithSmartcastImpl +import org.jetbrains.kotlin.fir.references.FirDelegateFieldReference +import org.jetbrains.kotlin.fir.references.FirResolvedCallableReference +import org.jetbrains.kotlin.fir.references.FirSuperReference +import org.jetbrains.kotlin.fir.references.impl.FirExplicitThisReference +import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference +import org.jetbrains.kotlin.fir.resolve.calls.ConeInferenceContext +import org.jetbrains.kotlin.fir.resolve.calls.candidate +import org.jetbrains.kotlin.fir.resolve.constructType +import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer +import org.jetbrains.kotlin.fir.resolve.typeFromCallee +import org.jetbrains.kotlin.fir.resolve.withNullability +import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType +import org.jetbrains.kotlin.fir.symbols.StandardClassIds +import org.jetbrains.kotlin.fir.symbols.invoke +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl +import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl +import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.compose +import org.jetbrains.kotlin.ir.expressions.IrConstKind +import org.jetbrains.kotlin.name.ClassId + +class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) { + private val qualifiedResolver: FirQualifiedNameResolver = FirQualifiedNameResolver(components) + private val callResolver: FirCallResolver = FirCallResolver( + this, + topLevelScopes, + localScopes, + implicitReceiverStack, + qualifiedResolver + ) + + private inline val builtinTypes: BuiltinTypes get() = session.builtinTypes + + override fun transformExpression(expression: FirExpression, data: Any?): CompositeTransformResult { + if (expression.resultType is FirImplicitTypeRef && expression !is FirWrappedExpression) { + val type = FirErrorTypeRefImpl(expression.psi, "Type calculating for ${expression::class} is not supported") + expression.resultType = type + } + return (expression.transformChildren(transformer, data) as FirStatement).compose() + } + + override fun transformQualifiedAccessExpression( + qualifiedAccessExpression: FirQualifiedAccessExpression, + data: Any? + ): CompositeTransformResult { + var result = when (val callee = qualifiedAccessExpression.calleeReference) { + is FirExplicitThisReference -> { + val labelName = callee.labelName + val implicitReceiver = implicitReceiverStack[labelName] + implicitReceiver?.boundSymbol?.let { + callee.replaceBoundSymbol(it) + } + qualifiedAccessExpression.resultType = FirResolvedTypeRefImpl( + null, implicitReceiver?.type ?: ConeKotlinErrorType("Unresolved this@$labelName") + ) + qualifiedAccessExpression + } + is FirSuperReference -> { + if (callee.superTypeRef is FirResolvedTypeRef) { + qualifiedAccessExpression.resultType = callee.superTypeRef + } else { + val superTypeRef = implicitReceiverStack.lastDispatchReceiver() + ?.boundSymbol?.phasedFir?.superTypeRefs?.firstOrNull() + ?: FirErrorTypeRefImpl(qualifiedAccessExpression.psi, "No super type") + qualifiedAccessExpression.resultType = superTypeRef + callee.replaceSuperTypeRef(superTypeRef) + } + qualifiedAccessExpression + } + is FirDelegateFieldReference -> { + val delegateFieldSymbol = callee.resolvedSymbol + qualifiedAccessExpression.resultType = delegateFieldSymbol.delegate.typeRef + qualifiedAccessExpression + } + is FirResolvedCallableReference -> { + if (qualifiedAccessExpression.typeRef !is FirResolvedTypeRef) { + storeTypeFromCallee(qualifiedAccessExpression) + } + qualifiedAccessExpression + } + else -> { + val transformedCallee = callResolver.resolveVariableAccessAndSelectCandidate(qualifiedAccessExpression, file) + // NB: here we can get raw expression because of dropped qualifiers (see transform callee), + // so candidate existence must be checked before calling completion + if (transformedCallee is FirQualifiedAccessExpression && transformedCallee.candidate() != null) { + callCompleter.completeCall(transformedCallee, data as? FirTypeRef) + } else { + transformedCallee + } + } + } + if (result is FirQualifiedAccessExpression) { + result = transformQualifiedAccessUsingSmartcastInfo(result) + dataFlowAnalyzer.exitQualifiedAccessExpression(result) + } + return result.compose() + } + + private fun transformQualifiedAccessUsingSmartcastInfo(qualifiedAccessExpression: FirQualifiedAccessExpression): FirQualifiedAccessExpression { + val typesFromSmartCast = dataFlowAnalyzer.getTypeUsingSmartcastInfo(qualifiedAccessExpression) ?: return qualifiedAccessExpression + val allTypes = typesFromSmartCast.toMutableList().also { + it += qualifiedAccessExpression.resultType.coneTypeUnsafe() + } + val intersectedType = ConeTypeIntersector.intersectTypes(inferenceComponents.ctx as ConeInferenceContext, allTypes) + // TODO: add check that intersectedType is not equal to original type + val intersectedTypeRef = FirResolvedTypeRefImpl(qualifiedAccessExpression.resultType.psi, intersectedType).apply { + annotations += qualifiedAccessExpression.resultType.annotations + } + return FirExpressionWithSmartcastImpl(qualifiedAccessExpression, intersectedTypeRef, typesFromSmartCast) + } + + override fun transformFunctionCall(functionCall: FirFunctionCall, data: Any?): CompositeTransformResult { + dataFlowAnalyzer.enterFunctionCall(functionCall) + if (functionCall.calleeReference is FirResolvedCallableReference && functionCall.resultType is FirImplicitTypeRef) { + storeTypeFromCallee(functionCall) + } + if (functionCall.calleeReference !is FirSimpleNamedReference) return functionCall.compose() + functionCall.transform(InvocationKindTransformer, null) + val expectedTypeRef = data as FirTypeRef? + val completeInference = + try { + val initialExplicitReceiver = functionCall.explicitReceiver + val resultExpression = callResolver.resolveCallAndSelectCandidate(functionCall, expectedTypeRef, file) + val resultExplicitReceiver = resultExpression.explicitReceiver + if (initialExplicitReceiver !== resultExplicitReceiver && resultExplicitReceiver is FirQualifiedAccess) { + // name.invoke() case + callCompleter.completeCall(resultExplicitReceiver, noExpectedType) + } + callCompleter.completeCall(resultExpression, expectedTypeRef) + } catch (e: Throwable) { + throw RuntimeException("While resolving call ${functionCall.render()}", e) + } + + dataFlowAnalyzer.exitFunctionCall(completeInference) + return completeInference.compose() + } + + override fun transformBlock(block: FirBlock, data: Any?): CompositeTransformResult { + dataFlowAnalyzer.enterBlock(block) + @Suppress("NAME_SHADOWING") + val block = block.transformChildren(transformer, data) as FirBlock + val statement = block.statements.lastOrNull() + + val resultExpression = when (statement) { + is FirReturnExpression -> statement.result + is FirExpression -> statement + else -> null + } + block.resultType = if (resultExpression == null) { + FirImplicitUnitTypeRef(block.psi) + } else { + (resultExpression.resultType as? FirResolvedTypeRef) ?: FirErrorTypeRefImpl(null, "No type for block") + } + dataFlowAnalyzer.exitBlock(block) + return block.compose() + } + + override fun transformThisReceiverExpression( + thisReceiverExpression: FirThisReceiverExpression, + data: Any? + ): CompositeTransformResult { + return transformQualifiedAccessExpression(thisReceiverExpression, data) + } + + override fun transformOperatorCall(operatorCall: FirOperatorCall, data: Any?): CompositeTransformResult { + val result = if (operatorCall.operation in FirOperation.BOOLEANS) { + (operatorCall.transformChildren(transformer, noExpectedType) as FirOperatorCall).also { + it.resultType = builtinTypes.booleanType + } + } else { + transformExpression(operatorCall, data).single + } as FirOperatorCall + dataFlowAnalyzer.exitOperatorCall(result) + return result.compose() + } + + override fun transformTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Any?): CompositeTransformResult { + val symbolProvider = session.firSymbolProvider + val resolved = transformExpression(typeOperatorCall, data).single + when ((resolved as FirTypeOperatorCall).operation) { + FirOperation.IS, FirOperation.NOT_IS -> { + resolved.resultType = FirResolvedTypeRefImpl( + null, + StandardClassIds.Boolean(symbolProvider).constructType(emptyArray(), isNullable = false) + ) + } + FirOperation.AS -> { + resolved.resultType = resolved.conversionTypeRef + } + FirOperation.SAFE_AS -> { + resolved.resultType = + resolved.conversionTypeRef.withReplacedConeType( + resolved.conversionTypeRef.coneTypeUnsafe().withNullability(ConeNullability.NULLABLE) + ) + } + else -> error("Unknown type operator") + } + dataFlowAnalyzer.exitTypeOperatorCall(typeOperatorCall) + return resolved.compose() + } + + override fun transformBinaryLogicExpression( + binaryLogicExpression: FirBinaryLogicExpression, + data: Any? + ): CompositeTransformResult { + val booleanType = builtinTypes.booleanType + return when (binaryLogicExpression.kind) { + LogicOperationKind.AND -> + binaryLogicExpression.also(dataFlowAnalyzer::enterBinaryAnd) + .transformLeftOperand(this, booleanType).also(dataFlowAnalyzer::exitLeftBinaryAndArgument) + .transformRightOperand(this, booleanType).also(dataFlowAnalyzer::exitBinaryAnd) + + LogicOperationKind.OR -> + binaryLogicExpression.also(dataFlowAnalyzer::enterBinaryOr) + .transformLeftOperand(this, booleanType).also(dataFlowAnalyzer::exitLeftBinaryOrArgument) + .transformRightOperand(this, booleanType).also(dataFlowAnalyzer::exitBinaryOr) + }.transformOtherChildren(transformer, booleanType).also { + it.resultType = booleanType + }.compose() + } + + override fun transformVariableAssignment( + variableAssignment: FirVariableAssignment, + data: Any? + ): CompositeTransformResult { + // val resolvedAssignment = transformCallee(variableAssignment) + val resolvedAssignment = callResolver.resolveVariableAccessAndSelectCandidate(variableAssignment, file) + val result = if (resolvedAssignment is FirVariableAssignment) { + val completeAssignment = callCompleter.completeCall(resolvedAssignment, noExpectedType) + val expectedType = components.typeFromCallee(completeAssignment) + completeAssignment.transformRValue(transformer, expectedType) + } else { + // This can happen in erroneous code only + resolvedAssignment + } + // TODO: maybe replace with FirAbstractAssignment for performance? + (result as? FirVariableAssignment)?.let { dataFlowAnalyzer.exitVariableAssignment(it) } + return result.compose() + } + + override fun transformGetClassCall(getClassCall: FirGetClassCall, data: Any?): CompositeTransformResult { + val transformedGetClassCall = transformExpression(getClassCall, data).single as FirGetClassCall + val kClassSymbol = ClassId.fromString("kotlin/reflect/KClass")(session.firSymbolProvider) + + val typeOfExpression = when (val lhs = transformedGetClassCall.argument) { + is FirResolvedQualifier -> { + val classId = lhs.classId + if (classId != null) { + val symbol = symbolProvider.getClassLikeSymbolByFqName(classId)!! + // TODO: Unify logic? + symbol.constructType( + Array(symbol.phasedFir.typeParameters.size) { + ConeStarProjection + }, + isNullable = false + ) + } else { + lhs.resultType.coneTypeUnsafe() + } + } + else -> lhs.resultType.coneTypeUnsafe() + } + + transformedGetClassCall.resultType = + FirResolvedTypeRefImpl( + null, + kClassSymbol.constructType(arrayOf(typeOfExpression), false) + ) + return transformedGetClassCall.compose() + } + + override fun transformWrappedDelegateExpression( + wrappedDelegateExpression: FirWrappedDelegateExpression, + data: Any? + ): CompositeTransformResult { + transformExpression(wrappedDelegateExpression, data) + with(wrappedDelegateExpression) { + val delegateProviderTypeRef = delegateProvider.typeRef + val useDelegateProvider = delegateProviderTypeRef is FirResolvedTypeRef && + delegateProviderTypeRef !is FirErrorTypeRef && + delegateProviderTypeRef.type !is ConeKotlinErrorType + return if (useDelegateProvider) delegateProvider.compose() else expression.compose() + } + } + + override fun transformConstExpression(constExpression: FirConstExpression, data: Any?): CompositeTransformResult { + val expectedType = data as FirTypeRef? + + val kind = constExpression.kind + if (expectedType == null || expectedType is FirImplicitTypeRef || + kind == IrConstKind.Null || kind == IrConstKind.Boolean || kind == IrConstKind.Char + ) { + val symbol = when (kind) { + IrConstKind.Null -> StandardClassIds.Nothing(symbolProvider) + IrConstKind.Boolean -> StandardClassIds.Boolean(symbolProvider) + IrConstKind.Char -> StandardClassIds.Char(symbolProvider) + IrConstKind.Byte -> StandardClassIds.Byte(symbolProvider) + IrConstKind.Short -> StandardClassIds.Short(symbolProvider) + IrConstKind.Int -> StandardClassIds.Int(symbolProvider) + IrConstKind.Long -> StandardClassIds.Long(symbolProvider) + IrConstKind.String -> StandardClassIds.String(symbolProvider) + IrConstKind.Float -> StandardClassIds.Float(symbolProvider) + IrConstKind.Double -> StandardClassIds.Double(symbolProvider) + } + + val type = ConeClassTypeImpl(symbol.toLookupTag(), emptyArray(), isNullable = kind == IrConstKind.Null) + + constExpression.resultType = FirResolvedTypeRefImpl(null, type) + } else { + constExpression.resultType = if (kind != IrConstKind.Null) { + expectedType.resolvedTypeFromPrototype( + expectedType.coneTypeUnsafe().withNullability(ConeNullability.NOT_NULL) + ) + } else { + expectedType + } + } + + + return transformExpression(constExpression, data).also { + dataFlowAnalyzer.exitConstExpresion(it.single as FirConstExpression<*>) + } + } + + override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: Any?): CompositeTransformResult { + dataFlowAnalyzer.enterAnnotationCall(annotationCall) + return (annotationCall.transformChildren(transformer, data) as FirAnnotationCall).also { + dataFlowAnalyzer.exitAnnotationCall(it) + }.compose() + } + + // ------------------------------------------------------------------------------------------------ + + internal fun storeTypeFromCallee(access: T) where T : FirQualifiedAccess, T : FirExpression { + access.resultType = callCompleter.typeFromCallee(access) + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirPartialBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirPartialBodyResolveTransformer.kt new file mode 100644 index 00000000000..4e909d51158 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirPartialBodyResolveTransformer.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2019 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.fir.resolve.transformers.body.resolve + +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult + +abstract class FirPartialBodyResolveTransformer( + val transformer: FirBodyResolveTransformer +) : FirAbstractBodyResolveTransformer(transformer.transformerPhase) { + @Suppress("OVERRIDE_BY_INLINE") + final override inline val components: BodyResolveTransformerComponents get() = transformer.components + + override var implicitTypeOnly: Boolean + get() = transformer.implicitTypeOnly + set(value) { + transformer.implicitTypeOnly = value + } + + override fun transformElement(element: E, data: Any?): CompositeTransformResult { + return element.transform(transformer, data) + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt index 36549e78f63..bc8b19db696 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.calls.ConeTypeVariableTypeConstructor import org.jetbrains.kotlin.fir.resolve.calls.hasNullableSuperType import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap -import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.* diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirResolutionApi.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirResolutionApi.kt index e67102f428e..c153a24f2af 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirResolutionApi.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirResolutionApi.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.resolve.FirProvider -import org.jetbrains.kotlin.fir.resolve.transformers.FirDesignatedBodyResolveTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDesignatedBodyResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.runResolve import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.impl.FirSelfImportingScope