[FIR] Get rid of field duplication in body resolve transformers

This commit is contained in:
Nikolay Lunyak
2022-10-19 18:33:53 +03:00
parent e34dd49872
commit b03e14f565
13 changed files with 760 additions and 696 deletions
@@ -10,13 +10,13 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractResolveTransformer
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveTreeBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer.Companion.updatePhaseDeep
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirAbstractContractResolveTransformerDispatcher
/**
* Transform designation into CONTRACTS declaration. Affects only for target declaration and it's children
@@ -25,7 +25,7 @@ internal class LLFirDesignatedContractsResolveTransformer(
private val designation: FirDeclarationDesignationWithFile,
session: FirSession,
scopeSession: ScopeSession,
) : LLFirLazyTransformer, FirContractResolveTransformer(session, scopeSession) {
) : LLFirLazyTransformer, FirAbstractContractResolveTransformerDispatcher(session, scopeSession) {
private val ideDeclarationTransformer = LLFirDeclarationTransformer(designation)
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.FirCallCompletionResultsWriterTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.InvocationKindTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher
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
@@ -44,7 +45,7 @@ import org.jetbrains.kotlin.types.model.safeSubstitute
import org.jetbrains.kotlin.utils.addToStdlib.runIf
class FirCallCompleter(
private val transformer: FirBodyResolveTransformer,
private val transformer: FirAbstractBodyResolveTransformerDispatcher,
private val components: FirAbstractBodyResolveTransformer.BodyResolveTransformerComponents
) {
private val session = components.session
@@ -76,7 +76,7 @@ abstract class FirAbstractBodyResolveTransformer(phase: FirResolvePhase) : FirAb
open class BodyResolveTransformerComponents(
override val session: FirSession,
override val scopeSession: ScopeSession,
val transformer: FirBodyResolveTransformer,
val transformer: FirAbstractBodyResolveTransformerDispatcher,
val context: BodyResolveContext
) : BodyResolveComponents() {
override val fileImportsScope: List<FirScope> get() = context.fileImportsScope
@@ -0,0 +1,431 @@
/*
* 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.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionStageRunner
import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowAnalyzerContext
import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
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.types.*
import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.fir.visitors.FirTransformer
abstract class FirAbstractBodyResolveTransformerDispatcher(
session: FirSession,
phase: FirResolvePhase,
override var implicitTypeOnly: Boolean,
scopeSession: ScopeSession,
val returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve,
outerBodyResolveContext: BodyResolveContext? = null,
val firTowerDataContextCollector: FirTowerDataContextCollector? = null,
val firProviderInterceptor: FirProviderInterceptor? = null,
) : FirAbstractBodyResolveTransformer(phase) {
final override val context: BodyResolveContext =
outerBodyResolveContext ?: BodyResolveContext(returnTypeCalculator, DataFlowAnalyzerContext.empty(session))
final override val components: BodyResolveTransformerComponents =
BodyResolveTransformerComponents(session, scopeSession, this, context)
final override val resolutionContext: ResolutionContext = ResolutionContext(session, components, context)
internal abstract val expressionsTransformer: FirExpressionsResolveTransformer
protected abstract val declarationsTransformer: FirDeclarationsResolveTransformer
private val controlFlowStatementsTransformer = FirControlFlowStatementsResolveTransformer(this)
override fun transformFile(file: FirFile, data: ResolutionMode): FirFile {
checkSessionConsistency(file)
return context.withFile(file, components) {
firTowerDataContextCollector?.addFileContext(file, context.towerDataContext)
@Suppress("UNCHECKED_CAST")
transformDeclarationContent(file, data) as FirFile
}
}
override fun <E : FirElement> transformElement(element: E, data: ResolutionMode): E {
@Suppress("UNCHECKED_CAST")
return (element.transformChildren(this, data) as E)
}
override fun transformTypeRef(typeRef: FirTypeRef, data: ResolutionMode): FirResolvedTypeRef {
val resolvedTypeRef = if (typeRef is FirResolvedTypeRef) {
typeRef
} else {
typeResolverTransformer.withFile(context.file) {
transformTypeRef(
typeRef,
ScopeClassDeclaration(
components.createCurrentScopeList(),
context.containingClassDeclarations,
context.containers.lastOrNull { it is FirTypeParameterRefsOwner && it !is FirAnonymousFunction }
)
)
}
}
resolvedTypeRef.coneType.forEachType {
it.type.attributes.customAnnotations.forEach { typeArgumentAnnotation ->
typeArgumentAnnotation.accept(this, data)
}
}
return resolvedTypeRef.transformAnnotations(this, data)
}
override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: ResolutionMode): FirTypeRef {
if (data !is ResolutionMode.WithExpectedType)
return implicitTypeRef
return data.expectedTypeRef
}
// ------------------------------------- Expressions -------------------------------------
override fun transformExpression(expression: FirExpression, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformExpression(expression, data)
}
override fun transformWrappedArgumentExpression(
wrappedArgumentExpression: FirWrappedArgumentExpression,
data: ResolutionMode
): FirStatement {
return transformElement(wrappedArgumentExpression, data)
}
override fun transformQualifiedAccessExpression(
qualifiedAccessExpression: FirQualifiedAccessExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformQualifiedAccessExpression(qualifiedAccessExpression, data)
}
override fun transformPropertyAccessExpression(
propertyAccessExpression: FirPropertyAccessExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformQualifiedAccessExpression(propertyAccessExpression, data)
}
override fun transformFunctionCall(functionCall: FirFunctionCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformFunctionCall(functionCall, data)
}
override fun transformStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformStringConcatenationCall(stringConcatenationCall, data)
}
override fun transformCallableReferenceAccess(
callableReferenceAccess: FirCallableReferenceAccess,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformCallableReferenceAccess(callableReferenceAccess, data)
}
override fun transformBlock(block: FirBlock, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformBlock(block, data)
}
override fun transformThisReceiverExpression(
thisReceiverExpression: FirThisReceiverExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformThisReceiverExpression(thisReceiverExpression, data)
}
override fun transformComparisonExpression(
comparisonExpression: FirComparisonExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformComparisonExpression(comparisonExpression, data)
}
override fun transformTypeOperatorCall(
typeOperatorCall: FirTypeOperatorCall,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformTypeOperatorCall(typeOperatorCall, data)
}
override fun transformAssignmentOperatorStatement(
assignmentOperatorStatement: FirAssignmentOperatorStatement,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformAssignmentOperatorStatement(assignmentOperatorStatement, data)
}
override fun transformEqualityOperatorCall(
equalityOperatorCall: FirEqualityOperatorCall,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformEqualityOperatorCall(equalityOperatorCall, data)
}
override fun transformCheckNotNullCall(
checkNotNullCall: FirCheckNotNullCall,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformCheckNotNullCall(checkNotNullCall, data)
}
override fun transformBinaryLogicExpression(
binaryLogicExpression: FirBinaryLogicExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformBinaryLogicExpression(binaryLogicExpression, data)
}
override fun transformVariableAssignment(
variableAssignment: FirVariableAssignment,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformVariableAssignment(variableAssignment, data)
}
override fun transformGetClassCall(getClassCall: FirGetClassCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformGetClassCall(getClassCall, data)
}
override fun transformWrappedDelegateExpression(
wrappedDelegateExpression: FirWrappedDelegateExpression,
data: ResolutionMode
): FirStatement {
return declarationsTransformer.transformWrappedDelegateExpression(wrappedDelegateExpression, data)
}
override fun <T> transformConstExpression(
constExpression: FirConstExpression<T>,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformConstExpression(constExpression, data)
}
override fun transformAnnotation(annotation: FirAnnotation, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformAnnotation(annotation, data)
}
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformAnnotationCall(annotationCall, data)
}
override fun transformErrorAnnotationCall(errorAnnotationCall: FirErrorAnnotationCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformErrorAnnotationCall(errorAnnotationCall, data)
}
override fun transformDelegatedConstructorCall(
delegatedConstructorCall: FirDelegatedConstructorCall,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformDelegatedConstructorCall(delegatedConstructorCall, data)
}
override fun transformAugmentedArraySetCall(
augmentedArraySetCall: FirAugmentedArraySetCall,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformAugmentedArraySetCall(augmentedArraySetCall, data)
}
override fun transformSafeCallExpression(
safeCallExpression: FirSafeCallExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformSafeCallExpression(safeCallExpression, data)
}
override fun transformCheckedSafeCallSubject(
checkedSafeCallSubject: FirCheckedSafeCallSubject,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformCheckedSafeCallSubject(checkedSafeCallSubject, data)
}
override fun transformArrayOfCall(arrayOfCall: FirArrayOfCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformArrayOfCall(arrayOfCall, data)
}
// ------------------------------------- Declarations -------------------------------------
override fun transformDeclaration(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration {
return declarationsTransformer.transformDeclaration(declaration, data)
}
open fun transformDeclarationContent(
declaration: FirDeclaration, data: ResolutionMode
): FirDeclaration {
return transformElement(declaration, data)
}
override fun transformDeclarationStatus(
declarationStatus: FirDeclarationStatus,
data: ResolutionMode
): FirDeclarationStatus {
return declarationsTransformer.transformDeclarationStatus(declarationStatus, data)
}
override fun transformEnumEntry(enumEntry: FirEnumEntry, data: ResolutionMode): FirEnumEntry {
return declarationsTransformer.transformEnumEntry(enumEntry, data)
}
override fun transformProperty(property: FirProperty, data: ResolutionMode): FirProperty {
return declarationsTransformer.transformProperty(property, data)
}
override fun transformPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: ResolutionMode): FirStatement {
return declarationsTransformer.transformPropertyAccessor(propertyAccessor, data)
}
override fun transformBackingField(
backingField: FirBackingField,
data: ResolutionMode
): FirStatement {
return declarationsTransformer.transformBackingField(backingField, data)
}
override fun transformField(field: FirField, data: ResolutionMode): FirField {
return declarationsTransformer.transformField(field, data)
}
override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): FirStatement {
return declarationsTransformer.transformRegularClass(regularClass, data)
}
override fun transformAnonymousObject(
anonymousObject: FirAnonymousObject,
data: ResolutionMode
): FirStatement {
return declarationsTransformer.transformAnonymousObject(anonymousObject, data)
}
override fun transformAnonymousObjectExpression(
anonymousObjectExpression: FirAnonymousObjectExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformAnonymousObjectExpression(anonymousObjectExpression, data)
}
override fun transformSimpleFunction(
simpleFunction: FirSimpleFunction,
data: ResolutionMode
): FirSimpleFunction {
return declarationsTransformer.transformSimpleFunction(simpleFunction, data)
}
override fun transformFunction(
function: FirFunction,
data: ResolutionMode
): FirStatement {
return declarationsTransformer.transformFunction(function, data)
}
override fun transformConstructor(constructor: FirConstructor, data: ResolutionMode): FirConstructor {
return declarationsTransformer.transformConstructor(constructor, data)
}
override fun transformAnonymousInitializer(
anonymousInitializer: FirAnonymousInitializer,
data: ResolutionMode
): FirAnonymousInitializer {
return declarationsTransformer.transformAnonymousInitializer(anonymousInitializer, data)
}
override fun transformAnonymousFunction(
anonymousFunction: FirAnonymousFunction,
data: ResolutionMode
): FirStatement {
return declarationsTransformer.transformAnonymousFunction(anonymousFunction, data)
}
override fun transformAnonymousFunctionExpression(
anonymousFunctionExpression: FirAnonymousFunctionExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformAnonymousFunctionExpression(anonymousFunctionExpression, data)
}
override fun transformValueParameter(valueParameter: FirValueParameter, data: ResolutionMode): FirStatement {
return declarationsTransformer.transformValueParameter(valueParameter, data)
}
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: ResolutionMode): FirTypeAlias {
return declarationsTransformer.transformTypeAlias(typeAlias, data)
}
// ------------------------------------- Control flow statements -------------------------------------
override fun transformWhileLoop(whileLoop: FirWhileLoop, data: ResolutionMode): FirStatement {
return controlFlowStatementsTransformer.transformWhileLoop(whileLoop, data)
}
override fun transformDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: ResolutionMode): FirStatement {
return controlFlowStatementsTransformer.transformDoWhileLoop(doWhileLoop, data)
}
override fun transformWhenExpression(whenExpression: FirWhenExpression, data: ResolutionMode): FirStatement {
return controlFlowStatementsTransformer.transformWhenExpression(whenExpression, data)
}
override fun transformWhenBranch(whenBranch: FirWhenBranch, data: ResolutionMode): FirWhenBranch {
return controlFlowStatementsTransformer.transformWhenBranch(whenBranch, data)
}
override fun transformWhenSubjectExpression(
whenSubjectExpression: FirWhenSubjectExpression,
data: ResolutionMode
): FirStatement {
return controlFlowStatementsTransformer.transformWhenSubjectExpression(whenSubjectExpression, data)
}
override fun transformTryExpression(tryExpression: FirTryExpression, data: ResolutionMode): FirStatement {
return controlFlowStatementsTransformer.transformTryExpression(tryExpression, data)
}
override fun transformCatch(catch: FirCatch, data: ResolutionMode): FirCatch {
return controlFlowStatementsTransformer.transformCatch(catch, data)
}
override fun <E : FirTargetElement> transformJump(jump: FirJump<E>, data: ResolutionMode): FirStatement {
return controlFlowStatementsTransformer.transformJump(jump, data)
}
override fun transformReturnExpression(
returnExpression: FirReturnExpression,
data: ResolutionMode
): FirStatement {
return controlFlowStatementsTransformer.transformReturnExpression(returnExpression, data)
}
override fun transformThrowExpression(
throwExpression: FirThrowExpression,
data: ResolutionMode
): FirStatement {
return controlFlowStatementsTransformer.transformThrowExpression(throwExpression, data)
}
override fun transformElvisExpression(
elvisExpression: FirElvisExpression,
data: ResolutionMode
): FirStatement {
return controlFlowStatementsTransformer.transformElvisExpression(elvisExpression, data)
}
// --------------------------------------------------------------------------
fun <D> FirElement.visitNoTransform(transformer: FirTransformer<D>, data: D) {
val result = this.transform<FirElement, D>(transformer, data)
require(result === this) { "become $result: `${result.render()}`, was ${this}: `${this.render()}`" }
}
}
@@ -5,425 +5,32 @@
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.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
import org.jetbrains.kotlin.fir.resolve.createCurrentScopeList
import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowAnalyzerContext
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptor
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve
import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirTransformer
open class FirBodyResolveTransformer(
session: FirSession,
phase: FirResolvePhase,
override var implicitTypeOnly: Boolean,
implicitTypeOnly: Boolean,
scopeSession: ScopeSession,
val returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve,
returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve,
outerBodyResolveContext: BodyResolveContext? = null,
val firTowerDataContextCollector: FirTowerDataContextCollector? = null,
val firProviderInterceptor: FirProviderInterceptor? = null,
) : FirAbstractBodyResolveTransformer(phase) {
final override val context: BodyResolveContext =
outerBodyResolveContext ?: BodyResolveContext(returnTypeCalculator, DataFlowAnalyzerContext.empty(session))
final override val components: BodyResolveTransformerComponents =
BodyResolveTransformerComponents(session, scopeSession, this, context)
final override val resolutionContext: ResolutionContext = ResolutionContext(session, components, context)
internal open val expressionsTransformer = FirExpressionsResolveTransformer(this)
protected open val declarationsTransformer = FirDeclarationsResolveTransformer(this)
private val controlFlowStatementsTransformer = FirControlFlowStatementsResolveTransformer(this)
override fun transformFile(file: FirFile, data: ResolutionMode): FirFile {
checkSessionConsistency(file)
return context.withFile(file, components) {
firTowerDataContextCollector?.addFileContext(file, context.towerDataContext)
@Suppress("UNCHECKED_CAST")
transformDeclarationContent(file, data) as FirFile
}
}
override fun <E : FirElement> transformElement(element: E, data: ResolutionMode): E {
@Suppress("UNCHECKED_CAST")
return (element.transformChildren(this, data) as E)
}
override fun transformTypeRef(typeRef: FirTypeRef, data: ResolutionMode): FirResolvedTypeRef {
val resolvedTypeRef = if (typeRef is FirResolvedTypeRef) {
typeRef
} else {
typeResolverTransformer.withFile(context.file) {
transformTypeRef(
typeRef,
ScopeClassDeclaration(
components.createCurrentScopeList(),
context.containingClassDeclarations,
context.containers.lastOrNull { it is FirTypeParameterRefsOwner && it !is FirAnonymousFunction }
)
)
}
}
resolvedTypeRef.coneType.forEachType {
it.type.attributes.customAnnotations.forEach { typeArgumentAnnotation ->
typeArgumentAnnotation.accept(this, data)
}
}
return resolvedTypeRef.transformAnnotations(this, data)
}
override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: ResolutionMode): FirTypeRef {
if (data !is ResolutionMode.WithExpectedType)
return implicitTypeRef
return data.expectedTypeRef
}
// ------------------------------------- Expressions -------------------------------------
override fun transformExpression(expression: FirExpression, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformExpression(expression, data)
}
override fun transformWrappedArgumentExpression(
wrappedArgumentExpression: FirWrappedArgumentExpression,
data: ResolutionMode
): FirStatement {
return transformElement(wrappedArgumentExpression, data)
}
override fun transformQualifiedAccessExpression(
qualifiedAccessExpression: FirQualifiedAccessExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformQualifiedAccessExpression(qualifiedAccessExpression, data)
}
override fun transformPropertyAccessExpression(
propertyAccessExpression: FirPropertyAccessExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformQualifiedAccessExpression(propertyAccessExpression, data)
}
override fun transformFunctionCall(functionCall: FirFunctionCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformFunctionCall(functionCall, data)
}
override fun transformStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformStringConcatenationCall(stringConcatenationCall, data)
}
override fun transformCallableReferenceAccess(
callableReferenceAccess: FirCallableReferenceAccess,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformCallableReferenceAccess(callableReferenceAccess, data)
}
override fun transformBlock(block: FirBlock, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformBlock(block, data)
}
override fun transformThisReceiverExpression(
thisReceiverExpression: FirThisReceiverExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformThisReceiverExpression(thisReceiverExpression, data)
}
override fun transformComparisonExpression(
comparisonExpression: FirComparisonExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformComparisonExpression(comparisonExpression, data)
}
override fun transformTypeOperatorCall(
typeOperatorCall: FirTypeOperatorCall,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformTypeOperatorCall(typeOperatorCall, data)
}
override fun transformAssignmentOperatorStatement(
assignmentOperatorStatement: FirAssignmentOperatorStatement,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformAssignmentOperatorStatement(assignmentOperatorStatement, data)
}
override fun transformEqualityOperatorCall(
equalityOperatorCall: FirEqualityOperatorCall,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformEqualityOperatorCall(equalityOperatorCall, data)
}
override fun transformCheckNotNullCall(
checkNotNullCall: FirCheckNotNullCall,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformCheckNotNullCall(checkNotNullCall, data)
}
override fun transformBinaryLogicExpression(
binaryLogicExpression: FirBinaryLogicExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformBinaryLogicExpression(binaryLogicExpression, data)
}
override fun transformVariableAssignment(
variableAssignment: FirVariableAssignment,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformVariableAssignment(variableAssignment, data)
}
override fun transformGetClassCall(getClassCall: FirGetClassCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformGetClassCall(getClassCall, data)
}
override fun transformWrappedDelegateExpression(
wrappedDelegateExpression: FirWrappedDelegateExpression,
data: ResolutionMode
): FirStatement {
return declarationsTransformer.transformWrappedDelegateExpression(wrappedDelegateExpression, data)
}
override fun <T> transformConstExpression(
constExpression: FirConstExpression<T>,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformConstExpression(constExpression, data)
}
override fun transformAnnotation(annotation: FirAnnotation, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformAnnotation(annotation, data)
}
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformAnnotationCall(annotationCall, data)
}
override fun transformErrorAnnotationCall(errorAnnotationCall: FirErrorAnnotationCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformErrorAnnotationCall(errorAnnotationCall, data)
}
override fun transformDelegatedConstructorCall(
delegatedConstructorCall: FirDelegatedConstructorCall,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformDelegatedConstructorCall(delegatedConstructorCall, data)
}
override fun transformAugmentedArraySetCall(
augmentedArraySetCall: FirAugmentedArraySetCall,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformAugmentedArraySetCall(augmentedArraySetCall, data)
}
override fun transformSafeCallExpression(
safeCallExpression: FirSafeCallExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformSafeCallExpression(safeCallExpression, data)
}
override fun transformCheckedSafeCallSubject(
checkedSafeCallSubject: FirCheckedSafeCallSubject,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformCheckedSafeCallSubject(checkedSafeCallSubject, data)
}
override fun transformArrayOfCall(arrayOfCall: FirArrayOfCall, data: ResolutionMode): FirStatement {
return expressionsTransformer.transformArrayOfCall(arrayOfCall, data)
}
// ------------------------------------- Declarations -------------------------------------
override fun transformDeclaration(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration {
return declarationsTransformer.transformDeclaration(declaration, data)
}
open fun transformDeclarationContent(
declaration: FirDeclaration, data: ResolutionMode
): FirDeclaration {
return transformElement(declaration, data)
}
override fun transformDeclarationStatus(
declarationStatus: FirDeclarationStatus,
data: ResolutionMode
): FirDeclarationStatus {
return declarationsTransformer.transformDeclarationStatus(declarationStatus, data)
}
override fun transformEnumEntry(enumEntry: FirEnumEntry, data: ResolutionMode): FirEnumEntry {
return declarationsTransformer.transformEnumEntry(enumEntry, data)
}
override fun transformProperty(property: FirProperty, data: ResolutionMode): FirProperty {
return declarationsTransformer.transformProperty(property, data)
}
override fun transformPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: ResolutionMode): FirStatement {
return declarationsTransformer.transformPropertyAccessor(propertyAccessor, data)
}
override fun transformBackingField(
backingField: FirBackingField,
data: ResolutionMode
): FirStatement {
return declarationsTransformer.transformBackingField(backingField, data)
}
override fun transformField(field: FirField, data: ResolutionMode): FirField {
return declarationsTransformer.transformField(field, data)
}
override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): FirStatement {
return declarationsTransformer.transformRegularClass(regularClass, data)
}
override fun transformAnonymousObject(
anonymousObject: FirAnonymousObject,
data: ResolutionMode
): FirStatement {
return declarationsTransformer.transformAnonymousObject(anonymousObject, data)
}
override fun transformAnonymousObjectExpression(
anonymousObjectExpression: FirAnonymousObjectExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformAnonymousObjectExpression(anonymousObjectExpression, data)
}
override fun transformSimpleFunction(
simpleFunction: FirSimpleFunction,
data: ResolutionMode
): FirSimpleFunction {
return declarationsTransformer.transformSimpleFunction(simpleFunction, data)
}
override fun transformFunction(
function: FirFunction,
data: ResolutionMode
): FirStatement {
return declarationsTransformer.transformFunction(function, data)
}
override fun transformConstructor(constructor: FirConstructor, data: ResolutionMode): FirConstructor {
return declarationsTransformer.transformConstructor(constructor, data)
}
override fun transformAnonymousInitializer(
anonymousInitializer: FirAnonymousInitializer,
data: ResolutionMode
): FirAnonymousInitializer {
return declarationsTransformer.transformAnonymousInitializer(anonymousInitializer, data)
}
override fun transformAnonymousFunction(
anonymousFunction: FirAnonymousFunction,
data: ResolutionMode
): FirStatement {
return declarationsTransformer.transformAnonymousFunction(anonymousFunction, data)
}
override fun transformAnonymousFunctionExpression(
anonymousFunctionExpression: FirAnonymousFunctionExpression,
data: ResolutionMode
): FirStatement {
return expressionsTransformer.transformAnonymousFunctionExpression(anonymousFunctionExpression, data)
}
override fun transformValueParameter(valueParameter: FirValueParameter, data: ResolutionMode): FirStatement {
return declarationsTransformer.transformValueParameter(valueParameter, data)
}
override fun transformTypeAlias(typeAlias: FirTypeAlias, data: ResolutionMode): FirTypeAlias {
return declarationsTransformer.transformTypeAlias(typeAlias, data)
}
// ------------------------------------- Control flow statements -------------------------------------
override fun transformWhileLoop(whileLoop: FirWhileLoop, data: ResolutionMode): FirStatement {
return controlFlowStatementsTransformer.transformWhileLoop(whileLoop, data)
}
override fun transformDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: ResolutionMode): FirStatement {
return controlFlowStatementsTransformer.transformDoWhileLoop(doWhileLoop, data)
}
override fun transformWhenExpression(whenExpression: FirWhenExpression, data: ResolutionMode): FirStatement {
return controlFlowStatementsTransformer.transformWhenExpression(whenExpression, data)
}
override fun transformWhenBranch(whenBranch: FirWhenBranch, data: ResolutionMode): FirWhenBranch {
return controlFlowStatementsTransformer.transformWhenBranch(whenBranch, data)
}
override fun transformWhenSubjectExpression(
whenSubjectExpression: FirWhenSubjectExpression,
data: ResolutionMode
): FirStatement {
return controlFlowStatementsTransformer.transformWhenSubjectExpression(whenSubjectExpression, data)
}
override fun transformTryExpression(tryExpression: FirTryExpression, data: ResolutionMode): FirStatement {
return controlFlowStatementsTransformer.transformTryExpression(tryExpression, data)
}
override fun transformCatch(catch: FirCatch, data: ResolutionMode): FirCatch {
return controlFlowStatementsTransformer.transformCatch(catch, data)
}
override fun <E : FirTargetElement> transformJump(jump: FirJump<E>, data: ResolutionMode): FirStatement {
return controlFlowStatementsTransformer.transformJump(jump, data)
}
override fun transformReturnExpression(
returnExpression: FirReturnExpression,
data: ResolutionMode
): FirStatement {
return controlFlowStatementsTransformer.transformReturnExpression(returnExpression, data)
}
override fun transformThrowExpression(
throwExpression: FirThrowExpression,
data: ResolutionMode
): FirStatement {
return controlFlowStatementsTransformer.transformThrowExpression(throwExpression, data)
}
override fun transformElvisExpression(
elvisExpression: FirElvisExpression,
data: ResolutionMode
): FirStatement {
return controlFlowStatementsTransformer.transformElvisExpression(elvisExpression, data)
}
// --------------------------------------------------------------------------
fun <D> FirElement.visitNoTransform(transformer: FirTransformer<D>, data: D) {
val result = this.transform<FirElement, D>(transformer, data)
require(result === this) { "become $result: `${result.render()}`, was ${this}: `${this.render()}`" }
}
firTowerDataContextCollector: FirTowerDataContextCollector? = null,
firProviderInterceptor: FirProviderInterceptor? = null,
) : FirAbstractBodyResolveTransformerDispatcher(
session,
phase,
implicitTypeOnly,
scopeSession,
returnTypeCalculator,
outerBodyResolveContext,
firTowerDataContextCollector,
firProviderInterceptor,
) {
final override val expressionsTransformer = FirExpressionsResolveTransformer(this)
final override val declarationsTransformer = FirDeclarationsResolveTransformer(this)
}
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.visitors.transformSingle
class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTransformer) :
class FirControlFlowStatementsResolveTransformer(transformer: FirAbstractBodyResolveTransformerDispatcher) :
FirPartialBodyResolveTransformer(transformer) {
private val syntheticCallGenerator: FirSyntheticCallGenerator get() = components.syntheticCallGenerator
@@ -51,7 +51,7 @@ import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.name.Name
open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolveTransformerDispatcher) : FirPartialBodyResolveTransformer(transformer) {
private val statusResolver: FirStatusResolver = FirStatusResolver(session, scopeSession)
private fun FirDeclaration.visibilityForApproximation(): Visibility {
@@ -53,7 +53,7 @@ import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.util.OperatorNameConventions
open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) : FirPartialBodyResolveTransformer(transformer) {
open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveTransformerDispatcher) : FirPartialBodyResolveTransformer(transformer) {
private inline val builtinTypes: BuiltinTypes get() = session.builtinTypes
private val arrayOfCallTransformer = FirArrayOfCallTransformer()
var enableArrayOfCallTransformation = false
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
abstract class FirPartialBodyResolveTransformer(
val transformer: FirBodyResolveTransformer
val transformer: FirAbstractBodyResolveTransformerDispatcher
) : FirAbstractBodyResolveTransformer(transformer.transformerPhase) {
@Suppress("OVERRIDE_BY_INLINE")
final override inline val context: BodyResolveContext
@@ -0,0 +1,286 @@
/*
* Copyright 2010-2022 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.contracts
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
import org.jetbrains.kotlin.fir.contracts.FirRawContractDescription
import org.jetbrains.kotlin.fir.contracts.builder.buildLegacyRawContractDescription
import org.jetbrains.kotlin.fir.contracts.builder.buildResolvedContractDescription
import org.jetbrains.kotlin.fir.contracts.description.ConeEffectDeclaration
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.contracts.toFirEffectDeclaration
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.errorTypeFromPrototype
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeContractDescriptionError
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.name.Name
abstract class FirAbstractContractResolveTransformerDispatcher(
session: FirSession,
scopeSession: ScopeSession,
outerBodyResolveContext: BodyResolveContext? = null
) : FirAbstractBodyResolveTransformerDispatcher(
session,
FirResolvePhase.CONTRACTS,
implicitTypeOnly = false,
scopeSession,
outerBodyResolveContext = outerBodyResolveContext
) {
final override val expressionsTransformer: FirExpressionsResolveTransformer =
FirExpressionsResolveTransformer(this)
override fun transformAnnotation(annotation: FirAnnotation, data: ResolutionMode): FirStatement {
return annotation
}
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: ResolutionMode): FirStatement {
return annotationCall
}
protected open class FirDeclarationsContractResolveTransformer(
transformer: FirAbstractBodyResolveTransformerDispatcher
) : FirDeclarationsResolveTransformer(transformer) {
override fun transformSimpleFunction(
simpleFunction: FirSimpleFunction,
data: ResolutionMode
): FirSimpleFunction {
if (!simpleFunction.hasContractToResolve) {
return simpleFunction
}
val containingDeclaration = context.containerIfAny
if (containingDeclaration != null && containingDeclaration !is FirClass) {
simpleFunction.replaceReturnTypeRef(
simpleFunction.returnTypeRef.errorTypeFromPrototype(
ConeContractDescriptionError("Local function can not be used in contract description")
)
)
return simpleFunction
}
@Suppress("UNCHECKED_CAST")
return context.withSimpleFunction(simpleFunction, session) {
context.forFunctionBody(simpleFunction, components) {
transformContractDescriptionOwner(simpleFunction)
}
}
}
override fun transformProperty(property: FirProperty, data: ResolutionMode): FirProperty {
if (
property.getter?.hasContractToResolve != true && property.setter?.hasContractToResolve != true ||
property.isLocal || property.delegate != null
) {
return property
}
if (property is FirSyntheticProperty) {
transformSimpleFunction(property.getter.delegate, data)
return property
}
context.withProperty(property) {
property.getter?.let { transformPropertyAccessor(it, property) }
property.setter?.let { transformPropertyAccessor(it, property) }
}
return property
}
override fun transformField(field: FirField, data: ResolutionMode): FirField {
return field
}
private fun transformPropertyAccessor(
propertyAccessor: FirPropertyAccessor,
owner: FirProperty
): FirStatement {
if (!propertyAccessor.hasContractToResolve) {
return propertyAccessor
}
return context.withPropertyAccessor(owner, propertyAccessor, components, forContracts = true) {
transformContractDescriptionOwner(propertyAccessor)
}
}
private fun <T : FirContractDescriptionOwner> transformContractDescriptionOwner(
owner: T
): T {
dataFlowAnalyzer.enterContractDescription()
return when (val contractDescription = owner.contractDescription) {
is FirLegacyRawContractDescription -> transformLegacyRawContractDescriptionOwner(owner, contractDescription)
is FirRawContractDescription -> transformRawContractDescriptionOwner(owner, contractDescription)
else -> throw IllegalArgumentException("$owner has a contract description of an unknown type")
}
}
private fun <T : FirContractDescriptionOwner> transformLegacyRawContractDescriptionOwner(
owner: T,
contractDescription: FirLegacyRawContractDescription
): T {
val valueParameters = owner.valueParameters
for (valueParameter in valueParameters) {
context.storeVariable(valueParameter, session)
}
val contractCall = contractDescription.contractCall.transformSingle(transformer, ResolutionMode.ContextIndependent)
val resolvedId = contractCall.toResolvedCallableSymbol()?.callableId ?: return transformOwnerWithUnresolvedContract(owner)
if (resolvedId != FirContractsDslNames.CONTRACT) return transformOwnerWithUnresolvedContract(owner)
if (contractCall.arguments.size != 1) return transformOwnerOfErrorContract(owner)
val argument = contractCall.argument as? FirLambdaArgumentExpression ?: return transformOwnerOfErrorContract(owner)
val lambdaBody = (argument.expression as FirAnonymousFunctionExpression).anonymousFunction.body
?: return transformOwnerOfErrorContract(owner)
val resolvedContractDescription = buildResolvedContractDescription {
val effectExtractor = ConeEffectExtractor(session, owner, valueParameters)
for (statement in lambdaBody.statements) {
val effect = statement.accept(effectExtractor, null) as? ConeEffectDeclaration
if (effect == null) {
unresolvedEffects += statement
} else {
effects += effect.toFirEffectDeclaration(statement.source)
}
}
this.source = owner.contractDescription.source
}
owner.replaceContractDescription(resolvedContractDescription)
dataFlowAnalyzer.exitContractDescription()
return owner
}
private fun <T : FirContractDescriptionOwner> transformRawContractDescriptionOwner(
owner: T,
contractDescription: FirRawContractDescription
): T {
val effectsBlock = buildAnonymousFunction {
moduleData = session.moduleData
origin = FirDeclarationOrigin.Source
returnTypeRef = buildImplicitTypeRef()
receiverTypeRef = buildImplicitTypeRef()
symbol = FirAnonymousFunctionSymbol()
isLambda = true
hasExplicitParameterList = true
body = buildBlock {
contractDescription.rawEffects.forEach {
statements += it
}
}
}
val lambdaArgument = buildLambdaArgumentExpression {
expression = buildAnonymousFunctionExpression {
anonymousFunction = effectsBlock
}
}
val contractCall = buildFunctionCall {
calleeReference = buildSimpleNamedReference {
name = Name.identifier("contract")
}
argumentList = buildArgumentList {
arguments += lambdaArgument
}
}
val legacyRawContractDescription = buildLegacyRawContractDescription {
this.contractCall = contractCall
}
owner.replaceContractDescription(legacyRawContractDescription)
return transformLegacyRawContractDescriptionOwner(owner, legacyRawContractDescription)
}
private fun <T : FirContractDescriptionOwner> transformOwnerWithUnresolvedContract(owner: T): T {
return when (val contractDescription = owner.contractDescription) {
is FirLegacyRawContractDescription -> { // old syntax contract description
val functionCall = contractDescription.contractCall
owner.replaceContractDescription(FirEmptyContractDescription)
owner.body.replaceFirstStatement(functionCall)
dataFlowAnalyzer.exitContractDescription()
owner
}
is FirRawContractDescription -> { // new syntax contract description
owner.replaceContractDescription(FirEmptyContractDescription)
dataFlowAnalyzer.exitContractDescription()
owner
}
else -> owner // TODO: change
}
}
open fun transformDeclarationContent(firClass: FirClass, data: ResolutionMode) {
firClass.transformDeclarations(this, data)
}
override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): FirStatement {
context.withRegularClass(regularClass, components, forContracts = true) {
transformDeclarationContent(regularClass, data)
}
return regularClass
}
override fun transformAnonymousObject(
anonymousObject: FirAnonymousObject,
data: ResolutionMode
): FirStatement {
context.withAnonymousObject(anonymousObject, components) {
transformDeclarationContent(anonymousObject, data)
}
return anonymousObject
}
override fun transformAnonymousInitializer(
anonymousInitializer: FirAnonymousInitializer,
data: ResolutionMode
): FirAnonymousInitializer {
return anonymousInitializer
}
override fun transformConstructor(constructor: FirConstructor, data: ResolutionMode): FirConstructor {
return constructor
}
override fun transformEnumEntry(enumEntry: FirEnumEntry, data: ResolutionMode): FirEnumEntry {
return enumEntry
}
private fun <T : FirContractDescriptionOwner> transformOwnerOfErrorContract(owner: T): T {
// TODO
dataFlowAnalyzer.exitContractDescription()
return owner
}
private val FirContractDescriptionOwner.hasContractToResolve: Boolean
get() = contractDescription is FirLegacyRawContractDescription || contractDescription is FirRawContractDescription
}
}
private val FirContractDescriptionOwner.valueParameters: List<FirValueParameter>
get() = when (this) {
is FirSimpleFunction -> valueParameters
is FirPropertyAccessor -> valueParameters
else -> error()
}
private val FirContractDescriptionOwner.body: FirBlock
get() = when (this) {
is FirSimpleFunction -> body!!
is FirPropertyAccessor -> body!!
else -> error()
}
private fun FirContractDescriptionOwner.error(): Nothing = throw IllegalStateException("${this::class} can not be a contract owner")
@@ -6,277 +6,18 @@
package org.jetbrains.kotlin.fir.resolve.transformers.contracts
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
import org.jetbrains.kotlin.fir.contracts.FirRawContractDescription
import org.jetbrains.kotlin.fir.contracts.builder.buildLegacyRawContractDescription
import org.jetbrains.kotlin.fir.contracts.builder.buildResolvedContractDescription
import org.jetbrains.kotlin.fir.contracts.description.ConeEffectDeclaration
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.contracts.toFirEffectDeclaration
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.errorTypeFromPrototype
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeContractDescriptionError
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.*
open class FirContractResolveTransformer(
session: FirSession,
scopeSession: ScopeSession,
outerBodyResolveContext: BodyResolveContext? = null
) : FirBodyResolveTransformer(
) : FirAbstractContractResolveTransformerDispatcher(
session,
FirResolvePhase.CONTRACTS,
implicitTypeOnly = false,
scopeSession,
outerBodyResolveContext = outerBodyResolveContext
outerBodyResolveContext,
) {
override val declarationsTransformer: FirDeclarationsResolveTransformer = FirDeclarationsContractResolveTransformer(this)
override fun transformAnnotation(annotation: FirAnnotation, data: ResolutionMode): FirStatement {
return annotation
}
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: ResolutionMode): FirStatement {
return annotationCall
}
protected open class FirDeclarationsContractResolveTransformer(transformer: FirBodyResolveTransformer) : FirDeclarationsResolveTransformer(transformer) {
override fun transformSimpleFunction(
simpleFunction: FirSimpleFunction,
data: ResolutionMode
): FirSimpleFunction {
if (!simpleFunction.hasContractToResolve) {
return simpleFunction
}
val containingDeclaration = context.containerIfAny
if (containingDeclaration != null && containingDeclaration !is FirClass) {
simpleFunction.replaceReturnTypeRef(
simpleFunction.returnTypeRef.errorTypeFromPrototype(
ConeContractDescriptionError("Local function can not be used in contract description")
)
)
return simpleFunction
}
@Suppress("UNCHECKED_CAST")
return context.withSimpleFunction(simpleFunction, session) {
context.forFunctionBody(simpleFunction, components) {
transformContractDescriptionOwner(simpleFunction)
}
}
}
override fun transformProperty(property: FirProperty, data: ResolutionMode): FirProperty {
if (
property.getter?.hasContractToResolve != true && property.setter?.hasContractToResolve != true ||
property.isLocal || property.delegate != null
) {
return property
}
if (property is FirSyntheticProperty) {
transformSimpleFunction(property.getter.delegate, data)
return property
}
context.withProperty(property) {
property.getter?.let { transformPropertyAccessor(it, property) }
property.setter?.let { transformPropertyAccessor(it, property) }
}
return property
}
override fun transformField(field: FirField, data: ResolutionMode): FirField {
return field
}
private fun transformPropertyAccessor(
propertyAccessor: FirPropertyAccessor,
owner: FirProperty
): FirStatement {
if (!propertyAccessor.hasContractToResolve) {
return propertyAccessor
}
return context.withPropertyAccessor(owner, propertyAccessor, components, forContracts = true) {
transformContractDescriptionOwner(propertyAccessor)
}
}
private fun <T : FirContractDescriptionOwner> transformContractDescriptionOwner(
owner: T
): T {
dataFlowAnalyzer.enterContractDescription()
return when (val contractDescription = owner.contractDescription) {
is FirLegacyRawContractDescription -> transformLegacyRawContractDescriptionOwner(owner, contractDescription)
is FirRawContractDescription -> transformRawContractDescriptionOwner(owner, contractDescription)
else -> throw IllegalArgumentException("$owner has a contract description of an unknown type")
}
}
private fun <T : FirContractDescriptionOwner> transformLegacyRawContractDescriptionOwner(
owner: T,
contractDescription: FirLegacyRawContractDescription
): T {
val valueParameters = owner.valueParameters
for (valueParameter in valueParameters) {
context.storeVariable(valueParameter, session)
}
val contractCall = contractDescription.contractCall.transformSingle(transformer, ResolutionMode.ContextIndependent)
val resolvedId = contractCall.toResolvedCallableSymbol()?.callableId ?: return transformOwnerWithUnresolvedContract(owner)
if (resolvedId != FirContractsDslNames.CONTRACT) return transformOwnerWithUnresolvedContract(owner)
if (contractCall.arguments.size != 1) return transformOwnerOfErrorContract(owner)
val argument = contractCall.argument as? FirLambdaArgumentExpression ?: return transformOwnerOfErrorContract(owner)
val lambdaBody = (argument.expression as FirAnonymousFunctionExpression).anonymousFunction.body
?: return transformOwnerOfErrorContract(owner)
val resolvedContractDescription = buildResolvedContractDescription {
val effectExtractor = ConeEffectExtractor(session, owner, valueParameters)
for (statement in lambdaBody.statements) {
val effect = statement.accept(effectExtractor, null) as? ConeEffectDeclaration
if (effect == null) {
unresolvedEffects += statement
} else {
effects += effect.toFirEffectDeclaration(statement.source)
}
}
this.source = owner.contractDescription.source
}
owner.replaceContractDescription(resolvedContractDescription)
dataFlowAnalyzer.exitContractDescription()
return owner
}
private fun <T : FirContractDescriptionOwner> transformRawContractDescriptionOwner(
owner: T,
contractDescription: FirRawContractDescription
): T {
val effectsBlock = buildAnonymousFunction {
moduleData = session.moduleData
origin = FirDeclarationOrigin.Source
returnTypeRef = buildImplicitTypeRef()
receiverTypeRef = buildImplicitTypeRef()
symbol = FirAnonymousFunctionSymbol()
isLambda = true
hasExplicitParameterList = true
body = buildBlock {
contractDescription.rawEffects.forEach {
statements += it
}
}
}
val lambdaArgument = buildLambdaArgumentExpression {
expression = buildAnonymousFunctionExpression {
anonymousFunction = effectsBlock
}
}
val contractCall = buildFunctionCall {
calleeReference = buildSimpleNamedReference {
name = Name.identifier("contract")
}
argumentList = buildArgumentList {
arguments += lambdaArgument
}
}
val legacyRawContractDescription = buildLegacyRawContractDescription {
this.contractCall = contractCall
}
owner.replaceContractDescription(legacyRawContractDescription)
return transformLegacyRawContractDescriptionOwner(owner, legacyRawContractDescription)
}
private fun <T : FirContractDescriptionOwner> transformOwnerWithUnresolvedContract(owner: T): T {
return when (val contractDescription = owner.contractDescription) {
is FirLegacyRawContractDescription -> { // old syntax contract description
val functionCall = contractDescription.contractCall
owner.replaceContractDescription(FirEmptyContractDescription)
owner.body.replaceFirstStatement(functionCall)
dataFlowAnalyzer.exitContractDescription()
owner
}
is FirRawContractDescription -> { // new syntax contract description
owner.replaceContractDescription(FirEmptyContractDescription)
dataFlowAnalyzer.exitContractDescription()
owner
}
else -> owner // TODO: change
}
}
open fun transformDeclarationContent(firClass: FirClass, data: ResolutionMode) {
firClass.transformDeclarations(this, data)
}
override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): FirStatement {
context.withRegularClass(regularClass, components, forContracts = true) {
transformDeclarationContent(regularClass, data)
}
return regularClass
}
override fun transformAnonymousObject(
anonymousObject: FirAnonymousObject,
data: ResolutionMode
): FirStatement {
context.withAnonymousObject(anonymousObject, components) {
transformDeclarationContent(anonymousObject, data)
}
return anonymousObject
}
override fun transformAnonymousInitializer(
anonymousInitializer: FirAnonymousInitializer,
data: ResolutionMode
): FirAnonymousInitializer {
return anonymousInitializer
}
override fun transformConstructor(constructor: FirConstructor, data: ResolutionMode): FirConstructor {
return constructor
}
override fun transformEnumEntry(enumEntry: FirEnumEntry, data: ResolutionMode): FirEnumEntry {
return enumEntry
}
private fun <T : FirContractDescriptionOwner> transformOwnerOfErrorContract(owner: T): T {
// TODO
dataFlowAnalyzer.exitContractDescription()
return owner
}
private val FirContractDescriptionOwner.hasContractToResolve: Boolean
get() = contractDescription is FirLegacyRawContractDescription || contractDescription is FirRawContractDescription
}
final override val declarationsTransformer: FirDeclarationsResolveTransformer =
FirDeclarationsContractResolveTransformer(this)
}
private val FirContractDescriptionOwner.valueParameters: List<FirValueParameter>
get() = when (this) {
is FirSimpleFunction -> valueParameters
is FirPropertyAccessor -> valueParameters
else -> error()
}
private val FirContractDescriptionOwner.body: FirBlock
get() = when (this) {
is FirSimpleFunction -> body!!
is FirPropertyAccessor -> body!!
else -> error()
}
private fun FirContractDescriptionOwner.error(): Nothing = throw IllegalStateException("${this::class} can not be a contract owner")
@@ -10,28 +10,29 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.*
open class FirAnnotationArgumentsMappingTransformer(
session: FirSession,
scopeSession: ScopeSession,
resolvePhase: FirResolvePhase,
outerBodyResolveContext: BodyResolveContext? = null
) : FirBodyResolveTransformer(
) : FirAbstractBodyResolveTransformerDispatcher(
session,
resolvePhase,
implicitTypeOnly = false,
scopeSession,
outerBodyResolveContext = outerBodyResolveContext
) {
override val declarationsTransformer: FirDeclarationsResolveTransformer =
final override val expressionsTransformer: FirExpressionsResolveTransformer =
FirExpressionsResolveTransformer(this)
final override val declarationsTransformer: FirDeclarationsResolveTransformer =
FirDeclarationsResolveTransformerForAnnotationArgumentsMapping(this)
}
private class FirDeclarationsResolveTransformerForAnnotationArgumentsMapping(
transformer: FirBodyResolveTransformer
transformer: FirAbstractBodyResolveTransformerDispatcher
) : FirDeclarationsResolveTransformer(transformer) {
override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): FirStatement {
regularClass.transformAnnotations(this, data)
@@ -11,30 +11,27 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.*
open class FirAnnotationArgumentsResolveTransformer(
session: FirSession,
scopeSession: ScopeSession,
resolvePhase: FirResolvePhase,
outerBodyResolveContext: BodyResolveContext? = null
) : FirBodyResolveTransformer(
) : FirAbstractBodyResolveTransformerDispatcher(
session,
resolvePhase,
implicitTypeOnly = false,
scopeSession,
outerBodyResolveContext = outerBodyResolveContext
) {
override val expressionsTransformer: FirExpressionsResolveTransformer = FirExpressionsResolveTransformerForSpecificAnnotations(this)
final override val expressionsTransformer: FirExpressionsResolveTransformer = FirExpressionsResolveTransformerForSpecificAnnotations(this)
override val declarationsTransformer: FirDeclarationsResolveTransformer = FirDeclarationsResolveTransformerForArgumentAnnotations(this)
final override val declarationsTransformer: FirDeclarationsResolveTransformer = FirDeclarationsResolveTransformerForArgumentAnnotations(this)
}
private class FirDeclarationsResolveTransformerForArgumentAnnotations(
transformer: FirBodyResolveTransformer
transformer: FirAbstractBodyResolveTransformerDispatcher
) : FirDeclarationsResolveTransformer(transformer) {
override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): FirStatement {
regularClass.transformAnnotations(this, data)
@@ -134,7 +131,7 @@ private class FirDeclarationsResolveTransformerForArgumentAnnotations(
}
private class FirExpressionsResolveTransformerForSpecificAnnotations(
transformer: FirBodyResolveTransformer
transformer: FirAbstractBodyResolveTransformerDispatcher
) : FirExpressionsResolveTransformer(transformer) {
override fun transformAnnotation(annotation: FirAnnotation, data: ResolutionMode): FirStatement {