Skip to content

Commit 94b34d2

Browse files
aksentyevantonmedv
authored andcommitted
supported embedded structs
1 parent 28e2903 commit 94b34d2

File tree

4 files changed

+76
-1
lines changed

4 files changed

+76
-1
lines changed

parser.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ func With(i interface{}) OptionFn {
134134
for i := 0; i < t.NumField(); i++ {
135135
f := t.Field(i)
136136
p.types[f.Name] = f.Type
137+
138+
for name, typ := range p.findEmbeddedFieldNames(f.Type) {
139+
p.types[name] = typ
140+
}
137141
}
138142
case reflect.Map:
139143
for _, key := range v.MapKeys() {
@@ -146,6 +150,26 @@ func With(i interface{}) OptionFn {
146150
}
147151
}
148152

153+
func (p *parser) findEmbeddedFieldNames(t reflect.Type) map[string]Type {
154+
res := make(map[string]Type)
155+
if t.Kind() == reflect.Struct {
156+
for i := 0; i < t.NumField(); i++ {
157+
f := t.Field(i)
158+
if f.Type.Kind() == reflect.Struct && f.Type.Name() == f.Name {
159+
for name, typ := range p.findEmbeddedFieldNames(f.Type) {
160+
res[name] = typ
161+
}
162+
163+
return res
164+
}
165+
166+
res[f.Name] = f.Type
167+
}
168+
}
169+
170+
return res
171+
}
172+
149173
func (p *parser) errorf(format string, args ...interface{}) *syntaxError {
150174
return &syntaxError{
151175
message: fmt.Sprintf(format, args...),

parser_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,24 @@ func TestParse_error(t *testing.T) {
207207
}
208208
}
209209
}
210+
211+
func TestParser_findEmbeddedFieldNames(t *testing.T) {
212+
type (
213+
C struct {
214+
F int
215+
}
216+
217+
B struct {
218+
C
219+
}
220+
221+
A struct {
222+
B
223+
}
224+
)
225+
226+
res := new(parser).findEmbeddedFieldNames(reflect.TypeOf(A{}))
227+
if res["F"] != reflect.TypeOf(1) {
228+
t.Error("expected embedded struct field")
229+
}
230+
}

type.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,13 +331,36 @@ func fieldType(ntype Type, name string) (Type, bool) {
331331
case reflect.Interface:
332332
return interfaceType, true
333333
case reflect.Struct:
334-
if t, ok := ntype.FieldByName(name); ok {
334+
t, ok := ntype.FieldByName(name)
335+
if ok {
335336
return t.Type, true
336337
}
338+
339+
if t, ok := checkEmbeddedFieldNames(ntype, name); ok {
340+
return t, true
341+
}
337342
case reflect.Map:
338343
return ntype.Elem(), true
339344
}
340345
}
346+
347+
return nil, false
348+
}
349+
350+
func checkEmbeddedFieldNames(t reflect.Type, name string) (Type, bool) {
351+
if t.Kind() == reflect.Struct {
352+
for i := 0; i < t.NumField(); i++ {
353+
f := t.Field(i)
354+
if f.Type.Kind() == reflect.Struct {
355+
return checkEmbeddedFieldNames(f.Type, name)
356+
}
357+
358+
if f.Name == name {
359+
return f.Type, true
360+
}
361+
}
362+
}
363+
341364
return nil, false
342365
}
343366

type_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ var typeTests = []typeTest{
6969
"Int + Int + Int",
7070
"Int % Int > 1",
7171
"Int in Int..Int",
72+
"FieldStr == 'test'",
7273
}
7374

7475
var typeErrorTests = []typeErrorTest{
@@ -273,7 +274,13 @@ type foo struct {
273274
Fn func()
274275
Abc abc
275276
}
277+
278+
type StringStruct struct {
279+
FieldStr string
280+
}
281+
276282
type payload struct {
283+
StringStruct
277284
Abc abc
278285
Foo *foo
279286
Arr []*foo

0 commit comments

Comments
 (0)