From dad5a62b4a778b7426473b05c0bf93c8aff038cc Mon Sep 17 00:00:00 2001 From: David Hoepelman Date: Fri, 15 Nov 2024 14:35:38 +0100 Subject: [PATCH 1/2] Open up ValidationBuilder for extension --- .../konform/validation/ValidationBuilder.kt | 3 +- .../io/konform/validation/ValidationResult.kt | 4 +- .../ExtendingValidationBuilderTest.kt | 53 +++++++++++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/commonTest/kotlin/io/konform/validation/validationbuilder/ExtendingValidationBuilderTest.kt diff --git a/src/commonMain/kotlin/io/konform/validation/ValidationBuilder.kt b/src/commonMain/kotlin/io/konform/validation/ValidationBuilder.kt index 59f8fec..3ae43bc 100644 --- a/src/commonMain/kotlin/io/konform/validation/ValidationBuilder.kt +++ b/src/commonMain/kotlin/io/konform/validation/ValidationBuilder.kt @@ -20,7 +20,8 @@ import kotlin.reflect.KProperty1 private annotation class ValidationScope @ValidationScope -public class ValidationBuilder { +// Class is open to users can define their extra local extension methods +public open class ValidationBuilder { private val constraints = mutableListOf>() private val subValidations = mutableListOf>() diff --git a/src/commonMain/kotlin/io/konform/validation/ValidationResult.kt b/src/commonMain/kotlin/io/konform/validation/ValidationResult.kt index 3e436c0..7114f28 100644 --- a/src/commonMain/kotlin/io/konform/validation/ValidationResult.kt +++ b/src/commonMain/kotlin/io/konform/validation/ValidationResult.kt @@ -35,9 +35,9 @@ public sealed class ValidationResult { } } - internal abstract fun prependPath(pathSegment: PathSegment): ValidationResult + public abstract fun prependPath(pathSegment: PathSegment): ValidationResult - internal abstract fun prependPath(path: ValidationPath): ValidationResult + public abstract fun prependPath(path: ValidationPath): ValidationResult } public data class Invalid( diff --git a/src/commonTest/kotlin/io/konform/validation/validationbuilder/ExtendingValidationBuilderTest.kt b/src/commonTest/kotlin/io/konform/validation/validationbuilder/ExtendingValidationBuilderTest.kt new file mode 100644 index 0000000..193bf5d --- /dev/null +++ b/src/commonTest/kotlin/io/konform/validation/validationbuilder/ExtendingValidationBuilderTest.kt @@ -0,0 +1,53 @@ +package io.konform.validation.validationbuilder + +import io.konform.validation.Validation +import io.konform.validation.ValidationBuilder +import io.konform.validation.ValidationError +import io.konform.validation.constraints.minLength +import io.konform.validation.path.ValidationPath +import io.kotest.assertions.konform.shouldBeInvalid +import io.kotest.assertions.konform.shouldBeValid +import io.kotest.assertions.konform.shouldContainExactlyErrors +import kotlin.reflect.KProperty1 +import kotlin.test.Test + +class ExtendingValidationBuilderTest { + @Test + fun allowsExtending() { + val validation = + MyValidationBuilder { + User::name trimmed { + minLength(1) + } + } + + validation shouldBeValid User("John") + (validation shouldBeInvalid User("")).shouldContainExactlyErrors( + ValidationError.of(User::name, "must have at least 1 characters"), + ) + (validation shouldBeInvalid User("\t")).shouldContainExactlyErrors( + ValidationError.of(User::name, "must have at least 1 characters"), + ) + } +} + +data class User( + val name: String, +) + +class MyValidationBuilder : ValidationBuilder() { + infix fun KProperty1.trimmed(init: ValidationBuilder.() -> Unit): Unit = + this { + validate(ValidationPath.EMPTY, { it.trim() }) { + run(buildWithNew(init)) + } + } + + companion object { + operator fun invoke(init: MyValidationBuilder.() -> Unit): Validation { + val builder = MyValidationBuilder() + init(builder) + return builder.build() + } + } +} From de88c881be0ba7400399416cb2fa01e4d3672791 Mon Sep 17 00:00:00 2001 From: David Hoepelman Date: Fri, 15 Nov 2024 15:02:16 +0100 Subject: [PATCH 2/2] Add fieldref --- api/konform.api | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/api/konform.api b/api/konform.api index 29e9ae1..32058f0 100644 --- a/api/konform.api +++ b/api/konform.api @@ -33,8 +33,10 @@ public final class io/konform/validation/Invalid : io/konform/validation/Validat public fun getErrors ()Ljava/util/List; public fun hashCode ()I public fun isValid ()Z - public synthetic fun prependPath$konform (Lio/konform/validation/path/PathSegment;)Lio/konform/validation/ValidationResult; - public synthetic fun prependPath$konform (Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/ValidationResult; + public fun prependPath (Lio/konform/validation/path/PathSegment;)Lio/konform/validation/Invalid; + public synthetic fun prependPath (Lio/konform/validation/path/PathSegment;)Lio/konform/validation/ValidationResult; + public fun prependPath (Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/Invalid; + public synthetic fun prependPath (Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/ValidationResult; public fun toString ()Ljava/lang/String; } @@ -52,6 +54,8 @@ public final class io/konform/validation/Valid : io/konform/validation/Validatio public final fun getValue ()Ljava/lang/Object; public fun hashCode ()I public fun isValid ()Z + public fun prependPath (Lio/konform/validation/path/PathSegment;)Lio/konform/validation/ValidationResult; + public fun prependPath (Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/ValidationResult; public fun toString ()Ljava/lang/String; } @@ -73,7 +77,7 @@ public final class io/konform/validation/Validation$DefaultImpls { public static fun prependPath (Lio/konform/validation/Validation;Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/Validation; } -public final class io/konform/validation/ValidationBuilder { +public class io/konform/validation/ValidationBuilder { public static final field Companion Lio/konform/validation/ValidationBuilder$Companion; public fun ()V public final fun addConstraint (Ljava/lang/String;[Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lio/konform/validation/Constraint; @@ -154,6 +158,8 @@ public abstract class io/konform/validation/ValidationResult { public abstract fun isValid ()Z public final fun map (Lkotlin/jvm/functions/Function1;)Lio/konform/validation/ValidationResult; public final fun plus (Lio/konform/validation/ValidationResult;)Lio/konform/validation/ValidationResult; + public abstract fun prependPath (Lio/konform/validation/path/PathSegment;)Lio/konform/validation/ValidationResult; + public abstract fun prependPath (Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/ValidationResult; } public final class io/konform/validation/ValidationResultKt {