From 854e4f15535536d0b11d0b53f1781fe7f4ccbdf3 Mon Sep 17 00:00:00 2001 From: "Dmitry A. Shashkin" Date: Wed, 28 Feb 2024 08:04:44 +1100 Subject: [PATCH] feat: check structs within arrays/slices/maps (#80) --- musttag.go | 21 ++++++++------ testdata/src/tests/tests.go | 56 +++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/musttag.go b/musttag.go index b7e41f3..d791177 100644 --- a/musttag.go +++ b/musttag.go @@ -150,16 +150,19 @@ type checker struct { } func (c *checker) parseStruct(typ types.Type) (*types.Struct, bool) { - for { - // unwrap pointers (if any) first. - ptr, ok := typ.(*types.Pointer) - if !ok { - break - } - typ = ptr.Elem() - } - switch typ := typ.(type) { + case *types.Pointer: + return c.parseStruct(typ.Elem()) + + case *types.Array: + return c.parseStruct(typ.Elem()) + + case *types.Slice: + return c.parseStruct(typ.Elem()) + + case *types.Map: + return c.parseStruct(typ.Elem()) + case *types.Named: // a struct of the named type. pkg := typ.Obj().Pkg() if pkg == nil { diff --git a/testdata/src/tests/tests.go b/testdata/src/tests/tests.go index 9112dab..bd869be 100644 --- a/testdata/src/tests/tests.go +++ b/testdata/src/tests/tests.go @@ -51,6 +51,62 @@ func embeddedType() { json.Marshal(&Foo{}) // want "the given struct should be annotated with the `json` tag" } +func nestedArrayType() { + type Bar struct { + NoTag string + } + type Foo struct { + Bars [5]Bar `json:"bars"` + } + var foo Foo + json.Marshal(foo) // want "the given struct should be annotated with the `json` tag" + json.Marshal(&foo) // want "the given struct should be annotated with the `json` tag" + json.Marshal(Foo{}) // want "the given struct should be annotated with the `json` tag" + json.Marshal(&Foo{}) // want "the given struct should be annotated with the `json` tag" +} + +func nestedSliceType() { + type Bar struct { + NoTag string + } + type Foo struct { + Bars []Bar `json:"bars"` + } + var foo Foo + json.Marshal(foo) // want "the given struct should be annotated with the `json` tag" + json.Marshal(&foo) // want "the given struct should be annotated with the `json` tag" + json.Marshal(Foo{}) // want "the given struct should be annotated with the `json` tag" + json.Marshal(&Foo{}) // want "the given struct should be annotated with the `json` tag" +} + +func nestedMapType() { + type Bar struct { + NoTag string + } + type Foo struct { + Bars map[string]Bar `json:"bars"` + } + var foo Foo + json.Marshal(foo) // want "the given struct should be annotated with the `json` tag" + json.Marshal(&foo) // want "the given struct should be annotated with the `json` tag" + json.Marshal(Foo{}) // want "the given struct should be annotated with the `json` tag" + json.Marshal(&Foo{}) // want "the given struct should be annotated with the `json` tag" +} + +func nestedComplexType() { + type Bar struct { + NoTag string + } + type Foo struct { + Bars **[][]map[string][][5][5]map[string]*Bar `json:"bars"` + } + var foo Foo + json.Marshal(foo) // want "the given struct should be annotated with the `json` tag" + json.Marshal(&foo) // want "the given struct should be annotated with the `json` tag" + json.Marshal(Foo{}) // want "the given struct should be annotated with the `json` tag" + json.Marshal(&Foo{}) // want "the given struct should be annotated with the `json` tag" +} + func recursiveType() { // should not cause panic; see issue #16. type Foo struct {