feat: Allow ignoring fields from embedded structs (#499)
If a field in a struct is ignored with `kong:"-"`, any embedded fields with the same name are also ignored. This allows an outer struct to remove flags from an embedded struct by redefining it and adding a kong ignore tag.
This commit is contained in:
@@ -54,6 +54,7 @@ func flattenedFields(v reflect.Value, ptag *Tag) (out []flattenedField, err erro
|
||||
if v.Kind() != reflect.Struct {
|
||||
return out, nil
|
||||
}
|
||||
ignored := map[string]bool{}
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
ft := v.Type().Field(i)
|
||||
fv := v.Field(i)
|
||||
@@ -61,7 +62,8 @@ func flattenedFields(v reflect.Value, ptag *Tag) (out []flattenedField, err erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tag.Ignored {
|
||||
if tag.Ignored || ignored[ft.Name] {
|
||||
ignored[ft.Name] = true
|
||||
continue
|
||||
}
|
||||
// Assign group if it's not already set.
|
||||
@@ -106,9 +108,27 @@ func flattenedFields(v reflect.Value, ptag *Tag) (out []flattenedField, err erro
|
||||
}
|
||||
out = append(out, sub...)
|
||||
}
|
||||
out = removeIgnored(out, ignored)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func removeIgnored(fields []flattenedField, ignored map[string]bool) []flattenedField {
|
||||
j := 0
|
||||
for i := 0; i < len(fields); i++ {
|
||||
if ignored[fields[i].field.Name] {
|
||||
continue
|
||||
}
|
||||
if i != j {
|
||||
fields[j] = fields[i]
|
||||
}
|
||||
j++
|
||||
}
|
||||
if j != len(fields) {
|
||||
fields = fields[:j]
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
// Build a Node in the Kong data model.
|
||||
//
|
||||
// "v" is the value to create the node from, "typ" is the output Node type.
|
||||
|
||||
@@ -856,6 +856,43 @@ func TestExcludedField(t *testing.T) {
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestExcludeEmbeddedField(t *testing.T) {
|
||||
type Embedded struct {
|
||||
Flag string
|
||||
Excluded string
|
||||
}
|
||||
type Embedded2 struct {
|
||||
Flag2 string
|
||||
Excluded string
|
||||
}
|
||||
var cli struct {
|
||||
Embedded
|
||||
Excluded string `kong:"-"`
|
||||
Embedded2
|
||||
}
|
||||
var cli2 struct {
|
||||
Embedded Embedded `kong:"embed"`
|
||||
Excluded string `kong:"-"`
|
||||
Embedded2 Embedded2 `kong:"embed"`
|
||||
}
|
||||
|
||||
p := mustNew(t, &cli)
|
||||
_, err := p.Parse([]string{"--flag=foo"})
|
||||
assert.NoError(t, err)
|
||||
_, err = p.Parse([]string{"--flag-2=foo"})
|
||||
assert.NoError(t, err)
|
||||
_, err = p.Parse([]string{"--excluded=foo"})
|
||||
assert.Error(t, err)
|
||||
|
||||
p = mustNew(t, &cli2)
|
||||
_, err = p.Parse([]string{"--flag=foo"})
|
||||
assert.NoError(t, err)
|
||||
_, err = p.Parse([]string{"--flag-2=foo"})
|
||||
assert.NoError(t, err)
|
||||
_, err = p.Parse([]string{"--excluded=foo"})
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestUnnamedFieldEmbeds(t *testing.T) {
|
||||
type Embed struct {
|
||||
Flag string
|
||||
|
||||
Reference in New Issue
Block a user