Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow parameter functions to be used in LazyParameterScope, just not declaring them #29

Open
BenWoodworth opened this issue Jul 13, 2024 · 0 comments

Comments

@BenWoodworth
Copy link
Owner

@ParameterizeDsl is used to prevent parameters from being declared in lazy parameter {...} functions, since nesting parameters is not currently supported.

However, a useful pattern that's come up is building on top of other pre-defined parameter functions. As a simple example, parameterOfEncoderVerifyingNbt being defined as a subset of parameterOfVerifyingNbt. Because of @ParameterizeDsl, calling the other parameter function requires an explicit this@parameterOfEncoderVerifyingNbt., even though the parameter isn't actually being declared (with provideDelegate):

internal fun ParameterizeScope.parameterOfEncoderVerifyingNbt(
    includeNamedRootNbt: Boolean = false, // TODO Temporary, since most tests won't support naming until it's redesigned
    builderAction: NbtFormatBuilder.() -> Unit = {}
) = parameter {
    this@parameterOfEncoderVerifyingNbt.parameterOfVerifyingNbt(includeNamedRootNbt, builderAction)
        .arguments.filterIsInstance<EncoderVerifyingNbt>()
}

With the way DslMarkercurrently works in Kotlin, it's not possible to make parameter functions available from ParameterizeScope (through LazyParameterScope) while also disallowing the parameter from being declared.

This can be solved by removing @ParameterizeDsl entirely (which then allows parameter functions to work through scopes), and then add a deprecated Parameter.provideDelegate overload in LazyParameterScope that shadows the normal function. This allows any parameter function to be called anywhere as long as a ParameterizeScope is in scope, while also preventing declaration where it isn't allowed.

@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("Nesting parameters is not currently supported", level = DeprecationLevel.ERROR)
public inline operator fun <T> Parameter<T>.provideDelegate(thisRef: Any?, property: KProperty<*>): ParameterDelegate<T> =
    with (parameterizeScope) { provideDelegate(thisRef, property) }

It's still possible to call the normal provideDelegate, so this isn't 100% compile-time safe, but nested declarations are still checked at runtime, the same goes for @DslMarker anyway (as seen in the code snippet above)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant