Skip to content

Commit 9f60a19

Browse files
committed
add location property to ValueSource.Invocation
allowing more useful help messages upon transform failure.
1 parent b62d41d commit 9f60a19

File tree

4 files changed

+72
-10
lines changed

4 files changed

+72
-10
lines changed

clikt/api/clikt.api

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,18 +1457,23 @@ public final class com/github/ajalt/clikt/sources/ValueSource$Companion {
14571457

14581458
public final class com/github/ajalt/clikt/sources/ValueSource$Invocation {
14591459
public static final field Companion Lcom/github/ajalt/clikt/sources/ValueSource$Invocation$Companion;
1460-
public fun <init> (Ljava/util/List;)V
1460+
public fun <init> (Ljava/util/List;Ljava/lang/String;)V
1461+
public synthetic fun <init> (Ljava/util/List;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
14611462
public final fun component1 ()Ljava/util/List;
1462-
public final fun copy (Ljava/util/List;)Lcom/github/ajalt/clikt/sources/ValueSource$Invocation;
1463-
public static synthetic fun copy$default (Lcom/github/ajalt/clikt/sources/ValueSource$Invocation;Ljava/util/List;ILjava/lang/Object;)Lcom/github/ajalt/clikt/sources/ValueSource$Invocation;
1463+
public final fun component2 ()Ljava/lang/String;
1464+
public final fun copy (Ljava/util/List;Ljava/lang/String;)Lcom/github/ajalt/clikt/sources/ValueSource$Invocation;
1465+
public static synthetic fun copy$default (Lcom/github/ajalt/clikt/sources/ValueSource$Invocation;Ljava/util/List;Ljava/lang/String;ILjava/lang/Object;)Lcom/github/ajalt/clikt/sources/ValueSource$Invocation;
14641466
public fun equals (Ljava/lang/Object;)Z
1467+
public final fun getLocation ()Ljava/lang/String;
14651468
public final fun getValues ()Ljava/util/List;
14661469
public fun hashCode ()I
14671470
public fun toString ()Ljava/lang/String;
14681471
}
14691472

14701473
public final class com/github/ajalt/clikt/sources/ValueSource$Invocation$Companion {
1471-
public final fun just (Ljava/lang/Object;)Ljava/util/List;
1472-
public final fun value (Ljava/lang/Object;)Lcom/github/ajalt/clikt/sources/ValueSource$Invocation;
1474+
public final fun just (Ljava/lang/Object;Ljava/lang/String;)Ljava/util/List;
1475+
public static synthetic fun just$default (Lcom/github/ajalt/clikt/sources/ValueSource$Invocation$Companion;Ljava/lang/Object;Ljava/lang/String;ILjava/lang/Object;)Ljava/util/List;
1476+
public final fun value (Ljava/lang/Object;Ljava/lang/String;)Lcom/github/ajalt/clikt/sources/ValueSource$Invocation;
1477+
public static synthetic fun value$default (Lcom/github/ajalt/clikt/sources/ValueSource$Invocation$Companion;Ljava/lang/Object;Ljava/lang/String;ILjava/lang/Object;)Lcom/github/ajalt/clikt/sources/ValueSource$Invocation;
14731478
}
14741479

clikt/src/commonMain/kotlin/com/github/ajalt/clikt/parameters/options/Option.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ internal fun Option.hasEnvvarOrSourcedValue(
174174

175175
private fun Option.readValueSource(context: Context): List<OptionInvocation>? {
176176
return context.valueSource?.getValues(context, this)
177-
?.map { OptionInvocation("", it.values) }
177+
?.map { OptionInvocation(it.location, it.values) }
178178
?.ifEmpty { null }
179179
}
180180

clikt/src/commonMain/kotlin/com/github/ajalt/clikt/sources/ValueSource.kt

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
package com.github.ajalt.clikt.sources
22

33
import com.github.ajalt.clikt.core.Context
4-
import com.github.ajalt.clikt.parameters.options.*
4+
import com.github.ajalt.clikt.parameters.options.Option
5+
import com.github.ajalt.clikt.parameters.options.OptionWithValues
6+
import com.github.ajalt.clikt.parameters.options.inferEnvvar
7+
import com.github.ajalt.clikt.parameters.options.longestName
8+
import com.github.ajalt.clikt.parameters.options.splitOptionPrefix
9+
import com.github.ajalt.clikt.sources.ValueSource.Companion.name
510

611
interface ValueSource {
7-
data class Invocation(val values: List<String>) {
12+
/**
13+
* @property location A pointer to where the invocation's values were retrieved from. Useful for indicating where
14+
* a failure occurred in error help messages.
15+
*/
16+
data class Invocation(val values: List<String>, val location: String = "") {
817
companion object {
918
/** Create a list of a single Invocation with a single value */
10-
fun just(value: Any?): List<Invocation> = listOf(value(value))
19+
fun just(value: Any?, location: String = ""): List<Invocation> =
20+
listOf(value(value = value, location = location))
1121

1222
/** Create an Invocation with a single value */
13-
fun value(value: Any?): Invocation = Invocation(listOf(value.toString()))
23+
fun value(value: Any?, location: String = ""): Invocation =
24+
Invocation(values = listOf(value.toString()), location = location)
1425
}
1526
}
1627

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.github.ajalt.clikt.sources
2+
3+
import com.github.ajalt.clikt.core.BadParameterValue
4+
import com.github.ajalt.clikt.core.Context
5+
import com.github.ajalt.clikt.parameters.options.Option
6+
import com.github.ajalt.clikt.parameters.options.option
7+
import com.github.ajalt.clikt.parameters.types.int
8+
import com.github.ajalt.clikt.testing.TestCommand
9+
import com.github.ajalt.clikt.testing.formattedMessage
10+
import com.github.ajalt.clikt.testing.parse
11+
import io.kotest.assertions.throwables.shouldThrow
12+
import io.kotest.matchers.shouldBe
13+
import kotlin.test.Test
14+
15+
class ValueSourceTest {
16+
@Test
17+
fun `parameter name can be provided to invocation`() {
18+
class C : TestCommand() {
19+
@Suppress("unused")
20+
val theInteger by option("-i").int()
21+
}
22+
23+
val sourceWithoutParameterName = object : ValueSource {
24+
override fun getValues(
25+
context: Context,
26+
option: Option
27+
): List<ValueSource.Invocation> = ValueSource.Invocation.just(value = "foo")
28+
}
29+
30+
val sourceWithParameterName = object : ValueSource {
31+
override fun getValues(
32+
context: Context,
33+
option: Option
34+
): List<ValueSource.Invocation> =
35+
ValueSource.Invocation.just(value = "foo", location = "value_source_option")
36+
}
37+
38+
shouldThrow<BadParameterValue> {
39+
C().apply { configureContext { valueSource = sourceWithoutParameterName } }.parse("")
40+
}.formattedMessage shouldBe "invalid value: foo is not a valid integer"
41+
42+
shouldThrow<BadParameterValue> {
43+
C().apply { configureContext { valueSource = sourceWithParameterName } }.parse("")
44+
}.formattedMessage shouldBe "invalid value for value_source_option: foo is not a valid integer"
45+
}
46+
}

0 commit comments

Comments
 (0)