[FIR] Add contract renderer
This commit is contained in:
+7
-3
@@ -125,16 +125,20 @@ class FirContractDeserializer(private val c: FirDeserializationContext) {
|
|||||||
|
|
||||||
val valueParameterIndex = proto.valueParameterReference - 1
|
val valueParameterIndex = proto.valueParameterReference - 1
|
||||||
|
|
||||||
|
val name: String
|
||||||
val typeRef = if (valueParameterIndex < 0) {
|
val typeRef = if (valueParameterIndex < 0) {
|
||||||
|
name = "this"
|
||||||
ownerFunction.receiverTypeRef
|
ownerFunction.receiverTypeRef
|
||||||
} else {
|
} else {
|
||||||
ownerFunction.valueParameters.getOrNull(valueParameterIndex)?.returnTypeRef
|
val parameter = ownerFunction.valueParameters.getOrNull(valueParameterIndex) ?: return null
|
||||||
|
name = parameter.name.asString()
|
||||||
|
parameter.returnTypeRef
|
||||||
} ?: return null
|
} ?: return null
|
||||||
|
|
||||||
return if (!typeRef.isBoolean)
|
return if (!typeRef.isBoolean)
|
||||||
ConeValueParameterReference(valueParameterIndex)
|
ConeValueParameterReference(valueParameterIndex, name)
|
||||||
else
|
else
|
||||||
ConeBooleanValueParameterReference(valueParameterIndex)
|
ConeBooleanValueParameterReference(valueParameterIndex, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ProtoBuf.Effect.InvocationKind.toDescriptorInvocationKind(): InvocationKind? = when (this) {
|
private fun ProtoBuf.Effect.InvocationKind.toDescriptorInvocationKind(): InvocationKind? = when (this) {
|
||||||
|
|||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.contracts.description
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.contracts.description.expressions.*
|
||||||
|
|
||||||
|
class ConeContractRenderer(private val builder: StringBuilder) : ConeContractDescriptionVisitor<Unit, Nothing?>() {
|
||||||
|
override fun visitConditionalEffectDeclaration(conditionalEffect: ConeConditionalEffectDeclaration, data: Nothing?) {
|
||||||
|
conditionalEffect.effect.accept(this, data)
|
||||||
|
builder.append(" -> ")
|
||||||
|
conditionalEffect.condition.accept(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitReturnsEffectDeclaration(returnsEffect: ConeReturnsEffectDeclaration, data: Nothing?) {
|
||||||
|
builder.append("Returns(")
|
||||||
|
returnsEffect.value.accept(this, data)
|
||||||
|
builder.append(")")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCallsEffectDeclaration(callsEffect: ConeCallsEffectDeclaration, data: Nothing?) {
|
||||||
|
builder.append("CallsInPlace(")
|
||||||
|
callsEffect.valueParameterReference.accept(this, data)
|
||||||
|
builder.append(", ${callsEffect.kind})")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitLogicalBinaryOperationContractExpression(binaryLogicExpression: ConeBinaryLogicExpression, data: Nothing?) {
|
||||||
|
inBracketsIfNecessary(binaryLogicExpression, binaryLogicExpression.left) { binaryLogicExpression.left.accept(this, data) }
|
||||||
|
builder.append(" ${binaryLogicExpression.kind.token} ")
|
||||||
|
inBracketsIfNecessary(binaryLogicExpression, binaryLogicExpression.right) { binaryLogicExpression.right.accept(this, data) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitLogicalNot(logicalNot: ConeLogicalNot, data: Nothing?) {
|
||||||
|
inBracketsIfNecessary(logicalNot, logicalNot.arg) { builder.append("!") }
|
||||||
|
logicalNot.arg.accept(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitIsInstancePredicate(isInstancePredicate: ConeIsInstancePredicate, data: Nothing?) {
|
||||||
|
isInstancePredicate.arg.accept(this, data)
|
||||||
|
builder.append(" ${if (isInstancePredicate.isNegated) "!" else ""}is ${isInstancePredicate.type}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitIsNullPredicate(isNullPredicate: ConeIsNullPredicate, data: Nothing?) {
|
||||||
|
isNullPredicate.arg.accept(this, data)
|
||||||
|
builder.append(" ${if (isNullPredicate.isNegated) "!=" else "=="} null")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitConstantDescriptor(constantReference: ConeConstantReference, data: Nothing?) {
|
||||||
|
builder.append(constantReference.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitValueParameterReference(valueParameterReference: ConeValueParameterReference, data: Nothing?) {
|
||||||
|
builder.append(valueParameterReference.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun inBracketsIfNecessary(parent: ConeContractDescriptionElement, child: ConeContractDescriptionElement, block: () -> Unit) {
|
||||||
|
if (needsBrackets(parent, child)) {
|
||||||
|
builder.append("(")
|
||||||
|
block()
|
||||||
|
builder.append(")")
|
||||||
|
} else {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ConeContractDescriptionElement.isAtom(): Boolean =
|
||||||
|
this is VariableReference || this is ConstantReference || this is ConeIsNullPredicate || this is ConeIsInstancePredicate
|
||||||
|
|
||||||
|
private fun needsBrackets(parent: ConeContractDescriptionElement, child: ConeContractDescriptionElement): Boolean {
|
||||||
|
if (child.isAtom()) return false
|
||||||
|
if (parent is ConeLogicalNot) return true
|
||||||
|
return parent::class != child::class
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ class ConeBooleanConstantReference private constructor(name: String) : ConeConst
|
|||||||
* Index of value parameter of function
|
* Index of value parameter of function
|
||||||
* -1 means that it is reference to extension receiver
|
* -1 means that it is reference to extension receiver
|
||||||
*/
|
*/
|
||||||
open class ConeValueParameterReference(val parameterIndex: Int) : ConeContractDescriptionValue {
|
open class ConeValueParameterReference(val parameterIndex: Int, val name: String) : ConeContractDescriptionValue {
|
||||||
init {
|
init {
|
||||||
assert(parameterIndex >= -1)
|
assert(parameterIndex >= -1)
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ open class ConeValueParameterReference(val parameterIndex: Int) : ConeContractDe
|
|||||||
contractDescriptionVisitor.visitValueParameterReference(this, data)
|
contractDescriptionVisitor.visitValueParameterReference(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConeBooleanValueParameterReference(parameterIndex: Int) : ConeValueParameterReference(parameterIndex), ConeBooleanExpression {
|
class ConeBooleanValueParameterReference(parameterIndex: Int, name: String) : ConeValueParameterReference(parameterIndex, name), ConeBooleanExpression {
|
||||||
override fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R =
|
override fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R =
|
||||||
contractDescriptionVisitor.visitBooleanValueParameterReference(this, data)
|
contractDescriptionVisitor.visitBooleanValueParameterReference(this, data)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user