[FIR] Properly track problems in contract description during effect extraction
This commit is contained in:
committed by
Space Team
parent
79d378f2bd
commit
5a92eb2c67
+82
-6
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
|
||||||
import org.jetbrains.kotlin.KtRealSourceElementKind
|
import org.jetbrains.kotlin.KtRealSourceElementKind
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
@@ -13,15 +12,16 @@ import org.jetbrains.kotlin.diagnostics.reportOn
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.description.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner
|
import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
|
|
||||||
object FirContractChecker : FirFunctionChecker() {
|
object FirContractChecker : FirFunctionChecker() {
|
||||||
// TODO: The message should vary. Migrate this to [ConeEffectExtractor] when creating fine-grained errors.
|
private val EMPTY_CONTRACT_MESSAGE = "Empty contract block is not allowed"
|
||||||
private const val UNEXPECTED_CONSTRUCTION = "unexpected construction in contract description"
|
|
||||||
|
|
||||||
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (declaration !is FirContractDescriptionOwner) return
|
if (declaration !is FirContractDescriptionOwner) return
|
||||||
@@ -29,6 +29,9 @@ object FirContractChecker : FirFunctionChecker() {
|
|||||||
|
|
||||||
checkUnresolvedEffects(contractDescription, context, reporter)
|
checkUnresolvedEffects(contractDescription, context, reporter)
|
||||||
checkContractNotAllowed(declaration, contractDescription, context, reporter)
|
checkContractNotAllowed(declaration, contractDescription, context, reporter)
|
||||||
|
if (contractDescription.effects.isEmpty() && contractDescription.unresolvedEffects.isEmpty()) {
|
||||||
|
reporter.reportOn(contractDescription.source, FirErrors.ERROR_IN_CONTRACT_DESCRIPTION, EMPTY_CONTRACT_MESSAGE, context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkUnresolvedEffects(
|
private fun checkUnresolvedEffects(
|
||||||
@@ -38,12 +41,11 @@ object FirContractChecker : FirFunctionChecker() {
|
|||||||
) {
|
) {
|
||||||
// Any statements that [ConeEffectExtractor] cannot extract effects will be in `unresolvedEffects`.
|
// Any statements that [ConeEffectExtractor] cannot extract effects will be in `unresolvedEffects`.
|
||||||
for (unresolvedEffect in contractDescription.unresolvedEffects) {
|
for (unresolvedEffect in contractDescription.unresolvedEffects) {
|
||||||
val statement = unresolvedEffect.statement
|
val diagnostic = unresolvedEffect.effect.accept(DiagnosticExtractor, null) ?: continue
|
||||||
if (statement.source == null || statement.source!!.kind is KtFakeSourceElementKind) continue
|
|
||||||
|
|
||||||
// TODO: report on fine-grained locations, e.g., ... implies unresolved => report on unresolved, not the entire statement.
|
// TODO: report on fine-grained locations, e.g., ... implies unresolved => report on unresolved, not the entire statement.
|
||||||
// but, sometimes, it's just reported on `contract`...
|
// but, sometimes, it's just reported on `contract`...
|
||||||
reporter.reportOn(statement.source, FirErrors.ERROR_IN_CONTRACT_DESCRIPTION, UNEXPECTED_CONSTRUCTION, context)
|
reporter.reportOn(unresolvedEffect.source, FirErrors.ERROR_IN_CONTRACT_DESCRIPTION, diagnostic.reason, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,4 +66,78 @@ object FirContractChecker : FirFunctionChecker() {
|
|||||||
else if (declaration.symbol.callableId.isLocal || declaration.visibility == Visibilities.Local) contractNotAllowed("Contracts are not allowed for local functions")
|
else if (declaration.symbol.callableId.isLocal || declaration.visibility == Visibilities.Local) contractNotAllowed("Contracts are not allowed for local functions")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object DiagnosticExtractor : ConeContractDescriptionVisitor<ConeDiagnostic?, Nothing?>() {
|
||||||
|
override fun visitContractDescriptionElement(
|
||||||
|
contractDescriptionElement: ConeContractDescriptionElement,
|
||||||
|
data: Nothing?
|
||||||
|
): ConeDiagnostic? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitConditionalEffectDeclaration(
|
||||||
|
conditionalEffect: ConeConditionalEffectDeclaration,
|
||||||
|
data: Nothing?
|
||||||
|
): ConeDiagnostic? {
|
||||||
|
return conditionalEffect.effect.accept(this, null) ?: conditionalEffect.condition.accept(this, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitReturnsEffectDeclaration(returnsEffect: ConeReturnsEffectDeclaration, data: Nothing?): ConeDiagnostic? {
|
||||||
|
return returnsEffect.value.accept(this, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCallsEffectDeclaration(callsEffect: ConeCallsEffectDeclaration, data: Nothing?): ConeDiagnostic? {
|
||||||
|
return callsEffect.valueParameterReference.accept(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitErroneousCallsEffectDeclaration(
|
||||||
|
callsEffect: ConeErroneousCallsEffectDeclaration,
|
||||||
|
data: Nothing?
|
||||||
|
): ConeDiagnostic {
|
||||||
|
return callsEffect.diagnostic
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitLogicalBinaryOperationContractExpression(
|
||||||
|
binaryLogicExpression: ConeBinaryLogicExpression,
|
||||||
|
data: Nothing?
|
||||||
|
): ConeDiagnostic? {
|
||||||
|
return binaryLogicExpression.left.accept(this, null) ?: binaryLogicExpression.right.accept(this, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitLogicalNot(logicalNot: ConeLogicalNot, data: Nothing?): ConeDiagnostic? {
|
||||||
|
return logicalNot.arg.accept(this, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitIsInstancePredicate(isInstancePredicate: ConeIsInstancePredicate, data: Nothing?): ConeDiagnostic? {
|
||||||
|
return isInstancePredicate.arg.accept(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitErroneousIsInstancePredicate(
|
||||||
|
isInstancePredicate: ConeErroneousIsInstancePredicate,
|
||||||
|
data: Nothing?
|
||||||
|
): ConeDiagnostic {
|
||||||
|
return isInstancePredicate.diagnostic
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitIsNullPredicate(isNullPredicate: ConeIsNullPredicate, data: Nothing?): ConeDiagnostic? {
|
||||||
|
return isNullPredicate.arg.accept(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitErroneousConstantReference(
|
||||||
|
erroneousConstantReference: ConeErroneousConstantReference,
|
||||||
|
data: Nothing?
|
||||||
|
): ConeDiagnostic {
|
||||||
|
return erroneousConstantReference.diagnostic
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitErroneousValueParameterReference(
|
||||||
|
valueParameterReference: ConeErroneousValueParameterReference,
|
||||||
|
data: Nothing?
|
||||||
|
): ConeDiagnostic {
|
||||||
|
return valueParameterReference.diagnostic
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitErroneousElement(element: ConeErroneousContractElement, data: Nothing?): ConeDiagnostic {
|
||||||
|
return element.diagnostic
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
|||||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.builder.buildResolvedContractDescription
|
import org.jetbrains.kotlin.fir.contracts.builder.buildResolvedContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.description.*
|
import org.jetbrains.kotlin.fir.contracts.description.*
|
||||||
import org.jetbrains.kotlin.fir.contracts.toFirEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.toFirElement
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner
|
import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.expressions.LogicOperationKind
|
import org.jetbrains.kotlin.fir.expressions.LogicOperationKind
|
||||||
@@ -24,7 +24,7 @@ class FirContractDeserializer(private val c: FirDeserializationContext) {
|
|||||||
fun loadContract(proto: ProtoBuf.Contract, owner: FirContractDescriptionOwner): FirContractDescription? {
|
fun loadContract(proto: ProtoBuf.Contract, owner: FirContractDescriptionOwner): FirContractDescription? {
|
||||||
val effects = proto.effectList.map { loadPossiblyConditionalEffect(it, owner) ?: return null }
|
val effects = proto.effectList.map { loadPossiblyConditionalEffect(it, owner) ?: return null }
|
||||||
return buildResolvedContractDescription {
|
return buildResolvedContractDescription {
|
||||||
this.effects += effects.map { it.toFirEffectDeclaration() }
|
this.effects += effects.map { it.toFirElement() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+100
-44
@@ -11,39 +11,49 @@ import org.jetbrains.kotlin.fir.FirSession
|
|||||||
import org.jetbrains.kotlin.fir.contracts.description.*
|
import org.jetbrains.kotlin.fir.contracts.description.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeContractDescriptionError
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
import org.jetbrains.kotlin.fir.resolve.getContainingClass
|
import org.jetbrains.kotlin.fir.resolve.getContainingClass
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
|
||||||
|
|
||||||
class ConeEffectExtractor(
|
class ConeEffectExtractor(
|
||||||
private val session: FirSession,
|
private val session: FirSession,
|
||||||
private val owner: FirContractDescriptionOwner,
|
private val owner: FirContractDescriptionOwner,
|
||||||
private val valueParameters: List<FirValueParameter>
|
private val valueParameters: List<FirValueParameter>
|
||||||
) : FirDefaultVisitor<ConeContractDescriptionElement?, Nothing?>() {
|
) : FirDefaultVisitor<ConeContractDescriptionElement, Nothing?>() {
|
||||||
companion object {
|
companion object {
|
||||||
private val BOOLEAN_AND = FirContractsDslNames.id("kotlin", "Boolean", "and")
|
private val BOOLEAN_AND = FirContractsDslNames.id("kotlin", "Boolean", "and")
|
||||||
private val BOOLEAN_OR = FirContractsDslNames.id("kotlin", "Boolean", "or")
|
private val BOOLEAN_OR = FirContractsDslNames.id("kotlin", "Boolean", "or")
|
||||||
private val BOOLEAN_NOT = FirContractsDslNames.id("kotlin", "Boolean", "not")
|
private val BOOLEAN_NOT = FirContractsDslNames.id("kotlin", "Boolean", "not")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitElement(element: FirElement, data: Nothing?): ConeContractDescriptionElement? {
|
private fun ConeContractDescriptionError.asElement(): ConeErroneousContractElement {
|
||||||
return null
|
return ConeErroneousContractElement(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitReturnExpression(returnExpression: FirReturnExpression, data: Nothing?): ConeContractDescriptionElement? {
|
override fun visitElement(element: FirElement, data: Nothing?): ConeContractDescriptionElement {
|
||||||
|
return ConeContractDescriptionError.IllegalElement(element).asElement()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitReturnExpression(returnExpression: FirReturnExpression, data: Nothing?): ConeContractDescriptionElement {
|
||||||
return returnExpression.result.accept(this, data)
|
return returnExpression.result.accept(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunctionCall(functionCall: FirFunctionCall, data: Nothing?): ConeContractDescriptionElement? {
|
override fun visitFunctionCall(functionCall: FirFunctionCall, data: Nothing?): ConeContractDescriptionElement {
|
||||||
val resolvedId = functionCall.toResolvedCallableSymbol()?.callableId ?: return null
|
val resolvedId = functionCall.toResolvedCallableSymbol()?.callableId
|
||||||
|
?: return ConeContractDescriptionError.UnresolvedCall(functionCall.calleeReference.name).asElement()
|
||||||
|
|
||||||
return when (resolvedId) {
|
return when (resolvedId) {
|
||||||
FirContractsDslNames.IMPLIES -> {
|
FirContractsDslNames.IMPLIES -> {
|
||||||
val effect = functionCall.explicitReceiver?.accept(this, null) as? ConeEffectDeclaration
|
val effect = functionCall.explicitReceiver?.asContractElement() as? ConeEffectDeclaration ?: noReceiver(resolvedId)
|
||||||
?: return null
|
val condition = functionCall.argument.asContractElement() as? ConeBooleanExpression ?: noArgument(resolvedId)
|
||||||
val condition = functionCall.argument.accept(this, null) as? ConeBooleanExpression
|
|
||||||
?: return null
|
|
||||||
ConeConditionalEffectDeclaration(effect, condition)
|
ConeConditionalEffectDeclaration(effect, condition)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,8 +62,10 @@ class ConeEffectExtractor(
|
|||||||
val value = if (argument == null) {
|
val value = if (argument == null) {
|
||||||
ConeConstantReference.WILDCARD
|
ConeConstantReference.WILDCARD
|
||||||
} else {
|
} else {
|
||||||
argument.accept(this, null) as? ConeConstantReference
|
when (val value = argument.asContractElement()) {
|
||||||
?: return null
|
is ConeConstantReference -> value
|
||||||
|
else -> ConeErroneousConstantReference(ConeContractDescriptionError.NotAConstant(value))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ConeReturnsEffectDeclaration(value)
|
ConeReturnsEffectDeclaration(value)
|
||||||
}
|
}
|
||||||
@@ -63,63 +75,80 @@ class ConeEffectExtractor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
FirContractsDslNames.CALLS_IN_PLACE -> {
|
FirContractsDslNames.CALLS_IN_PLACE -> {
|
||||||
val reference = functionCall.arguments[0].accept(this, null) as? ConeValueParameterReference
|
val reference = functionCall.arguments[0].asContractValueExpression()
|
||||||
?: return null
|
when (val argument = functionCall.arguments.getOrNull(1)) {
|
||||||
val kind = functionCall.arguments.getOrNull(1)?.parseInvocationKind() ?: EventOccurrencesRange.UNKNOWN
|
null -> ConeCallsEffectDeclaration(reference, EventOccurrencesRange.UNKNOWN)
|
||||||
ConeCallsEffectDeclaration(reference, kind)
|
else -> when (val kind = argument.parseInvocationKind()) {
|
||||||
|
null -> ConeErroneousCallsEffectDeclaration(reference, ConeContractDescriptionError.UnresolvedInvocationKind(argument))
|
||||||
|
else -> ConeCallsEffectDeclaration(reference, kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN_AND, BOOLEAN_OR -> {
|
BOOLEAN_AND, BOOLEAN_OR -> {
|
||||||
val left = functionCall.explicitReceiver?.accept(this, null) as? ConeBooleanExpression ?: return null
|
val left = functionCall.explicitReceiver?.asContractBooleanExpression() ?: noReceiver(resolvedId)
|
||||||
val right = functionCall.argument.accept(this, null) as? ConeBooleanExpression ?: return null
|
val right = functionCall.arguments.firstOrNull()?.asContractBooleanExpression() ?: noArgument(resolvedId)
|
||||||
val kind = when (resolvedId) {
|
val kind = when (resolvedId) {
|
||||||
BOOLEAN_AND -> LogicOperationKind.AND
|
BOOLEAN_AND -> LogicOperationKind.AND
|
||||||
BOOLEAN_OR -> LogicOperationKind.OR
|
BOOLEAN_OR -> LogicOperationKind.OR
|
||||||
else -> throw IllegalStateException()
|
else -> shouldNotBeCalled()
|
||||||
}
|
}
|
||||||
ConeBinaryLogicExpression(left, right, kind)
|
ConeBinaryLogicExpression(left, right, kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN_NOT -> {
|
BOOLEAN_NOT -> {
|
||||||
val arg = functionCall.explicitReceiver?.accept(this, null) as? ConeBooleanExpression ?: return null
|
val arg = functionCall.explicitReceiver?.asContractBooleanExpression() ?: noReceiver(resolvedId)
|
||||||
ConeLogicalNot(arg)
|
ConeLogicalNot(arg)
|
||||||
}
|
}
|
||||||
else -> null
|
|
||||||
|
else -> ConeContractDescriptionError.NotContractDsl(resolvedId).asElement()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBinaryLogicExpression(
|
override fun visitBinaryLogicExpression(
|
||||||
binaryLogicExpression: FirBinaryLogicExpression,
|
binaryLogicExpression: FirBinaryLogicExpression,
|
||||||
data: Nothing?
|
data: Nothing?
|
||||||
): ConeContractDescriptionElement? {
|
): ConeContractDescriptionElement {
|
||||||
val left = binaryLogicExpression.leftOperand.accept(this, null) as? ConeBooleanExpression ?: return null
|
val left = binaryLogicExpression.leftOperand.asContractBooleanExpression()
|
||||||
val right = binaryLogicExpression.rightOperand.accept(this, null) as? ConeBooleanExpression ?: return null
|
val right = binaryLogicExpression.rightOperand.asContractBooleanExpression()
|
||||||
return ConeBinaryLogicExpression(left, right, binaryLogicExpression.kind)
|
return ConeBinaryLogicExpression(left, right, binaryLogicExpression.kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Nothing?): ConeContractDescriptionElement? {
|
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Nothing?): ConeContractDescriptionElement {
|
||||||
val isNegated = when (equalityOperatorCall.operation) {
|
val isNegated = when (val operation = equalityOperatorCall.operation) {
|
||||||
FirOperation.EQ -> false
|
FirOperation.EQ -> false
|
||||||
FirOperation.NOT_EQ -> true
|
FirOperation.NOT_EQ -> true
|
||||||
else -> return null
|
else -> return ConeContractDescriptionError.IllegalEqualityOperator(operation).asElement()
|
||||||
}
|
}
|
||||||
val const = equalityOperatorCall.arguments[1] as? FirConstExpression<*> ?: return null
|
|
||||||
if (const.kind != ConstantValueKind.Null) return null
|
val argument = equalityOperatorCall.arguments[1]
|
||||||
val arg = equalityOperatorCall.arguments[0].accept(this, null) as? ConeValueParameterReference ?: return null
|
val const = argument as? FirConstExpression<*> ?: return ConeContractDescriptionError.NotAConstant(argument).asElement()
|
||||||
|
if (const.kind != ConstantValueKind.Null) return ConeContractDescriptionError.IllegalConst(const, onlyNullAllowed = true).asElement()
|
||||||
|
|
||||||
|
val arg = equalityOperatorCall.arguments[0].asContractValueExpression()
|
||||||
return ConeIsNullPredicate(arg, isNegated)
|
return ConeIsNullPredicate(arg, isNegated)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: Nothing?): ConeContractDescriptionElement? {
|
override fun visitSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: Nothing?): ConeContractDescriptionElement {
|
||||||
return smartCastExpression.originalExpression.accept(this, data)
|
return smartCastExpression.originalExpression.accept(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitQualifiedAccessExpression(
|
override fun visitQualifiedAccessExpression(
|
||||||
qualifiedAccessExpression: FirQualifiedAccessExpression,
|
qualifiedAccessExpression: FirQualifiedAccessExpression,
|
||||||
data: Nothing?
|
data: Nothing?
|
||||||
): ConeContractDescriptionElement? {
|
): ConeContractDescriptionElement {
|
||||||
val symbol = qualifiedAccessExpression.toResolvedCallableSymbol() ?: return null
|
val symbol = qualifiedAccessExpression.toResolvedCallableSymbol()
|
||||||
val parameter = symbol.fir as? FirValueParameter ?: return null
|
?: run {
|
||||||
val index = valueParameters.indexOf(parameter).takeUnless { it < 0 } ?: return null
|
val name = (qualifiedAccessExpression.calleeReference as? FirNamedReference)?.name ?: Name.special("unresolved")
|
||||||
|
return ConeContractDescriptionError.UnresolvedCall(name).asElement()
|
||||||
|
}
|
||||||
|
val parameter = symbol.fir as? FirValueParameter
|
||||||
|
?: return ConeErroneousValueParameterReference(
|
||||||
|
ConeContractDescriptionError.IllegalParameter(symbol, "$symbol is not a value parameter")
|
||||||
|
)
|
||||||
|
val index = valueParameters.indexOf(parameter).takeUnless { it < 0 } ?: return ConeErroneousValueParameterReference(
|
||||||
|
ConeContractDescriptionError.IllegalParameter(symbol, "Value paramter $symbol is not found in parameters of outer function")
|
||||||
|
)
|
||||||
val type = parameter.returnTypeRef.coneType
|
val type = parameter.returnTypeRef.coneType
|
||||||
|
|
||||||
val name = parameter.name.asString()
|
val name = parameter.name.asString()
|
||||||
@@ -129,7 +158,7 @@ class ConeEffectExtractor(
|
|||||||
override fun visitPropertyAccessExpression(
|
override fun visitPropertyAccessExpression(
|
||||||
propertyAccessExpression: FirPropertyAccessExpression,
|
propertyAccessExpression: FirPropertyAccessExpression,
|
||||||
data: Nothing?
|
data: Nothing?
|
||||||
): ConeContractDescriptionElement? {
|
): ConeContractDescriptionElement {
|
||||||
return visitQualifiedAccessExpression(propertyAccessExpression, data)
|
return visitQualifiedAccessExpression(propertyAccessExpression, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,8 +181,9 @@ class ConeEffectExtractor(
|
|||||||
override fun visitThisReceiverExpression(
|
override fun visitThisReceiverExpression(
|
||||||
thisReceiverExpression: FirThisReceiverExpression,
|
thisReceiverExpression: FirThisReceiverExpression,
|
||||||
data: Nothing?
|
data: Nothing?
|
||||||
): ConeContractDescriptionElement? {
|
): ConeContractDescriptionElement {
|
||||||
val declaration = thisReceiverExpression.calleeReference.boundSymbol?.fir ?: return null
|
val declaration = thisReceiverExpression.calleeReference.boundSymbol?.fir
|
||||||
|
?: return ConeContractDescriptionError.UnresolvedThis(thisReceiverExpression).asElement()
|
||||||
val callableOwner = owner as? FirCallableDeclaration
|
val callableOwner = owner as? FirCallableDeclaration
|
||||||
val ownerHasReceiver = callableOwner?.receiverParameter != null
|
val ownerHasReceiver = callableOwner?.receiverParameter != null
|
||||||
val ownerIsMemberOfDeclaration = callableOwner?.getContainingClass(session) == declaration
|
val ownerIsMemberOfDeclaration = callableOwner?.getContainingClass(session) == declaration
|
||||||
@@ -161,24 +191,24 @@ class ConeEffectExtractor(
|
|||||||
val type = thisReceiverExpression.typeRef.coneType
|
val type = thisReceiverExpression.typeRef.coneType
|
||||||
toValueParameterReference(type, -1, "this")
|
toValueParameterReference(type, -1, "this")
|
||||||
} else {
|
} else {
|
||||||
null
|
ConeContractDescriptionError.IllegalThis(thisReceiverExpression).asElement()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: Nothing?): ConeContractDescriptionElement? {
|
override fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: Nothing?): ConeContractDescriptionElement {
|
||||||
return when (constExpression.kind) {
|
return when (constExpression.kind) {
|
||||||
ConstantValueKind.Null -> ConeConstantReference.NULL
|
ConstantValueKind.Null -> ConeConstantReference.NULL
|
||||||
ConstantValueKind.Boolean -> when (constExpression.value as Boolean) {
|
ConstantValueKind.Boolean -> when (constExpression.value as Boolean) {
|
||||||
true -> ConeBooleanConstantReference.TRUE
|
true -> ConeBooleanConstantReference.TRUE
|
||||||
false -> ConeBooleanConstantReference.FALSE
|
false -> ConeBooleanConstantReference.FALSE
|
||||||
}
|
}
|
||||||
else -> null
|
else -> ConeContractDescriptionError.IllegalConst(constExpression, onlyNullAllowed = false).asElement()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Nothing?): ConeContractDescriptionElement? {
|
override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Nothing?): ConeContractDescriptionElement {
|
||||||
val arg = typeOperatorCall.argument.accept(this, data) as? ConeValueParameterReference ?: return null
|
val arg = typeOperatorCall.argument.asContractValueExpression()
|
||||||
val type = typeOperatorCall.conversionTypeRef.coneType
|
val type = typeOperatorCall.conversionTypeRef.coneType.fullyExpandedType(session)
|
||||||
val isNegated = typeOperatorCall.operation == FirOperation.NOT_IS
|
val isNegated = typeOperatorCall.operation == FirOperation.NOT_IS
|
||||||
return ConeIsInstancePredicate(arg, type, isNegated)
|
return ConeIsInstancePredicate(arg, type, isNegated)
|
||||||
}
|
}
|
||||||
@@ -194,4 +224,30 @@ class ConeEffectExtractor(
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun noReceiver(callableId: CallableId): ConeErroneousContractElement {
|
||||||
|
return ConeContractDescriptionError.NoReceiver(callableId.callableName).asElement()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun noArgument(callableId: CallableId): ConeErroneousContractElement {
|
||||||
|
return ConeContractDescriptionError.NoArgument(callableId.callableName).asElement()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirElement.asContractElement(): ConeContractDescriptionElement {
|
||||||
|
return accept(this@ConeEffectExtractor, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirExpression.asContractBooleanExpression(): ConeBooleanExpression {
|
||||||
|
return when (val element = asContractElement()) {
|
||||||
|
is ConeBooleanExpression -> element
|
||||||
|
else -> ConeContractDescriptionError.NotABooleanExpression(element).asElement()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirExpression.asContractValueExpression(): ConeValueParameterReference {
|
||||||
|
return when (val element = asContractElement()) {
|
||||||
|
is ConeValueParameterReference -> element
|
||||||
|
else -> ConeErroneousValueParameterReference(ConeContractDescriptionError.NotAParameterReference(element))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-7
@@ -5,15 +5,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.transformers.contracts
|
package org.jetbrains.kotlin.fir.resolve.transformers.contracts
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirRawContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirRawContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.builder.buildLegacyRawContractDescription
|
import org.jetbrains.kotlin.fir.contracts.builder.buildLegacyRawContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.builder.buildResolvedContractDescription
|
import org.jetbrains.kotlin.fir.contracts.builder.buildResolvedContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.description.ConeEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.description.ConeEffectDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.description.ConeUnresolvedEffect
|
|
||||||
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
|
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.toFirEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.toFirElement
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction
|
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildReceiverParameter
|
import org.jetbrains.kotlin.fir.declarations.builder.buildReceiverParameter
|
||||||
@@ -179,11 +179,13 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
|
|||||||
val resolvedContractDescription = buildResolvedContractDescription {
|
val resolvedContractDescription = buildResolvedContractDescription {
|
||||||
val effectExtractor = ConeEffectExtractor(session, owner, valueParameters)
|
val effectExtractor = ConeEffectExtractor(session, owner, valueParameters)
|
||||||
for (statement in lambdaBody.statements) {
|
for (statement in lambdaBody.statements) {
|
||||||
val effect = statement.accept(effectExtractor, null) as? ConeEffectDeclaration
|
if (statement.source?.kind is KtFakeSourceElementKind.ImplicitReturn) continue
|
||||||
if (effect == null) {
|
when (val effect = statement.accept(effectExtractor, null)) {
|
||||||
unresolvedEffects += ConeUnresolvedEffect(statement)
|
is ConeEffectDeclaration -> when (effect.erroneous) {
|
||||||
} else {
|
false -> effects += effect.toFirElement(statement.source)
|
||||||
effects += effect.toFirEffectDeclaration(statement.source)
|
true -> unresolvedEffects += effect.toFirElement(statement.source)
|
||||||
|
}
|
||||||
|
else -> unresolvedEffects += effect.toFirElement(statement.source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.source = contractDescription.source
|
this.source = contractDescription.source
|
||||||
|
|||||||
+83
-1
@@ -7,9 +7,14 @@ package org.jetbrains.kotlin.fir.resolve.diagnostics
|
|||||||
|
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import org.jetbrains.kotlin.KtSourceElement
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.description.ConeContractDescriptionElement
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnosticWithSource
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnosticWithSource
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirOperation
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
||||||
import org.jetbrains.kotlin.fir.render
|
import org.jetbrains.kotlin.fir.render
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.AbstractCandidate
|
import org.jetbrains.kotlin.fir.resolve.calls.AbstractCandidate
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
@@ -17,6 +22,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.*
|
|||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.FirQualifierPart
|
import org.jetbrains.kotlin.fir.types.FirQualifierPart
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||||
@@ -138,7 +144,83 @@ object ConeVariableExpectedError : ConeDiagnostic {
|
|||||||
override val reason: String get() = "Variable expected"
|
override val reason: String get() = "Variable expected"
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConeContractDescriptionError(override val reason: String) : ConeDiagnostic
|
sealed class ConeContractDescriptionError : ConeDiagnostic {
|
||||||
|
class IllegalElement(val element: FirElement) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "Illegal element in contract description"
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnresolvedCall(val name: Name) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "Unresolved call in contract description: ${name.asString()}"
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoReceiver(val name: Name) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "No receiver for call ${name.asString()} found"
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoArgument(val name: Name) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "No argument for call ${name.asString()} found"
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotAConstant(val element: Any) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "$element is not a constant reference"
|
||||||
|
}
|
||||||
|
|
||||||
|
class IllegalConst(
|
||||||
|
val element: FirConstExpression<*>,
|
||||||
|
val onlyNullAllowed: Boolean
|
||||||
|
) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = buildString {
|
||||||
|
append(element.render())
|
||||||
|
append("is not a null")
|
||||||
|
if (!onlyNullAllowed) {
|
||||||
|
append(", true or false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotAParameterReference(val element: ConeContractDescriptionElement) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "$element is not a parameter or receiver reference"
|
||||||
|
}
|
||||||
|
|
||||||
|
class IllegalParameter(val symbol: FirCallableSymbol<*>, override val reason: String) : ConeContractDescriptionError()
|
||||||
|
|
||||||
|
class UnresolvedThis(val expression: FirThisReceiverExpression) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "Can't resolve this reference"
|
||||||
|
}
|
||||||
|
|
||||||
|
class IllegalThis(val expression: FirThisReceiverExpression) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "Only this reference to extension receiver of a function is allowed"
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnresolvedInvocationKind(val element: FirElement) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "${element.render()} is not a valid invocation kind"
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotABooleanExpression(val element: ConeContractDescriptionElement) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "$element is not a boolean expression"
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotContractDsl(val callableId: CallableId) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "$callableId is not a part of contracts DSL"
|
||||||
|
}
|
||||||
|
|
||||||
|
class IllegalEqualityOperator(val operation: FirOperation) : ConeContractDescriptionError() {
|
||||||
|
override val reason: String
|
||||||
|
get() = "$operation operator call is illegal in contract description"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ConeIllegalAnnotationError(val name: Name) : ConeDiagnostic {
|
class ConeIllegalAnnotationError(val name: Name) : ConeDiagnostic {
|
||||||
override val reason: String get() = "Not a legal annotation: $name"
|
override val reason: String get() = "Not a legal annotation: $name"
|
||||||
|
|||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirPureAbstractElement
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.description.ConeContractDescriptionElement
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.*
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was generated automatically
|
||||||
|
* DO NOT MODIFY IT MANUALLY
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class FirContractElementDeclaration : FirPureAbstractElement(), FirElement {
|
||||||
|
abstract override val source: KtSourceElement?
|
||||||
|
abstract val effect: ConeContractDescriptionElement
|
||||||
|
|
||||||
|
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitContractElementDeclaration(this, data)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
|
||||||
|
transformer.transformContractElementDeclaration(this, data) as E
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.contracts
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.KtSourceElement
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.FirPureAbstractElement
|
|
||||||
import org.jetbrains.kotlin.fir.contracts.description.ConeEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.description.ConeEffectDeclaration
|
||||||
import org.jetbrains.kotlin.fir.visitors.*
|
import org.jetbrains.kotlin.fir.visitors.*
|
||||||
|
|
||||||
@@ -16,9 +15,9 @@ import org.jetbrains.kotlin.fir.visitors.*
|
|||||||
* DO NOT MODIFY IT MANUALLY
|
* DO NOT MODIFY IT MANUALLY
|
||||||
*/
|
*/
|
||||||
|
|
||||||
abstract class FirEffectDeclaration : FirPureAbstractElement(), FirElement {
|
abstract class FirEffectDeclaration : FirContractElementDeclaration() {
|
||||||
abstract override val source: KtSourceElement?
|
abstract override val source: KtSourceElement?
|
||||||
abstract val effect: ConeEffectDeclaration
|
abstract override val effect: ConeEffectDeclaration
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitEffectDeclaration(this, data)
|
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitEffectDeclaration(this, data)
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.contracts
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.KtSourceElement
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.contracts.description.ConeUnresolvedEffect
|
|
||||||
import org.jetbrains.kotlin.fir.visitors.*
|
import org.jetbrains.kotlin.fir.visitors.*
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -18,7 +17,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
|||||||
abstract class FirResolvedContractDescription : FirContractDescription() {
|
abstract class FirResolvedContractDescription : FirContractDescription() {
|
||||||
abstract override val source: KtSourceElement?
|
abstract override val source: KtSourceElement?
|
||||||
abstract val effects: List<FirEffectDeclaration>
|
abstract val effects: List<FirEffectDeclaration>
|
||||||
abstract val unresolvedEffects: List<ConeUnresolvedEffect>
|
abstract val unresolvedEffects: List<FirContractElementDeclaration>
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitResolvedContractDescription(this, data)
|
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitResolvedContractDescription(this, data)
|
||||||
|
|
||||||
|
|||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("DuplicatedCode")
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.contracts.builder
|
||||||
|
|
||||||
|
import kotlin.contracts.*
|
||||||
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.FirContractElementDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.description.ConeContractDescriptionElement
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.impl.FirContractElementDeclarationImpl
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.*
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was generated automatically
|
||||||
|
* DO NOT MODIFY IT MANUALLY
|
||||||
|
*/
|
||||||
|
|
||||||
|
@FirBuilderDsl
|
||||||
|
class FirContractElementDeclarationBuilder {
|
||||||
|
var source: KtSourceElement? = null
|
||||||
|
lateinit var effect: ConeContractDescriptionElement
|
||||||
|
|
||||||
|
fun build(): FirContractElementDeclaration {
|
||||||
|
return FirContractElementDeclarationImpl(
|
||||||
|
source,
|
||||||
|
effect,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
inline fun buildContractElementDeclaration(init: FirContractElementDeclarationBuilder.() -> Unit): FirContractElementDeclaration {
|
||||||
|
contract {
|
||||||
|
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
return FirContractElementDeclarationBuilder().apply(init).build()
|
||||||
|
}
|
||||||
+2
-2
@@ -10,9 +10,9 @@ package org.jetbrains.kotlin.fir.contracts.builder
|
|||||||
import kotlin.contracts.*
|
import kotlin.contracts.*
|
||||||
import org.jetbrains.kotlin.KtSourceElement
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
|
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.FirContractElementDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.description.ConeUnresolvedEffect
|
|
||||||
import org.jetbrains.kotlin.fir.contracts.impl.FirResolvedContractDescriptionImpl
|
import org.jetbrains.kotlin.fir.contracts.impl.FirResolvedContractDescriptionImpl
|
||||||
import org.jetbrains.kotlin.fir.visitors.*
|
import org.jetbrains.kotlin.fir.visitors.*
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
|||||||
class FirResolvedContractDescriptionBuilder {
|
class FirResolvedContractDescriptionBuilder {
|
||||||
var source: KtSourceElement? = null
|
var source: KtSourceElement? = null
|
||||||
val effects: MutableList<FirEffectDeclaration> = mutableListOf()
|
val effects: MutableList<FirEffectDeclaration> = mutableListOf()
|
||||||
val unresolvedEffects: MutableList<ConeUnresolvedEffect> = mutableListOf()
|
val unresolvedEffects: MutableList<FirContractElementDeclaration> = mutableListOf()
|
||||||
|
|
||||||
fun build(): FirResolvedContractDescription {
|
fun build(): FirResolvedContractDescription {
|
||||||
return FirResolvedContractDescriptionImpl(
|
return FirResolvedContractDescriptionImpl(
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("DuplicatedCode")
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.contracts.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.FirContractElementDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.description.ConeContractDescriptionElement
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.*
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was generated automatically
|
||||||
|
* DO NOT MODIFY IT MANUALLY
|
||||||
|
*/
|
||||||
|
|
||||||
|
internal class FirContractElementDeclarationImpl(
|
||||||
|
override val source: KtSourceElement?,
|
||||||
|
override val effect: ConeContractDescriptionElement,
|
||||||
|
) : FirContractElementDeclaration() {
|
||||||
|
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
||||||
|
|
||||||
|
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirContractElementDeclarationImpl {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-2
@@ -8,9 +8,9 @@
|
|||||||
package org.jetbrains.kotlin.fir.contracts.impl
|
package org.jetbrains.kotlin.fir.contracts.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.KtSourceElement
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.FirContractElementDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.description.ConeUnresolvedEffect
|
|
||||||
import org.jetbrains.kotlin.fir.visitors.*
|
import org.jetbrains.kotlin.fir.visitors.*
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -21,14 +21,16 @@ import org.jetbrains.kotlin.fir.visitors.*
|
|||||||
internal class FirResolvedContractDescriptionImpl(
|
internal class FirResolvedContractDescriptionImpl(
|
||||||
override val source: KtSourceElement?,
|
override val source: KtSourceElement?,
|
||||||
override val effects: MutableList<FirEffectDeclaration>,
|
override val effects: MutableList<FirEffectDeclaration>,
|
||||||
override val unresolvedEffects: MutableList<ConeUnresolvedEffect>,
|
override val unresolvedEffects: MutableList<FirContractElementDeclaration>,
|
||||||
) : FirResolvedContractDescription() {
|
) : FirResolvedContractDescription() {
|
||||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||||
effects.forEach { it.accept(visitor, data) }
|
effects.forEach { it.accept(visitor, data) }
|
||||||
|
unresolvedEffects.forEach { it.accept(visitor, data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirResolvedContractDescriptionImpl {
|
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirResolvedContractDescriptionImpl {
|
||||||
effects.transformInplace(transformer, data)
|
effects.transformInplace(transformer, data)
|
||||||
|
unresolvedEffects.transformInplace(transformer, data)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ import org.jetbrains.kotlin.fir.types.FirDynamicTypeRef
|
|||||||
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirIntersectionTypeRef
|
import org.jetbrains.kotlin.fir.types.FirIntersectionTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.FirContractElementDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
||||||
@@ -314,6 +315,8 @@ abstract class FirDefaultVisitor<out R, in D> : FirVisitor<R, D>() {
|
|||||||
|
|
||||||
override fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: D): R = visitTypeRef(implicitTypeRef, data)
|
override fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: D): R = visitTypeRef(implicitTypeRef, data)
|
||||||
|
|
||||||
|
override fun visitEffectDeclaration(effectDeclaration: FirEffectDeclaration, data: D): R = visitContractElementDeclaration(effectDeclaration, data)
|
||||||
|
|
||||||
override fun visitLegacyRawContractDescription(legacyRawContractDescription: FirLegacyRawContractDescription, data: D): R = visitContractDescription(legacyRawContractDescription, data)
|
override fun visitLegacyRawContractDescription(legacyRawContractDescription: FirLegacyRawContractDescription, data: D): R = visitContractDescription(legacyRawContractDescription, data)
|
||||||
|
|
||||||
override fun visitRawContractDescription(rawContractDescription: FirRawContractDescription, data: D): R = visitContractDescription(rawContractDescription, data)
|
override fun visitRawContractDescription(rawContractDescription: FirRawContractDescription, data: D): R = visitContractDescription(rawContractDescription, data)
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ import org.jetbrains.kotlin.fir.types.FirDynamicTypeRef
|
|||||||
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirIntersectionTypeRef
|
import org.jetbrains.kotlin.fir.types.FirIntersectionTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.FirContractElementDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
||||||
@@ -314,6 +315,8 @@ abstract class FirDefaultVisitorVoid : FirVisitorVoid() {
|
|||||||
|
|
||||||
override fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef) = visitTypeRef(implicitTypeRef)
|
override fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef) = visitTypeRef(implicitTypeRef)
|
||||||
|
|
||||||
|
override fun visitEffectDeclaration(effectDeclaration: FirEffectDeclaration) = visitContractElementDeclaration(effectDeclaration)
|
||||||
|
|
||||||
override fun visitLegacyRawContractDescription(legacyRawContractDescription: FirLegacyRawContractDescription) = visitContractDescription(legacyRawContractDescription)
|
override fun visitLegacyRawContractDescription(legacyRawContractDescription: FirLegacyRawContractDescription) = visitContractDescription(legacyRawContractDescription)
|
||||||
|
|
||||||
override fun visitRawContractDescription(rawContractDescription: FirRawContractDescription) = visitContractDescription(rawContractDescription)
|
override fun visitRawContractDescription(rawContractDescription: FirRawContractDescription) = visitContractDescription(rawContractDescription)
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ import org.jetbrains.kotlin.fir.types.FirDynamicTypeRef
|
|||||||
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirIntersectionTypeRef
|
import org.jetbrains.kotlin.fir.types.FirIntersectionTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.FirContractElementDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
||||||
@@ -731,7 +732,11 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
|||||||
return transformElement(implicitTypeRef, data)
|
return transformElement(implicitTypeRef, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun transformEffectDeclaration(effectDeclaration: FirEffectDeclaration, data: D): FirEffectDeclaration {
|
open fun transformContractElementDeclaration(contractElementDeclaration: FirContractElementDeclaration, data: D): FirContractElementDeclaration {
|
||||||
|
return transformElement(contractElementDeclaration, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun transformEffectDeclaration(effectDeclaration: FirEffectDeclaration, data: D): FirContractElementDeclaration {
|
||||||
return transformElement(effectDeclaration, data)
|
return transformElement(effectDeclaration, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1323,7 +1328,11 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
|||||||
return transformImplicitTypeRef(implicitTypeRef, data)
|
return transformImplicitTypeRef(implicitTypeRef, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun visitEffectDeclaration(effectDeclaration: FirEffectDeclaration, data: D): FirEffectDeclaration {
|
final override fun visitContractElementDeclaration(contractElementDeclaration: FirContractElementDeclaration, data: D): FirContractElementDeclaration {
|
||||||
|
return transformContractElementDeclaration(contractElementDeclaration, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
final override fun visitEffectDeclaration(effectDeclaration: FirEffectDeclaration, data: D): FirContractElementDeclaration {
|
||||||
return transformEffectDeclaration(effectDeclaration, data)
|
return transformEffectDeclaration(effectDeclaration, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ import org.jetbrains.kotlin.fir.types.FirDynamicTypeRef
|
|||||||
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirIntersectionTypeRef
|
import org.jetbrains.kotlin.fir.types.FirIntersectionTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.FirContractElementDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
||||||
@@ -446,6 +447,8 @@ abstract class FirVisitor<out R, in D> {
|
|||||||
|
|
||||||
open fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: D): R = visitElement(implicitTypeRef, data)
|
open fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: D): R = visitElement(implicitTypeRef, data)
|
||||||
|
|
||||||
|
open fun visitContractElementDeclaration(contractElementDeclaration: FirContractElementDeclaration, data: D): R = visitElement(contractElementDeclaration, data)
|
||||||
|
|
||||||
open fun visitEffectDeclaration(effectDeclaration: FirEffectDeclaration, data: D): R = visitElement(effectDeclaration, data)
|
open fun visitEffectDeclaration(effectDeclaration: FirEffectDeclaration, data: D): R = visitElement(effectDeclaration, data)
|
||||||
|
|
||||||
open fun visitContractDescription(contractDescription: FirContractDescription, data: D): R = visitElement(contractDescription, data)
|
open fun visitContractDescription(contractDescription: FirContractDescription, data: D): R = visitElement(contractDescription, data)
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ import org.jetbrains.kotlin.fir.types.FirDynamicTypeRef
|
|||||||
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirIntersectionTypeRef
|
import org.jetbrains.kotlin.fir.types.FirIntersectionTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.FirContractElementDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
|
||||||
@@ -730,6 +731,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
|||||||
visitElement(implicitTypeRef)
|
visitElement(implicitTypeRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun visitContractElementDeclaration(contractElementDeclaration: FirContractElementDeclaration) {
|
||||||
|
visitElement(contractElementDeclaration)
|
||||||
|
}
|
||||||
|
|
||||||
open fun visitEffectDeclaration(effectDeclaration: FirEffectDeclaration) {
|
open fun visitEffectDeclaration(effectDeclaration: FirEffectDeclaration) {
|
||||||
visitElement(effectDeclaration)
|
visitElement(effectDeclaration)
|
||||||
}
|
}
|
||||||
@@ -1322,6 +1327,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
|||||||
visitImplicitTypeRef(implicitTypeRef)
|
visitImplicitTypeRef(implicitTypeRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final override fun visitContractElementDeclaration(contractElementDeclaration: FirContractElementDeclaration, data: Nothing?) {
|
||||||
|
visitContractElementDeclaration(contractElementDeclaration)
|
||||||
|
}
|
||||||
|
|
||||||
final override fun visitEffectDeclaration(effectDeclaration: FirEffectDeclaration, data: Nothing?) {
|
final override fun visitEffectDeclaration(effectDeclaration: FirEffectDeclaration, data: Nothing?) {
|
||||||
visitEffectDeclaration(effectDeclaration)
|
visitEffectDeclaration(effectDeclaration)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,16 +6,27 @@
|
|||||||
package org.jetbrains.kotlin.fir.contracts
|
package org.jetbrains.kotlin.fir.contracts
|
||||||
|
|
||||||
import org.jetbrains.kotlin.KtSourceElement
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.builder.buildContractElementDeclaration
|
||||||
import org.jetbrains.kotlin.fir.contracts.builder.buildEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.builder.buildEffectDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.contracts.description.ConeContractDescriptionElement
|
||||||
import org.jetbrains.kotlin.fir.contracts.description.ConeEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.description.ConeEffectDeclaration
|
||||||
|
|
||||||
val FirContractDescription.effects: List<FirEffectDeclaration>?
|
val FirContractDescription.effects: List<FirEffectDeclaration>?
|
||||||
get() = (this as? FirResolvedContractDescription)?.effects
|
get() = (this as? FirResolvedContractDescription)?.effects
|
||||||
|
|
||||||
fun ConeEffectDeclaration.toFirEffectDeclaration(source: KtSourceElement? = null): FirEffectDeclaration =
|
fun ConeEffectDeclaration.toFirElement(source: KtSourceElement? = null): FirEffectDeclaration =
|
||||||
buildEffectDeclaration {
|
buildEffectDeclaration {
|
||||||
if (source != null) {
|
if (source != null) {
|
||||||
this.source = source
|
this.source = source
|
||||||
}
|
}
|
||||||
effect = this@toFirEffectDeclaration
|
effect = this@toFirElement
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun ConeContractDescriptionElement.toFirElement(source: KtSourceElement? = null): FirContractElementDeclaration =
|
||||||
|
buildContractElementDeclaration {
|
||||||
|
if (source != null) {
|
||||||
|
this.source = source
|
||||||
|
}
|
||||||
|
effect = this@toFirElement
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.fir.contracts.description
|
|||||||
|
|
||||||
interface ConeContractDescriptionElement {
|
interface ConeContractDescriptionElement {
|
||||||
fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R
|
fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R
|
||||||
|
|
||||||
|
val erroneous: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ConeEffectDeclaration : ConeContractDescriptionElement {
|
abstract class ConeEffectDeclaration : ConeContractDescriptionElement {
|
||||||
|
|||||||
+17
-1
@@ -23,6 +23,9 @@ abstract class ConeContractDescriptionVisitor<out R, in D> {
|
|||||||
open fun visitCallsEffectDeclaration(callsEffect: ConeCallsEffectDeclaration, data: D): R =
|
open fun visitCallsEffectDeclaration(callsEffect: ConeCallsEffectDeclaration, data: D): R =
|
||||||
visitEffectDeclaration(callsEffect, data)
|
visitEffectDeclaration(callsEffect, data)
|
||||||
|
|
||||||
|
open fun visitErroneousCallsEffectDeclaration(callsEffect: ConeErroneousCallsEffectDeclaration, data: D): R =
|
||||||
|
visitCallsEffectDeclaration(callsEffect, data)
|
||||||
|
|
||||||
// Expressions
|
// Expressions
|
||||||
open fun visitBooleanExpression(booleanExpression: ConeBooleanExpression, data: D): R =
|
open fun visitBooleanExpression(booleanExpression: ConeBooleanExpression, data: D): R =
|
||||||
visitContractDescriptionElement(booleanExpression, data)
|
visitContractDescriptionElement(booleanExpression, data)
|
||||||
@@ -35,6 +38,9 @@ abstract class ConeContractDescriptionVisitor<out R, in D> {
|
|||||||
open fun visitIsInstancePredicate(isInstancePredicate: ConeIsInstancePredicate, data: D): R =
|
open fun visitIsInstancePredicate(isInstancePredicate: ConeIsInstancePredicate, data: D): R =
|
||||||
visitBooleanExpression(isInstancePredicate, data)
|
visitBooleanExpression(isInstancePredicate, data)
|
||||||
|
|
||||||
|
open fun visitErroneousIsInstancePredicate(isInstancePredicate: ConeErroneousIsInstancePredicate, data: D): R =
|
||||||
|
visitIsInstancePredicate(isInstancePredicate, data)
|
||||||
|
|
||||||
open fun visitIsNullPredicate(isNullPredicate: ConeIsNullPredicate, data: D): R = visitBooleanExpression(isNullPredicate, data)
|
open fun visitIsNullPredicate(isNullPredicate: ConeIsNullPredicate, data: D): R = visitBooleanExpression(isNullPredicate, data)
|
||||||
|
|
||||||
// Values
|
// Values
|
||||||
@@ -45,9 +51,19 @@ abstract class ConeContractDescriptionVisitor<out R, in D> {
|
|||||||
open fun visitBooleanConstantDescriptor(booleanConstantDescriptor: ConeBooleanConstantReference, data: D): R =
|
open fun visitBooleanConstantDescriptor(booleanConstantDescriptor: ConeBooleanConstantReference, data: D): R =
|
||||||
visitConstantDescriptor(booleanConstantDescriptor, data)
|
visitConstantDescriptor(booleanConstantDescriptor, data)
|
||||||
|
|
||||||
|
open fun visitErroneousConstantReference(erroneousConstantReference: ConeErroneousConstantReference, data: D): R =
|
||||||
|
visitConstantDescriptor(erroneousConstantReference, data)
|
||||||
|
|
||||||
open fun visitValueParameterReference(valueParameterReference: ConeValueParameterReference, data: D): R =
|
open fun visitValueParameterReference(valueParameterReference: ConeValueParameterReference, data: D): R =
|
||||||
visitValue(valueParameterReference, data)
|
visitValue(valueParameterReference, data)
|
||||||
|
|
||||||
open fun visitBooleanValueParameterReference(booleanValueParameterReference: ConeBooleanValueParameterReference, data: D): R =
|
open fun visitBooleanValueParameterReference(booleanValueParameterReference: ConeBooleanValueParameterReference, data: D): R =
|
||||||
visitValueParameterReference(booleanValueParameterReference, data)
|
visitValueParameterReference(booleanValueParameterReference, data)
|
||||||
}
|
|
||||||
|
open fun visitErroneousValueParameterReference(valueParameterReference: ConeErroneousValueParameterReference, data: D): R =
|
||||||
|
visitValueParameterReference(valueParameterReference, data)
|
||||||
|
|
||||||
|
// Error
|
||||||
|
open fun visitErroneousElement(element: ConeErroneousContractElement, data: D): R =
|
||||||
|
visitContractDescriptionElement(element, data)
|
||||||
|
}
|
||||||
|
|||||||
+26
-3
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.contracts.description
|
package org.jetbrains.kotlin.fir.contracts.description
|
||||||
|
|
||||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Effect with condition attached to it.
|
* Effect with condition attached to it.
|
||||||
@@ -22,6 +23,9 @@ import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
|||||||
* - if [condition] is true, we *can't* reason that [effect] will be observed.
|
* - if [condition] is true, we *can't* reason that [effect] will be observed.
|
||||||
*/
|
*/
|
||||||
class ConeConditionalEffectDeclaration(val effect: ConeEffectDeclaration, val condition: ConeBooleanExpression) : ConeEffectDeclaration() {
|
class ConeConditionalEffectDeclaration(val effect: ConeEffectDeclaration, val condition: ConeBooleanExpression) : ConeEffectDeclaration() {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = effect.erroneous || condition.erroneous
|
||||||
|
|
||||||
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.visitConditionalEffectDeclaration(this, data)
|
contractDescriptionVisitor.visitConditionalEffectDeclaration(this, data)
|
||||||
}
|
}
|
||||||
@@ -31,9 +35,11 @@ class ConeConditionalEffectDeclaration(val effect: ConeEffectDeclaration, val co
|
|||||||
* Effect which specifies that subroutine returns some particular value
|
* Effect which specifies that subroutine returns some particular value
|
||||||
*/
|
*/
|
||||||
class ConeReturnsEffectDeclaration(val value: ConeConstantReference) : ConeEffectDeclaration() {
|
class ConeReturnsEffectDeclaration(val value: ConeConstantReference) : ConeEffectDeclaration() {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = value.erroneous
|
||||||
|
|
||||||
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.visitReturnsEffectDeclaration(this, data)
|
contractDescriptionVisitor.visitReturnsEffectDeclaration(this, data)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -41,7 +47,24 @@ class ConeReturnsEffectDeclaration(val value: ConeConstantReference) : ConeEffec
|
|||||||
* Effect which specifies, that during execution of subroutine, callable [valueParameterReference] will be invoked
|
* Effect which specifies, that during execution of subroutine, callable [valueParameterReference] will be invoked
|
||||||
* [kind] amount of times, and will never be invoked after subroutine call is finished.
|
* [kind] amount of times, and will never be invoked after subroutine call is finished.
|
||||||
*/
|
*/
|
||||||
class ConeCallsEffectDeclaration(val valueParameterReference: ConeValueParameterReference, val kind: EventOccurrencesRange) : ConeEffectDeclaration() {
|
open class ConeCallsEffectDeclaration(
|
||||||
|
val valueParameterReference: ConeValueParameterReference,
|
||||||
|
val kind: EventOccurrencesRange
|
||||||
|
) : ConeEffectDeclaration() {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = valueParameterReference.erroneous
|
||||||
|
|
||||||
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.visitCallsEffectDeclaration(this, data)
|
contractDescriptionVisitor.visitCallsEffectDeclaration(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ConeErroneousCallsEffectDeclaration(
|
||||||
|
valueParameterReference: ConeValueParameterReference,
|
||||||
|
val diagnostic: ConeDiagnostic
|
||||||
|
) : ConeCallsEffectDeclaration(valueParameterReference, EventOccurrencesRange.UNKNOWN) {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = true
|
||||||
|
|
||||||
|
override fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R =
|
||||||
|
contractDescriptionVisitor.visitErroneousCallsEffectDeclaration(this, data)
|
||||||
|
}
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* 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.contracts.description
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
|
|
||||||
|
class ConeErroneousContractElement(
|
||||||
|
val diagnostic: ConeDiagnostic
|
||||||
|
) : ConeEffectDeclaration(), ConeBooleanExpression, ConeContractDescriptionValue {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = true
|
||||||
|
|
||||||
|
override fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R {
|
||||||
|
return contractDescriptionVisitor.visitErroneousElement(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -8,12 +8,18 @@ package org.jetbrains.kotlin.fir.contracts.description
|
|||||||
import org.jetbrains.kotlin.fir.expressions.LogicOperationKind
|
import org.jetbrains.kotlin.fir.expressions.LogicOperationKind
|
||||||
|
|
||||||
class ConeBinaryLogicExpression(val left: ConeBooleanExpression, val right: ConeBooleanExpression, val kind: LogicOperationKind) : ConeBooleanExpression {
|
class ConeBinaryLogicExpression(val left: ConeBooleanExpression, val right: ConeBooleanExpression, val kind: LogicOperationKind) : ConeBooleanExpression {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = left.erroneous || right.erroneous
|
||||||
|
|
||||||
override fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R {
|
override fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R {
|
||||||
return contractDescriptionVisitor.visitLogicalBinaryOperationContractExpression(this, data)
|
return contractDescriptionVisitor.visitLogicalBinaryOperationContractExpression(this, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConeLogicalNot(val arg: ConeBooleanExpression) : ConeBooleanExpression {
|
class ConeLogicalNot(val arg: ConeBooleanExpression) : ConeBooleanExpression {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = arg.erroneous
|
||||||
|
|
||||||
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.visitLogicalNot(this, data)
|
contractDescriptionVisitor.visitLogicalNot(this, data)
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-2
@@ -5,9 +5,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.contracts.description
|
package org.jetbrains.kotlin.fir.contracts.description
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
|
|
||||||
class ConeIsInstancePredicate(val arg: ConeValueParameterReference, val type: ConeKotlinType, val isNegated: Boolean) : ConeBooleanExpression {
|
open class ConeIsInstancePredicate(val arg: ConeValueParameterReference, val type: ConeKotlinType, val isNegated: Boolean) : ConeBooleanExpression {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = arg.erroneous
|
||||||
|
|
||||||
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.visitIsInstancePredicate(this, data)
|
contractDescriptionVisitor.visitIsInstancePredicate(this, data)
|
||||||
|
|
||||||
@@ -15,10 +19,26 @@ class ConeIsInstancePredicate(val arg: ConeValueParameterReference, val type: Co
|
|||||||
ConeIsInstancePredicate(arg, type, isNegated.not())
|
ConeIsInstancePredicate(arg, type, isNegated.not())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ConeErroneousIsInstancePredicate(
|
||||||
|
arg: ConeValueParameterReference,
|
||||||
|
type: ConeKotlinType,
|
||||||
|
isNegated: Boolean,
|
||||||
|
val diagnostic: ConeDiagnostic
|
||||||
|
) : ConeIsInstancePredicate(arg, type, isNegated) {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = true
|
||||||
|
|
||||||
|
override fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R =
|
||||||
|
contractDescriptionVisitor.visitErroneousIsInstancePredicate(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
class ConeIsNullPredicate(val arg: ConeValueParameterReference, val isNegated: Boolean) : ConeBooleanExpression {
|
class ConeIsNullPredicate(val arg: ConeValueParameterReference, val isNegated: Boolean) : ConeBooleanExpression {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = arg.erroneous
|
||||||
|
|
||||||
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.visitIsNullPredicate(this, data)
|
contractDescriptionVisitor.visitIsNullPredicate(this, data)
|
||||||
|
|
||||||
fun negated(): ConeIsNullPredicate =
|
fun negated(): ConeIsNullPredicate =
|
||||||
ConeIsNullPredicate(arg, isNegated.not())
|
ConeIsNullPredicate(arg, isNegated.not())
|
||||||
}
|
}
|
||||||
|
|||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.contracts.description
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
|
||||||
|
|
||||||
class ConeUnresolvedEffect(val statement: FirStatement)
|
|
||||||
@@ -5,12 +5,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.contracts.description
|
package org.jetbrains.kotlin.fir.contracts.description
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||||
|
|
||||||
interface ConeContractDescriptionValue : ConeContractDescriptionElement {
|
interface ConeContractDescriptionValue : ConeContractDescriptionElement {
|
||||||
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.visitValue(this, data)
|
contractDescriptionVisitor.visitValue(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
open class ConeConstantReference protected constructor(val name: String) : ConeContractDescriptionValue {
|
open class ConeConstantReference protected constructor(val name: String) : ConeContractDescriptionValue {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = false
|
||||||
|
|
||||||
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.visitConstantDescriptor(this, data)
|
contractDescriptionVisitor.visitConstantDescriptor(this, data)
|
||||||
|
|
||||||
@@ -31,6 +36,14 @@ class ConeBooleanConstantReference private constructor(name: String) : ConeConst
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ConeErroneousConstantReference(val diagnostic: ConeDiagnostic) : ConeConstantReference("ERROR") {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = true
|
||||||
|
|
||||||
|
override fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R =
|
||||||
|
contractDescriptionVisitor.visitErroneousConstantReference(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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
|
||||||
@@ -40,6 +53,9 @@ open class ConeValueParameterReference(val parameterIndex: Int, val name: String
|
|||||||
assert(parameterIndex >= -1)
|
assert(parameterIndex >= -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = false
|
||||||
|
|
||||||
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.visitValueParameterReference(this, data)
|
contractDescriptionVisitor.visitValueParameterReference(this, data)
|
||||||
}
|
}
|
||||||
@@ -47,4 +63,12 @@ open class ConeValueParameterReference(val parameterIndex: Int, val name: String
|
|||||||
class ConeBooleanValueParameterReference(parameterIndex: Int, name: String) : ConeValueParameterReference(parameterIndex, name), 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ConeErroneousValueParameterReference(val diagnostic: ConeDiagnostic) : ConeValueParameterReference(Int.MAX_VALUE, "ERROR") {
|
||||||
|
override val erroneous: Boolean
|
||||||
|
get() = true
|
||||||
|
|
||||||
|
override fun <R, D> accept(contractDescriptionVisitor: ConeContractDescriptionVisitor<R, D>, data: D): R =
|
||||||
|
contractDescriptionVisitor.visitErroneousValueParameterReference(this, data)
|
||||||
|
}
|
||||||
|
|||||||
+2
-1
@@ -180,7 +180,8 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
|
|||||||
val intersectionTypeRef by element(TypeRef, typeRefWithNullability)
|
val intersectionTypeRef by element(TypeRef, typeRefWithNullability)
|
||||||
val implicitTypeRef by element(TypeRef, typeRef)
|
val implicitTypeRef by element(TypeRef, typeRef)
|
||||||
|
|
||||||
val effectDeclaration by element(Contracts)
|
val contractElementDeclaration by element(Contracts)
|
||||||
|
val effectDeclaration by element(Contracts, contractElementDeclaration)
|
||||||
|
|
||||||
val contractDescription by element(Contracts)
|
val contractDescription by element(Contracts)
|
||||||
val legacyRawContractDescription by element(Contracts, contractDescription)
|
val legacyRawContractDescription by element(Contracts, contractDescription)
|
||||||
|
|||||||
+2
@@ -562,6 +562,8 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
|||||||
noImpl(argumentList)
|
noImpl(argumentList)
|
||||||
noImpl(annotationArgumentMapping)
|
noImpl(annotationArgumentMapping)
|
||||||
|
|
||||||
|
impl(contractElementDeclaration)
|
||||||
|
|
||||||
val implementationsWithoutStatusAndTypeParameters = listOf(
|
val implementationsWithoutStatusAndTypeParameters = listOf(
|
||||||
"FirAnonymousFunctionImpl",
|
"FirAnonymousFunctionImpl",
|
||||||
"FirValueParameterImpl",
|
"FirValueParameterImpl",
|
||||||
|
|||||||
+5
-1
@@ -732,6 +732,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
|||||||
+field(varianceType)
|
+field(varianceType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contractElementDeclaration.configure {
|
||||||
|
+field("effect", coneContractElementType)
|
||||||
|
}
|
||||||
|
|
||||||
effectDeclaration.configure {
|
effectDeclaration.configure {
|
||||||
+field("effect", coneEffectDeclarationType)
|
+field("effect", coneEffectDeclarationType)
|
||||||
}
|
}
|
||||||
@@ -742,7 +746,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
|||||||
|
|
||||||
resolvedContractDescription.configure {
|
resolvedContractDescription.configure {
|
||||||
+fieldList("effects", effectDeclaration)
|
+fieldList("effects", effectDeclaration)
|
||||||
+fieldList("unresolvedEffects", coneUnresolvedEffect)
|
+fieldList("unresolvedEffects", contractElementDeclaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
legacyRawContractDescription.configure {
|
legacyRawContractDescription.configure {
|
||||||
|
|||||||
+1
-1
@@ -79,11 +79,11 @@ val emptyArgumentListType = type("fir.expressions", "FirEmptyArgumentList")
|
|||||||
val firScopeProviderType = type("fir.scopes", "FirScopeProvider")
|
val firScopeProviderType = type("fir.scopes", "FirScopeProvider")
|
||||||
|
|
||||||
val pureAbstractElementType = generatedType("FirPureAbstractElement")
|
val pureAbstractElementType = generatedType("FirPureAbstractElement")
|
||||||
|
val coneContractElementType = type("fir.contracts.description", "ConeContractDescriptionElement")
|
||||||
val coneEffectDeclarationType = type("fir.contracts.description", "ConeEffectDeclaration")
|
val coneEffectDeclarationType = type("fir.contracts.description", "ConeEffectDeclaration")
|
||||||
val emptyContractDescriptionType = generatedType("contracts.impl", "FirEmptyContractDescription")
|
val emptyContractDescriptionType = generatedType("contracts.impl", "FirEmptyContractDescription")
|
||||||
val coneDiagnosticType = generatedType("diagnostics", "ConeDiagnostic")
|
val coneDiagnosticType = generatedType("diagnostics", "ConeDiagnostic")
|
||||||
val coneStubDiagnosticType = generatedType("diagnostics", "ConeStubDiagnostic")
|
val coneStubDiagnosticType = generatedType("diagnostics", "ConeStubDiagnostic")
|
||||||
val coneUnresolvedEffect = type("fir.contracts.description", "ConeUnresolvedEffect")
|
|
||||||
|
|
||||||
val dslBuilderAnnotationType = generatedType("builder", "FirBuilderDsl")
|
val dslBuilderAnnotationType = generatedType("builder", "FirBuilderDsl")
|
||||||
val firImplementationDetailType = generatedType("FirImplementationDetail")
|
val firImplementationDetailType = generatedType("FirImplementationDetail")
|
||||||
|
|||||||
+2
-2
@@ -5,5 +5,5 @@
|
|||||||
import kotlin.contracts.*
|
import kotlin.contracts.*
|
||||||
|
|
||||||
fun emptyContract() {
|
fun emptyContract() {
|
||||||
contract { }
|
<!ERROR_IN_CONTRACT_DESCRIPTION!>contract { }<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -25,9 +25,9 @@ fun whenInContract(x: Any?, boolean: Boolean) {
|
|||||||
|
|
||||||
fun forInContract(x: Any?) {
|
fun forInContract(x: Any?) {
|
||||||
contract {
|
contract {
|
||||||
for (i in 0..1) {
|
<!ERROR_IN_CONTRACT_DESCRIPTION!>for (i in 0..1) {
|
||||||
returns() implies (x is String)
|
returns() implies (x is String)
|
||||||
}
|
}<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ import kotlin.contracts.*
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 1
|
// TESTCASE NUMBER: 1
|
||||||
inline fun case_1(block: () -> Unit) {
|
inline fun case_1(block: () -> Unit) {
|
||||||
contract { }
|
<!ERROR_IN_CONTRACT_DESCRIPTION!>contract { }<!>
|
||||||
return block()
|
return block()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -11,24 +11,24 @@ object SampleObject {
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 1
|
// TESTCASE NUMBER: 1
|
||||||
inline fun case_1(invocationKind: InvocationKind, block: () -> Unit) {
|
inline fun case_1(invocationKind: InvocationKind, block: () -> Unit) {
|
||||||
contract { callsInPlace(block, invocationKind) }
|
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>callsInPlace(block, invocationKind)<!> }
|
||||||
return block()
|
return block()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TESTCASE NUMBER: 2
|
// TESTCASE NUMBER: 2
|
||||||
inline fun <T : InvocationKind> case_2(invocationKind: T, block: () -> Unit) {
|
inline fun <T : InvocationKind> case_2(invocationKind: T, block: () -> Unit) {
|
||||||
contract { callsInPlace(block, invocationKind) }
|
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>callsInPlace(block, invocationKind)<!> }
|
||||||
return block()
|
return block()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TESTCASE NUMBER: 3
|
// TESTCASE NUMBER: 3
|
||||||
inline fun case_3(block: () -> Unit) {
|
inline fun case_3(block: () -> Unit) {
|
||||||
contract { callsInPlace(block, invocationKind) }
|
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>callsInPlace(block, invocationKind)<!> }
|
||||||
return block()
|
return block()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TESTCASE NUMBER: 4
|
// TESTCASE NUMBER: 4
|
||||||
inline fun case_4(block: () -> Unit) {
|
inline fun case_4(block: () -> Unit) {
|
||||||
contract { callsInPlace(block, SampleObject.invocationKind) }
|
contract { <!ERROR_IN_CONTRACT_DESCRIPTION!>callsInPlace(block, SampleObject.invocationKind)<!> }
|
||||||
return block()
|
return block()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user