Support for embedding interfaces.
This commit is contained in:
@@ -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'
|
- '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'
|
- 'exported method (.*\.MarshalJSON|.*\.UnmarshalJSON) should have comment or be unexported'
|
||||||
- 'composite literal uses unkeyed fields'
|
- 'composite literal uses unkeyed fields'
|
||||||
|
- 'bad syntax for struct tag key'
|
||||||
|
- 'bad syntax for struct tag pair'
|
||||||
|
|||||||
@@ -42,17 +42,22 @@ type flattenedField struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func flattenedFields(v reflect.Value) (out []flattenedField) {
|
func flattenedFields(v reflect.Value) (out []flattenedField) {
|
||||||
|
v = reflect.Indirect(v)
|
||||||
for i := 0; i < v.NumField(); i++ {
|
for i := 0; i < v.NumField(); i++ {
|
||||||
ft := v.Type().Field(i)
|
ft := v.Type().Field(i)
|
||||||
fv := v.Field(i)
|
fv := v.Field(i)
|
||||||
tag := parseTag(fv, ft)
|
tag := parseTag(fv, ft)
|
||||||
if ft.Anonymous {
|
if ft.Anonymous {
|
||||||
|
if fv.Kind() == reflect.Interface {
|
||||||
|
fv = fv.Elem()
|
||||||
|
}
|
||||||
sub := flattenedFields(fv)
|
sub := flattenedFields(fv)
|
||||||
// Assign parent group to children, if they're not otherwise set.
|
|
||||||
for _, subf := range sub {
|
for _, subf := range sub {
|
||||||
|
// Assign parent if it's not already set.
|
||||||
if subf.tag.Group == "" {
|
if subf.tag.Group == "" {
|
||||||
subf.tag.Group = tag.Group
|
subf.tag.Group = tag.Group
|
||||||
}
|
}
|
||||||
|
// Accumulate prefixes.
|
||||||
subf.tag.Prefix = tag.Prefix + subf.tag.Prefix
|
subf.tag.Prefix = tag.Prefix + subf.tag.Prefix
|
||||||
}
|
}
|
||||||
out = append(out, sub...)
|
out = append(out, sub...)
|
||||||
|
|||||||
@@ -590,3 +590,26 @@ func TestAnonymousPrefix(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "moo", cli.Flag)
|
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)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user