improve argument parsing

fail fast by parsing arguments before command execution instead of on demand
This commit is contained in:
2025-12-28 00:16:50 +01:00
parent 79629ae68d
commit f1185886d4
2 changed files with 12 additions and 33 deletions

View File

@@ -12,11 +12,7 @@ class Execution private constructor(
val arguments: List<Arg>,
) {
companion object {
fun from(
command: Command,
cmd: List<String>,
arg: List<String>,
): Execution {
fun from(command: Command, cmd: List<String>, arg: List<String>): Execution {
val commands = Cmd.from(cmd)
val arguments = Arg.from(command, arg)
return Execution(commands, arguments)
@@ -33,7 +29,7 @@ class Execution private constructor(
class Arg(
val name: String,
val value: String?,
val value: Any,
) {
companion object {
fun from(command: Command, arg: List<String>): List<Arg> = buildList {
@@ -68,10 +64,10 @@ class Execution private constructor(
}
for (name in names) {
if (command.arguments.none { name in it.names })
throw UnknownArgumentException(name)
val argument = command.arguments.firstOrNull { name in it.names }
?: throw UnknownArgumentException(name)
//TODO parse early
val value = argument.parser.parse(value) as Any
add(Arg(name, value))
}
i++
@@ -88,26 +84,11 @@ class Execution private constructor(
}
}
operator fun Command.Key.getValue(
thisRef: Any?,
property: KProperty<*>,
): String = commands[index].name
operator fun Command.Key.getValue(thisRef: Any?, property: KProperty<*>): String = commands[index].name
operator fun <T> Argument.Single<T>.getValue(
thisRef: Any?,
property: KProperty<*>,
): T = arguments.single { it.name in names }
.let { parser.parse(it.value) }
operator fun <T> Argument.SingleOrElse<T>.getValue(
thisRef: Any?,
property: KProperty<*>,
): T = arguments.singleOrNull { it.name in names }
?.let { parser.parse(it.value) } ?: other
operator fun <T> Argument.SingleOrNull<T>.getValue(
thisRef: Any?,
property: KProperty<*>,
): T? = arguments.singleOrNull { it.name in names }
?.let { parser.parse(it.value) }
@Suppress("UNCHECKED_CAST")
private fun <T> Argument<T>.getValue(): T? = arguments.firstOrNull { it.name in names }?.value as? T
operator fun <T> Argument.Single<T>.getValue(thisRef: Any?, property: KProperty<*>): T = getValue()!!
operator fun <T> Argument.SingleOrElse<T>.getValue(thisRef: Any?, property: KProperty<*>): T = getValue() ?: other
operator fun <T> Argument.SingleOrNull<T>.getValue(thisRef: Any?, property: KProperty<*>): T? = getValue()
}