[FIR] Add contract description blocks support to RawFirBuilder

This commit is contained in:
Arsen Nagdalian
2020-07-22 04:23:39 +03:00
parent d53f3b9ba8
commit 9fd104eec8
2 changed files with 33 additions and 5 deletions
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.contracts.FirContractDescription import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.contracts.builder.buildRawContractDescription
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.* import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
@@ -225,7 +226,11 @@ class RawFirBuilder(
null to null null to null
hasBlockBody() -> if (!stubMode) { hasBlockBody() -> if (!stubMode) {
val block = bodyBlockExpression?.accept(this@Visitor, Unit) as? FirBlock val block = bodyBlockExpression?.accept(this@Visitor, Unit) as? FirBlock
block.extractContractDescriptionIfPossible() if (hasContractEffectList()) {
block to null
} else {
block.extractContractDescriptionIfPossible()
}
} else { } else {
FirSingleExpressionBlock(buildExpressionStub { source = this@buildFirBody.toFirSourceElement() }.toReturn()) to null FirSingleExpressionBlock(buildExpressionStub { source = this@buildFirBody.toFirSourceElement() }.toReturn()) to null
} }
@@ -331,8 +336,10 @@ class RawFirBuilder(
} }
} }
symbol = FirPropertyAccessorSymbol() symbol = FirPropertyAccessorSymbol()
val (body, contractDescription) = this@toFirPropertyAccessor.buildFirBody() val outerContractDescription = this@toFirPropertyAccessor.obtainContractDescription()
this.body = body val bodyWithContractDescription = this@toFirPropertyAccessor.buildFirBody()
this.body = bodyWithContractDescription.first
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second
contractDescription?.let { contractDescription?.let {
this.contractDescription = it this.contractDescription = it
} }
@@ -954,8 +961,10 @@ class RawFirBuilder(
} }
withCapturedTypeParameters { withCapturedTypeParameters {
if (this is FirSimpleFunctionBuilder) addCapturedTypeParameters(this.typeParameters) if (this is FirSimpleFunctionBuilder) addCapturedTypeParameters(this.typeParameters)
val (body, contractDescription) = function.buildFirBody() val outerContractDescription = function.obtainContractDescription()
this.body = body val bodyWithContractDescription = function.buildFirBody()
this.body = bodyWithContractDescription.first
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second
contractDescription?.let { contractDescription?.let {
// TODO: add error reporting for contracts on lambdas // TODO: add error reporting for contracts on lambdas
if (this is FirSimpleFunctionBuilder) { if (this is FirSimpleFunctionBuilder) {
@@ -969,6 +978,21 @@ class RawFirBuilder(
} }
} }
private fun KtDeclarationWithBody.obtainContractDescription(): FirContractDescription? {
return when(val description = contractDescription) {
null -> null
else -> buildRawContractDescription {
source = description.toFirSourceElement()
description.extractRawEffects(rawEffects)
}
}
}
private fun KtContractEffectList.extractRawEffects(destination: MutableList<FirExpression>) {
getExpressions()
.mapTo(destination) { it.accept(this@Visitor, Unit) as FirExpression }
}
override fun visitLambdaExpression(expression: KtLambdaExpression, data: Unit): FirElement { override fun visitLambdaExpression(expression: KtLambdaExpression, data: Unit): FirElement {
val literal = expression.functionLiteral val literal = expression.functionLiteral
val literalSource = literal.toFirSourceElement() val literalSource = literal.toFirSourceElement()
@@ -38,6 +38,10 @@ public interface KtDeclarationWithBody extends KtDeclaration {
return null; return null;
} }
default boolean hasContractEffectList() {
return getContractDescription() != null;
}
boolean hasBlockBody(); boolean hasBlockBody();
boolean hasBody(); boolean hasBody();