Panic on duplicate command names (#317)
This commit is contained in:
@@ -158,6 +158,11 @@ MAIN:
|
||||
}
|
||||
}
|
||||
|
||||
// Validate if there are no duplicate names
|
||||
if err := checkDuplicateNames(node, v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// "Unsee" flags.
|
||||
for _, flag := range node.Flags {
|
||||
delete(seenFlags, "--"+flag.Name)
|
||||
@@ -311,3 +316,20 @@ func buildGroupForKey(k *Kong, key string) *Group {
|
||||
Title: key,
|
||||
}
|
||||
}
|
||||
|
||||
func checkDuplicateNames(node *Node, v reflect.Value) error {
|
||||
seenNames := make(map[string]struct{})
|
||||
for _, node := range node.Children {
|
||||
if _, ok := seenNames[node.Name]; ok {
|
||||
name := v.Type().Name()
|
||||
if name == "" {
|
||||
name = "<anonymous struct>"
|
||||
}
|
||||
return fmt.Errorf("duplicate command name %q in command %q", node.Name, name)
|
||||
}
|
||||
|
||||
seenNames[node.Name] = struct{}{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1662,3 +1662,35 @@ func TestMapDecoderHelpfulErrorMsg(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDuplicateName(t *testing.T) {
|
||||
var cli struct {
|
||||
DupA struct{} `cmd:"" name:"duplicate"`
|
||||
DupB struct{} `cmd:"" name:"duplicate"`
|
||||
}
|
||||
_, err := kong.New(&cli)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestDuplicateChildName(t *testing.T) {
|
||||
var cli struct {
|
||||
A struct {
|
||||
DupA struct{} `cmd:"" name:"duplicate"`
|
||||
DupB struct{} `cmd:"" name:"duplicate"`
|
||||
} `cmd:""`
|
||||
B struct{} `cmd:""`
|
||||
}
|
||||
_, err := kong.New(&cli)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestChildNameCanBeDuplicated(t *testing.T) {
|
||||
var cli struct {
|
||||
A struct {
|
||||
A struct{} `cmd:"" name:"duplicateA"`
|
||||
B struct{} `cmd:"" name:"duplicateB"`
|
||||
} `cmd:"" name:"duplicateA"`
|
||||
B struct{} `cmd:"" name:"duplicateB"`
|
||||
}
|
||||
mustNew(t, &cli)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user