[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.fir.*
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.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
@@ -225,7 +226,11 @@ class RawFirBuilder(
null to null
hasBlockBody() -> if (!stubMode) {
val block = bodyBlockExpression?.accept(this@Visitor, Unit) as? FirBlock
block.extractContractDescriptionIfPossible()
if (hasContractEffectList()) {
block to null
} else {
block.extractContractDescriptionIfPossible()
}
} else {
FirSingleExpressionBlock(buildExpressionStub { source = this@buildFirBody.toFirSourceElement() }.toReturn()) to null
}
@@ -331,8 +336,10 @@ class RawFirBuilder(
}
}
symbol = FirPropertyAccessorSymbol()
val (body, contractDescription) = this@toFirPropertyAccessor.buildFirBody()
this.body = body
val outerContractDescription = this@toFirPropertyAccessor.obtainContractDescription()
val bodyWithContractDescription = this@toFirPropertyAccessor.buildFirBody()
this.body = bodyWithContractDescription.first
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second
contractDescription?.let {
this.contractDescription = it
}
@@ -954,8 +961,10 @@ class RawFirBuilder(
}
withCapturedTypeParameters {
if (this is FirSimpleFunctionBuilder) addCapturedTypeParameters(this.typeParameters)
val (body, contractDescription) = function.buildFirBody()
this.body = body
val outerContractDescription = function.obtainContractDescription()
val bodyWithContractDescription = function.buildFirBody()
this.body = bodyWithContractDescription.first
val contractDescription = outerContractDescription ?: bodyWithContractDescription.second
contractDescription?.let {
// TODO: add error reporting for contracts on lambdas
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 {
val literal = expression.functionLiteral
val literalSource = literal.toFirSourceElement()
@@ -38,6 +38,10 @@ public interface KtDeclarationWithBody extends KtDeclaration {
return null;
}
default boolean hasContractEffectList() {
return getContractDescription() != null;
}
boolean hasBlockBody();
boolean hasBody();