diff --git a/build.go b/build.go index 5d17f53..63afcd4 100644 --- a/build.go +++ b/build.go @@ -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. diff --git a/kong_test.go b/kong_test.go index 6b5f5d6..15d1f51 100644 --- a/kong_test.go +++ b/kong_test.go @@ -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