summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Flint <[email protected]>2021-05-24 21:50:33 -0700
committerGitHub <[email protected]>2021-05-24 21:50:33 -0700
commiteb0393e9bc0bbd8d3cc37a6ee98c1d538e4e5c91 (patch)
tree560557982ca2baefcfb6157cb9feece14e6b8663
parent679be43af38a865f8318ed9bc3fde7ae424a2dad (diff)
parentfa12c02e81bdff1e9c11ee8a70b938b8c02da6b6 (diff)
Merge pull request #158 from alexflint/unexported-embeddedv1.4.2
Recurse into unexported embedded structs
-rw-r--r--parse.go13
-rw-r--r--parse_test.go23
2 files changed, 33 insertions, 3 deletions
diff --git a/parse.go b/parse.go
index 13e8195..d76ef0f 100644
--- a/parse.go
+++ b/parse.go
@@ -257,17 +257,24 @@ func cmdFromStruct(name string, dest path, t reflect.Type) (*command, error) {
var errs []string
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")
- if tag == "-" || !isExported(field.Name) {
+ if tag == "-" {
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 {
return true
}
+ // ignore any other unexported field
+ if !isExported(field.Name) {
+ return false
+ }
+
// duplicate the entire path to avoid slice overwrites
subdest := dest.Child(field)
spec := spec{
diff --git a/parse_test.go b/parse_test.go
index 695b1d8..e78b4d4 100644
--- a/parse_test.go
+++ b/parse_test.go
@@ -1095,6 +1095,29 @@ func TestEmbeddedWithDuplicateField2(t *testing.T) {
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) {
origArgs := os.Args