@@ -663,8 +663,7 @@ func main() {
|
||||
## Validation
|
||||
|
||||
Kong does validation on the structure of a command-line, but also supports
|
||||
extensible validation. Any node in the tree may implement the following
|
||||
interface:
|
||||
extensible validation. Any node in the tree may implement either of the following interfaces:
|
||||
|
||||
```go
|
||||
type Validatable interface {
|
||||
@@ -672,6 +671,12 @@ type Validatable interface {
|
||||
}
|
||||
```
|
||||
|
||||
```go
|
||||
type Validatable interface {
|
||||
Validate(kctx *kong.Context) error
|
||||
}
|
||||
```
|
||||
|
||||
If one of these nodes is in the active command-line it will be called during
|
||||
normal validation.
|
||||
|
||||
|
||||
+13
-2
@@ -208,7 +208,7 @@ func (c *Context) Validate() error { //nolint: gocyclo
|
||||
desc = node.Path()
|
||||
}
|
||||
if validate := isValidatable(value); validate != nil {
|
||||
if err := validate.Validate(); err != nil {
|
||||
if err := validate.Validate(c); err != nil {
|
||||
if desc != "" {
|
||||
return fmt.Errorf("%s: %w", desc, err)
|
||||
}
|
||||
@@ -1094,12 +1094,23 @@ func findPotentialCandidates(needle string, haystack []string, format string, ar
|
||||
}
|
||||
|
||||
type validatable interface{ Validate() error }
|
||||
type extendedValidatable interface {
|
||||
Validate(kctx *Context) error
|
||||
}
|
||||
|
||||
func isValidatable(v reflect.Value) validatable {
|
||||
// Proxy a validatable function to the extendedValidatable interface
|
||||
type validatableFunc func() error
|
||||
|
||||
func (f validatableFunc) Validate(kctx *Context) error { return f() }
|
||||
|
||||
func isValidatable(v reflect.Value) extendedValidatable {
|
||||
if !v.IsValid() || (v.Kind() == reflect.Ptr || v.Kind() == reflect.Slice || v.Kind() == reflect.Map) && v.IsNil() {
|
||||
return nil
|
||||
}
|
||||
if validate, ok := v.Interface().(validatable); ok {
|
||||
return validatableFunc(validate.Validate)
|
||||
}
|
||||
if validate, ok := v.Interface().(extendedValidatable); ok {
|
||||
return validate
|
||||
}
|
||||
if v.CanAddr() {
|
||||
|
||||
@@ -1466,6 +1466,19 @@ func TestValidateArg(t *testing.T) {
|
||||
assert.EqualError(t, err, "<arg>: flag error")
|
||||
}
|
||||
|
||||
type extendedValidateFlag string
|
||||
|
||||
func (v *extendedValidateFlag) Validate(kctx *kong.Context) error { return errors.New("flag error") }
|
||||
|
||||
func TestExtendedValidateFlag(t *testing.T) {
|
||||
cli := struct {
|
||||
Flag extendedValidateFlag
|
||||
}{}
|
||||
p := mustNew(t, &cli)
|
||||
_, err := p.Parse([]string{"--flag=one"})
|
||||
assert.EqualError(t, err, "--flag: flag error")
|
||||
}
|
||||
|
||||
func TestPointers(t *testing.T) {
|
||||
cli := struct {
|
||||
Mapped *mappedValue
|
||||
|
||||
Reference in New Issue
Block a user