konform-kt / konform

Portable validations for Kotlin
https://www.konform.io
MIT License
651 stars 39 forks source link

add function and lambda accessor syntax #65

Open NikkyAI opened 1 year ago

NikkyAI commented 1 year ago

may be a partial duplicate of #63 but have this code anyhow.. maybe it helps even a little bit

this allows validations of java libraries without needing to write a val ThatClass.someValue = getSomeValue() extensions for each property

it also allows to use aliased custom accessors

a example out of our codebase using this to validate com.nimbusds.jwt.SignedJWT

fun ValidationBuilder<SignedJWT>.hasSubject(expectedSubject: String) {
    SignedJWT::getJWTClaimsSet required {
        JWTClaimsSet::getSubject required {
            addConstraint("subject must be '{0}'", expectedSubject) { subject ->
                subject == expectedSubject
            }
        }

    }
}

fun ValidationBuilder<SignedJWT>.hasClaimWithValue(claim: String, expected: String) {
    SignedJWT::getJWTClaimsSet required {
        val accessClaim = { it: JWTClaimsSet ->
            it.getStringClaim(claim) ?: null
        }
        accessClaim.required("getStringClaim($claim)") {
            addConstraint(
                "claim '{0}' must be '{1}'",
                claim,
                expected
            ) { value ->
                value == expected
            }
        }
    }
}

i added tests functionAccessorSyntax, lambdaAccessorSyntax, complexLambdaAccessors to demonstrate usage of this syntax

dhoepelman commented 4 months ago

Looks interesting, I have definitely encountered this. On my list to review for inclusion

dhoepelman commented 3 months ago

If we wait long enough this will likely be solved by Kotlin itself, synthetic java accessors are scheduled for kotlin 2.1: https://youtrack.jetbrains.com/issue/KT-8575/Support-Java-synthetic-property-references. It's currently available behind a language version feature flag, although I don't know the right incantation for 1.9 or 2.0.

Still, allowing constraints to be specified for any function/lambda seems a good feature to have in general, if only because I find it annoying to not be able to easily specify constraints on nested things. Supporting KFunction in addition to KProperty also makes a lot of sense.

dhoepelman commented 3 months ago

Fixes #14

NikkyAI commented 3 months ago

yep, I think this works for us

elijah-pl commented 2 months ago

This issue you may find interesting 🙂 Having options for Kotlin pre-2.1 would be great though! https://youtrack.jetbrains.com/issue/KT-8575/Support-Java-synthetic-property-references