Skip to content

Commit

Permalink
🐛 Fix reflect HasField() with anonymous pointer field. (#736)
Browse files Browse the repository at this point in the history
Signed-off-by: Jeff Ortel <[email protected]>
  • Loading branch information
jortel committed Jul 24, 2024
1 parent 73a0668 commit 15b11a8
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
17 changes: 17 additions & 0 deletions reflect/fields.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package reflect

import (
"fmt"
"reflect"
"time"

Expand Down Expand Up @@ -92,6 +93,18 @@ func NameOf(m any) (name string) {
// - db.Omit()
// - db.Select()
func HasFields(m any, in ...string) (out []string, err error) {
defer func() {
p := recover()
if p != nil {
if pe, cast := p.(error); cast {
err = pe
} else {
err = fmt.Errorf(
"(paniced) failed: %#v",
p)
}
}
}()
mp := make(map[string]any)
var inspect func(r any)
inspect = func(r any) {
Expand All @@ -109,6 +122,10 @@ func HasFields(m any, in ...string) (out []string, err error) {
}
switch fv.Kind() {
case reflect.Ptr:
if ft.Anonymous {
inspect(fv.Interface())
continue
}
inst := fv.Interface()
mp[ft.Name] = inst
case reflect.Struct:
Expand Down
72 changes: 72 additions & 0 deletions reflect/reflect_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package reflect

import (
"errors"
"testing"

"github.com/onsi/gomega"
)

func TestHasField(t *testing.T) {
g := gomega.NewGomegaWithT(t)
type B struct {
Name string
Age string
}
type B2 struct {
Name2 string
Age2 string
}
type M struct {
B
*B2
Ptr *B
Object B
Int int
IntPtr *int
List []string
}

// Test expected.
_, err := HasFields(
&M{B2: &B2{}},
"Name",
"Age",
"Name2",
"Age2",
"Ptr",
"Object",
"Int",
"IntPtr",
"List")
g.Expect(err).To(gomega.BeNil())

// Test anonymous NIL pointer.
_, err = HasFields(
&M{}, // PROBLEM HERE.
"Name",
"Age",
"Name2",
"Age2",
"Ptr",
"Object",
"Int",
"IntPtr",
"List")
g.Expect(err).ToNot(gomega.BeNil())

// Invalid field.
_, err = HasFields(
&M{B2: &B2{}},
"Name",
"Age",
"Name2",
"Age2",
"Ptr",
"NOT-VALID", // PROBLEM HERE
"Object",
"Int",
"IntPtr",
"List")
g.Expect(errors.Is(err, &FieldNotValid{})).To(gomega.BeTrue())
}

0 comments on commit 15b11a8

Please sign in to comment.