-
Notifications
You must be signed in to change notification settings - Fork 4
Allow parameter functions to be used in LazyParameterScope, just not declaring them #29
Description
@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)