Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cumulative argument needs to be last #331

Merged
merged 2 commits into from Sep 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 20 additions & 4 deletions build.go
Expand Up @@ -171,17 +171,33 @@ MAIN:
}
}

// Scan through argument positionals to ensure optional is never before a required.
if err := validatePositionalArguments(node); err != nil {
return nil, err
}

return node, nil
}

func validatePositionalArguments(node *Node) error {
var last *Value
for i, curr := range node.Positional {
if last != nil && !last.Required && curr.Required {
return nil, fmt.Errorf("%s: required %q can not come after optional %q", node.FullPath(), curr.Name, last.Name)
if last != nil {
// Scan through argument positionals to ensure optional is never before a required.
if !last.Required && curr.Required {
return fmt.Errorf("%s: required %q cannot come after optional %q", node.FullPath(), curr.Name, last.Name)
}

// Cumulative argument needs to be last.
if last.IsCumulative() {
return fmt.Errorf("%s: argument %q cannot come after cumulative %q", node.FullPath(), curr.Name, last.Name)
}
}

last = curr
curr.Position = i
}

return node, nil
return nil
}

func buildChild(k *Kong, node *Node, typ NodeType, v reflect.Value, ft reflect.StructField, fv reflect.Value, tag *Tag, name string, seenFlags map[string]bool) error {
Expand Down
18 changes: 18 additions & 0 deletions kong_test.go
Expand Up @@ -1718,3 +1718,21 @@ func TestChildNameCanBeDuplicated(t *testing.T) {
}
mustNew(t, &cli)
}

func TestCumulativeArgumentLast(t *testing.T) {
var cli struct {
Arg1 string `arg:""`
Arg2 []string `arg:""`
}
_, err := kong.New(&cli)
assert.NoError(t, err)
}

func TestCumulativeArgumentNotLast(t *testing.T) {
var cli struct {
Arg2 []string `arg:""`
Arg1 string `arg:""`
}
_, err := kong.New(&cli)
assert.Error(t, err)
}