diff --git a/libraries/stdlib/src/kotlin/contracts/ContractBuilder.kt b/libraries/stdlib/src/kotlin/contracts/ContractBuilder.kt index fb540a5ac1d..42200dc3e41 100644 --- a/libraries/stdlib/src/kotlin/contracts/ContractBuilder.kt +++ b/libraries/stdlib/src/kotlin/contracts/ContractBuilder.kt @@ -8,31 +8,119 @@ package kotlin.contracts import kotlin.internal.ContractsDsl import kotlin.internal.InlineOnly +/** + * Marker of the use experimental contracts API. + * Any declaration annotated with that marker must be used with the [UseExperimental] annotation + * or the compiler argument `-Xuse-experimental=kotlin.contracts.ExperimentalContracts`. + */ @Retention(AnnotationRetention.BINARY) @SinceKotlin("1.3") @Experimental public annotation class ExperimentalContracts +/** + * The builder is used to specify contract effects for some function. + * + * @see contract + */ @ContractsDsl @ExperimentalContracts @SinceKotlin("1.3") public interface ContractBuilder { + /** + * Expresses that a function returned successfully. + * + * @sample samples.contracts.returnsContract + */ @ContractsDsl public fun returns(): Returns + + /** + * Expresses that a function returned with some value. + * Value can only be `true`, `false` or `null`. + * + * @sample samples.contracts.returnsTrueContract + * @sample samples.contracts.returnsFalseContract + * @sample samples.contracts.returnsNullContract + */ @ContractsDsl public fun returns(value: Any?): Returns + + /** + * Expresses that a function returned with any not null value. + * + * @sample samples.contracts.returnsNotNullContract + */ @ContractsDsl public fun returnsNotNull(): ReturnsNotNull + + /** + * Expresses that: + * 1) [lambda] will not be called after the call to owner-function is finished; + * 2) [lambda] will not be passed to another function without the similar contract. + * + * @param kind amount of times, that a [lambda] guaranteed will be invoked. + * + * Note that a function with the `callsInPlace` effect must be inline. + * + * @sample samples.contracts.callsInPlaceAtMostOnceContract + * @sample samples.contracts.callsInPlaceAtLeastOnceContract + * @sample samples.contracts.callsInPlaceExactlyOnceContract + * @sample samples.contracts.callsInPlaceUnknownContract + */ @ContractsDsl public fun callsInPlace(lambda: Function, kind: InvocationKind = InvocationKind.UNKNOWN): CallsInPlace } +/** + * This enum class is used to specify the amount of times, that `callable` which is used in the [ContractBuilder.callsInPlace] effect guaranteed will be invoked. + */ @ContractsDsl @ExperimentalContracts @SinceKotlin("1.3") public enum class InvocationKind { + /** + * Expresses that the `callable` will be invoked zero or one time. + * + * @sample samples.contracts.callsInPlaceAtMostOnceContract + */ @ContractsDsl AT_MOST_ONCE, + + /** + * Expresses that the `callable` will be invoked one or more times. + * + * @sample samples.contracts.callsInPlaceAtLeastOnceContract + */ @ContractsDsl AT_LEAST_ONCE, + + /** + * Expresses that the `callable` will be invoked exactly one time. + * + * @sample samples.contracts.callsInPlaceExactlyOnceContract + */ @ContractsDsl EXACTLY_ONCE, + + /** + * Expresses that the `callable` will be invoked unknown amount of times. + * + * @sample samples.contracts.callsInPlaceUnknownContract + */ @ContractsDsl UNKNOWN } +/** + * The function to describe a contract. + * The contract description must be at the beginning of a function and has at least one effect. + * Also the contract description can be used only in the top-level functions. + * + * @param builder the lambda in the body of which the effects from the [ContractBuilder] are specified. + * + * @sample samples.contracts.returnsContract + * @sample samples.contracts.returnsTrueContract + * @sample samples.contracts.returnsFalseContract + * @sample samples.contracts.returnsNullContract + * @sample samples.contracts.returnsNotNullContract + * @sample samples.contracts.callsInPlaceAtMostOnceContract + * @sample samples.contracts.callsInPlaceAtLeastOnceContract + * @sample samples.contracts.callsInPlaceExactlyOnceContract + * @sample samples.contracts.callsInPlaceUnknownContract + */ @ContractsDsl @ExperimentalContracts @InlineOnly diff --git a/libraries/stdlib/src/kotlin/contracts/Effect.kt b/libraries/stdlib/src/kotlin/contracts/Effect.kt index 2550ad0d0d1..90269498338 100644 --- a/libraries/stdlib/src/kotlin/contracts/Effect.kt +++ b/libraries/stdlib/src/kotlin/contracts/Effect.kt @@ -12,31 +12,62 @@ import kotlin.internal.ContractsDsl @SinceKotlin("1.3") public interface Effect +/** + * This interface corresponds to an additional condition applied to the [SimpleEffect]. + * Can only be used in conjunction with [SimpleEffect]. + * + * @see SimpleEffect.implies + */ @ContractsDsl @ExperimentalContracts @SinceKotlin("1.3") public interface ConditionalEffect : Effect +/** + * Describes of function's behavior regardless of any conditions. + */ @ContractsDsl @ExperimentalContracts @SinceKotlin("1.3") public interface SimpleEffect { + /** + * The function to specify an additional condition for some `SimpleEffect`. + * + * @param booleanExpression the additional condition which is a subset of the Kotlin boolean expressions. + * + * Note: the subset of the Kotlin boolean expressions is true/false/null checks (using the equality expression) for a function parameter or receiver, also allowed the conjunction and disjunction. + */ @ContractsDsl @ExperimentalContracts public infix fun implies(booleanExpression: Boolean): ConditionalEffect } - +/** + * Describes the return value of a function. + * The return value can only be `true`, `false` or `null`. + * + * @see ContractBuilder.returns + */ @ContractsDsl @ExperimentalContracts @SinceKotlin("1.3") public interface Returns : SimpleEffect +/** + * Describes that the return value of a function is not null. + * + * @see ContractBuilder.returnsNotNull + */ @ContractsDsl @ExperimentalContracts @SinceKotlin("1.3") public interface ReturnsNotNull : SimpleEffect +/** + * Describes of function's behavior in relation to the invocation of the received lambda. + * + * @see ContractBuilder.callsInPlace + */ @ContractsDsl @ExperimentalContracts @SinceKotlin("1.3")