mirror of
https://github.com/hanzoai/expr.git
synced 2026-09-24 16:58:58 +00:00
Fix: checker panic on embedded pointer to struct field (#500)
* add failing test case: embedded pointer to struct * fix(dereference embedded pointers to structs) * add evaluation test for field access and method call on embedded pointer struct
This commit is contained in:
committed by
GitHub
parent
d61d849c39
commit
3426d4bcce
@@ -131,6 +131,7 @@ func TestCheck(t *testing.T) {
|
||||
{"(Any.Bool ?? Bool) > 0"},
|
||||
{"Bool ?? Bool"},
|
||||
{"let foo = 1; foo == 1"},
|
||||
{"(Embed).EmbedPointerEmbedInt > 0"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
+5
-1
@@ -192,7 +192,11 @@ func fetchField(t reflect.Type, name string) (reflect.StructField, bool) {
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
anon := t.Field(i)
|
||||
if anon.Anonymous {
|
||||
if field, ok := fetchField(anon.Type, name); ok {
|
||||
anonType := anon.Type
|
||||
for anonType.Kind() == reflect.Pointer {
|
||||
anonType = anonType.Elem()
|
||||
}
|
||||
if field, ok := fetchField(anonType, name); ok {
|
||||
field.Index = append(anon.Index, field.Index...)
|
||||
return field, true
|
||||
}
|
||||
|
||||
@@ -2180,6 +2180,68 @@ func TestIssue462(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestIssue_embedded_pointer_struct(t *testing.T) {
|
||||
var tests = []struct {
|
||||
input string
|
||||
env mock.Env
|
||||
want any
|
||||
}{
|
||||
{
|
||||
input: "(Embed).EmbedPointerEmbedInt > 0",
|
||||
env: mock.Env{
|
||||
Embed: mock.Embed{
|
||||
EmbedPointerEmbed: &mock.EmbedPointerEmbed{
|
||||
EmbedPointerEmbedInt: 123,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
input: "(Embed).EmbedPointerEmbedInt > 0",
|
||||
env: mock.Env{
|
||||
Embed: mock.Embed{
|
||||
EmbedPointerEmbed: &mock.EmbedPointerEmbed{
|
||||
EmbedPointerEmbedInt: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
input: "(Embed).EmbedPointerEmbedMethod(0)",
|
||||
env: mock.Env{
|
||||
Embed: mock.Embed{
|
||||
EmbedPointerEmbed: &mock.EmbedPointerEmbed{
|
||||
EmbedPointerEmbedInt: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
input: "(Embed).EmbedPointerEmbedPointerReceiverMethod(0)",
|
||||
env: mock.Env{
|
||||
Embed: mock.Embed{
|
||||
EmbedPointerEmbed: nil,
|
||||
},
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.input, func(t *testing.T) {
|
||||
program, err := expr.Compile(tt.input, expr.Env(tt.env))
|
||||
require.NoError(t, err)
|
||||
|
||||
out, err := expr.Run(program, tt.env)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, tt.want, out)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue(t *testing.T) {
|
||||
testCases := []struct {
|
||||
code string
|
||||
|
||||
@@ -103,6 +103,7 @@ func (Env) NotStringerStringerEqual(f fmt.Stringer, g fmt.Stringer) bool {
|
||||
|
||||
type Embed struct {
|
||||
EmbedEmbed
|
||||
*EmbedPointerEmbed
|
||||
EmbedString string
|
||||
}
|
||||
|
||||
@@ -110,6 +111,18 @@ func (p Embed) EmbedMethod(_ int) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type EmbedPointerEmbed struct {
|
||||
EmbedPointerEmbedInt int
|
||||
}
|
||||
|
||||
func (p EmbedPointerEmbed) EmbedPointerEmbedMethod(_ int) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *EmbedPointerEmbed) EmbedPointerEmbedPointerReceiverMethod(_ int) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type EmbedEmbed struct {
|
||||
EmbedEmbedString string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user