Merge pull request #158 from alexflint/unexported-embedded
Recurse into unexported embedded structs
This commit is contained in:
commit
eb0393e9bc
13
parse.go
13
parse.go
|
@ -257,17 +257,24 @@ func cmdFromStruct(name string, dest path, t reflect.Type) (*command, error) {
|
||||||
|
|
||||||
var errs []string
|
var errs []string
|
||||||
walkFields(t, func(field reflect.StructField, t reflect.Type) bool {
|
walkFields(t, func(field reflect.StructField, t reflect.Type) bool {
|
||||||
// Check for the ignore switch in the tag
|
// check for the ignore switch in the tag
|
||||||
tag := field.Tag.Get("arg")
|
tag := field.Tag.Get("arg")
|
||||||
if tag == "-" || !isExported(field.Name) {
|
if tag == "-" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is an embedded struct then recurse into its fields
|
// if this is an embedded struct then recurse into its fields, even if
|
||||||
|
// it is unexported, because exported fields on unexported embedded
|
||||||
|
// structs are still writable
|
||||||
if field.Anonymous && field.Type.Kind() == reflect.Struct {
|
if field.Anonymous && field.Type.Kind() == reflect.Struct {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore any other unexported field
|
||||||
|
if !isExported(field.Name) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// duplicate the entire path to avoid slice overwrites
|
// duplicate the entire path to avoid slice overwrites
|
||||||
subdest := dest.Child(field)
|
subdest := dest.Child(field)
|
||||||
spec := spec{
|
spec := spec{
|
||||||
|
|
|
@ -1095,6 +1095,29 @@ func TestEmbeddedWithDuplicateField2(t *testing.T) {
|
||||||
assert.Equal(t, "", args.U.A)
|
assert.Equal(t, "", args.U.A)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnexportedEmbedded(t *testing.T) {
|
||||||
|
type embeddedArgs struct {
|
||||||
|
Foo string
|
||||||
|
}
|
||||||
|
var args struct {
|
||||||
|
embeddedArgs
|
||||||
|
}
|
||||||
|
err := parse("--foo bar", &args)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "bar", args.Foo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIgnoredEmbedded(t *testing.T) {
|
||||||
|
type embeddedArgs struct {
|
||||||
|
Foo string
|
||||||
|
}
|
||||||
|
var args struct {
|
||||||
|
embeddedArgs `arg:"-"`
|
||||||
|
}
|
||||||
|
err := parse("--foo bar", &args)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestEmptyArgs(t *testing.T) {
|
func TestEmptyArgs(t *testing.T) {
|
||||||
origArgs := os.Args
|
origArgs := os.Args
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue