diff --git a/.golangci.yml b/.golangci.yml index 8e056c9..bb56945 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -33,3 +33,5 @@ issues: - 'Error return value of .(.*\.Help|.*\.MarkFlagRequired|(os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked' - 'exported method (.*\.MarshalJSON|.*\.UnmarshalJSON) should have comment or be unexported' - 'composite literal uses unkeyed fields' + - 'bad syntax for struct tag key' + - 'bad syntax for struct tag pair' diff --git a/build.go b/build.go index 829107c..bd46907 100644 --- a/build.go +++ b/build.go @@ -42,17 +42,22 @@ type flattenedField struct { } func flattenedFields(v reflect.Value) (out []flattenedField) { + v = reflect.Indirect(v) for i := 0; i < v.NumField(); i++ { ft := v.Type().Field(i) fv := v.Field(i) tag := parseTag(fv, ft) if ft.Anonymous { + if fv.Kind() == reflect.Interface { + fv = fv.Elem() + } sub := flattenedFields(fv) - // Assign parent group to children, if they're not otherwise set. for _, subf := range sub { + // Assign parent if it's not already set. if subf.tag.Group == "" { subf.tag.Group = tag.Group } + // Accumulate prefixes. subf.tag.Prefix = tag.Prefix + subf.tag.Prefix } out = append(out, sub...) diff --git a/kong_test.go b/kong_test.go index d77b11e..3863c9e 100644 --- a/kong_test.go +++ b/kong_test.go @@ -590,3 +590,26 @@ func TestAnonymousPrefix(t *testing.T) { require.NoError(t, err) require.Equal(t, "moo", cli.Flag) } + +type TestInterface interface { + SomeMethod() +} + +type TestImpl struct { + Flag string +} + +func (t *TestImpl) SomeMethod() {} + +func TestEmbedInterface(t *testing.T) { + type CLI struct { + SomeFlag string + TestInterface + } + cli := &CLI{TestInterface: &TestImpl{}} + p := mustNew(t, cli) + _, err := p.Parse([]string{"--some-flag=foo", "--flag=yes"}) + require.NoError(t, err) + require.Equal(t, "foo", cli.SomeFlag) + require.Equal(t, "yes", cli.TestInterface.(*TestImpl).Flag) +}