fix: lookup embedded binary fields in struct (#207)

This commit is contained in:
Marc Vertes
2019-06-11 09:17:53 +02:00
committed by Ludovic Fernandez
parent 264782408a
commit 67ba2888d7
4 changed files with 65 additions and 0 deletions

20
_test/struct18.go Normal file
View File

@@ -0,0 +1,20 @@
package main
import (
"fmt"
"net/http"
)
type AuthenticatedRequest struct {
http.Request
Username string
}
func main() {
a := &AuthenticatedRequest{}
fmt.Printf("%v %T\n", a.Header, a.Header)
}
// Output:
// map[] http.Header

View File

@@ -1129,6 +1129,12 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
n.typ = &Type{cat: ValueT, rtype: rtype}
}
}
} else if s, lind, ok := n.typ.lookupBinField(n.child[1].ident); ok {
// Handle an embedded binary field into a struct field
n.gen = getIndexSeqField
lind = append(lind, s.Index...)
n.val = lind
n.typ = &Type{cat: ValueT, rtype: s.Type}
} else {
err = n.cfgError("undefined selector: %s", n.child[1].ident)
}

View File

@@ -1086,6 +1086,25 @@ func getPtrIndexSeq(n *Node) {
}
}
func getIndexSeqField(n *Node) {
value := genValue(n.child[0])
index := n.val.([]int)
i := n.findex
next := getExec(n.tnext)
if n.child[0].typ.TypeOf().Kind() == reflect.Ptr {
n.exec = func(f *Frame) Builtin {
f.data[i] = value(f).Elem().FieldByIndex(index)
return next
}
} else {
n.exec = func(f *Frame) Builtin {
f.data[i] = value(f).FieldByIndex(index)
return next
}
}
}
func getIndexSeqMethod(n *Node) {
value := genValue(n.child[0])
index := n.val.([]int)

View File

@@ -528,6 +528,26 @@ func (t *Type) lookupField(name string) []int {
return nil
}
// lookupBinField returns a structfield and a path to access an embedded binary field in a struct object
func (t *Type) lookupBinField(name string) (reflect.StructField, []int, bool) {
if t.cat == PtrT {
return t.val.lookupBinField(name)
}
var index []int
s, ok := t.TypeOf().FieldByName(name)
if !ok {
for i, f := range t.field {
if f.embed {
if s2, index2, ok2 := f.typ.lookupBinField(name); ok2 {
index = append([]int{i}, index2...)
return s2, index, ok2
}
}
}
}
return s, index, ok
}
// getMethod returns a pointer to the method definition
func (t *Type) getMethod(name string) *Node {
for _, m := range t.method {