Much more thorough checking of enum values.
This commit is contained in:
+31
-6
@@ -135,13 +135,10 @@ func (c *Context) Empty() bool {
|
|||||||
func (c *Context) Validate() error {
|
func (c *Context) Validate() error {
|
||||||
err := Visit(c.Model, func(node Visitable, next Next) error {
|
err := Visit(c.Model, func(node Visitable, next Next) error {
|
||||||
if value, ok := node.(*Value); ok {
|
if value, ok := node.(*Value); ok {
|
||||||
if value.Enum != "" && !value.EnumMap()[fmt.Sprintf("%v", value.Target.Interface())] {
|
if value.Enum != "" {
|
||||||
enums := []string{}
|
if err := checkEnum(value, value.Target); err != nil {
|
||||||
for enum := range value.EnumMap() {
|
return err
|
||||||
enums = append(enums, fmt.Sprintf("%q", enum))
|
|
||||||
}
|
}
|
||||||
sort.Strings(enums)
|
|
||||||
return fmt.Errorf("%s must be one of %s but got %q", value.ShortSummary(), strings.Join(enums, ","), value.Target.Interface())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return next(nil)
|
return next(nil)
|
||||||
@@ -646,6 +643,34 @@ func checkMissingPositionals(positional int, values []*Value) error {
|
|||||||
return fmt.Errorf("missing positional arguments %s", strings.Join(missing, " "))
|
return fmt.Errorf("missing positional arguments %s", strings.Join(missing, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkEnum(value *Value, target reflect.Value) error {
|
||||||
|
switch target.Kind() {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
for i := 0; i < target.Len(); i++ {
|
||||||
|
if err := checkEnum(value, target.Index(i)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case reflect.Map, reflect.Struct:
|
||||||
|
return errors.Errorf("enum can only be applied to a slice or value")
|
||||||
|
|
||||||
|
default:
|
||||||
|
enumMap := value.EnumMap()
|
||||||
|
v := fmt.Sprintf("%v", target)
|
||||||
|
if enumMap[v] {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
enums := []string{}
|
||||||
|
for enum := range enumMap {
|
||||||
|
enums = append(enums, fmt.Sprintf("%q", enum))
|
||||||
|
}
|
||||||
|
sort.Strings(enums)
|
||||||
|
return fmt.Errorf("%s must be one of %s but got %q", value.ShortSummary(), strings.Join(enums, ","), target.Interface())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func checkXorDuplicates(paths []*Path) error {
|
func checkXorDuplicates(paths []*Path) error {
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
seen := map[string]*Flag{}
|
seen := map[string]*Flag{}
|
||||||
|
|||||||
@@ -781,3 +781,13 @@ func TestXorChild(t *testing.T) {
|
|||||||
_, err = p.Parse([]string{"--two=hi", "cmd", "--three"})
|
_, err = p.Parse([]string{"--two=hi", "cmd", "--three"})
|
||||||
require.Error(t, err, "--two and --three can't be used together")
|
require.Error(t, err, "--two and --three can't be used together")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEnumSequence(t *testing.T) {
|
||||||
|
var cli struct {
|
||||||
|
State []string `enum:"a,b,c" default:"a"`
|
||||||
|
}
|
||||||
|
p := mustNew(t, &cli)
|
||||||
|
_, err := p.Parse(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, []string{"a"}, cli.State)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user