From bab2d3046de2df2e1d4719ec0557deeea8f1fe21 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 7 Jun 2017 11:56:14 +0200 Subject: [PATCH] fix crash for fields of built-in type --- internal/tests/ftypes/input.go | 13 ++++++++++ internal/tests/ftypes/output.go | 42 +++++++++++++++++++++++++++++++++ main_test.go | 1 + typeutil.go | 9 +++++-- 4 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 internal/tests/ftypes/input.go create mode 100644 internal/tests/ftypes/output.go diff --git a/internal/tests/ftypes/input.go b/internal/tests/ftypes/input.go new file mode 100644 index 0000000..7534234 --- /dev/null +++ b/internal/tests/ftypes/input.go @@ -0,0 +1,13 @@ +// Copyright 2017 Felix Lange . +// Use of this source code is governed by the MIT license, +// which can be found in the LICENSE file. + +//go:generate gencodec -type X -formats json -out output.go + +package ftypes + +type X struct { + Int int + Err error + If interface{} +} diff --git a/internal/tests/ftypes/output.go b/internal/tests/ftypes/output.go new file mode 100644 index 0000000..6a86c8a --- /dev/null +++ b/internal/tests/ftypes/output.go @@ -0,0 +1,42 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package ftypes + +import ( + "encoding/json" +) + +func (x X) MarshalJSON() ([]byte, error) { + type X struct { + Int int + Err error + If interface{} + } + var enc X + enc.Int = x.Int + enc.Err = x.Err + enc.If = x.If + return json.Marshal(&enc) +} + +func (x *X) UnmarshalJSON(input []byte) error { + type X struct { + Int *int + Err *error + If *interface{} + } + var dec X + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Int != nil { + x.Int = *dec.Int + } + if dec.Err != nil { + x.Err = *dec.Err + } + if dec.If != nil { + x.If = *dec.If + } + return nil +} diff --git a/main_test.go b/main_test.go index 7c196a9..7b53e47 100644 --- a/main_test.go +++ b/main_test.go @@ -24,6 +24,7 @@ func TestGolden(t *testing.T) { Config{Dir: "nameclash", Type: "Y", FieldOverride: "Yo", Formats: AllFormats}, Config{Dir: "omitempty", Type: "X", FieldOverride: "Xo", Formats: AllFormats}, Config{Dir: "reqfield", Type: "X", Formats: []string{"json"}}, + Config{Dir: "ftypes", Type: "X", Formats: []string{"json"}}, Config{Dir: "funcoverride", Type: "Z", FieldOverride: "Zo", Formats: AllFormats}, } for _, test := range tests { diff --git a/typeutil.go b/typeutil.go index cafd675..c766673 100644 --- a/typeutil.go +++ b/typeutil.go @@ -32,6 +32,10 @@ func walkNamedTypes(typ types.Type, callback func(*types.Named)) { for i := 0; i < typ.NumFields(); i++ { walkNamedTypes(typ.Field(i).Type(), callback) } + case *types.Interface: + if typ.NumMethods() > 0 { + panic("BUG: can't walk non-empty interface") + } default: panic(fmt.Errorf("BUG: can't walk %T", typ)) } @@ -176,9 +180,10 @@ func (s *fileScope) addImport(path string) { // addReferences marks all names referenced by typ as used. func (s *fileScope) addReferences(typ types.Type) { walkNamedTypes(typ, func(nt *types.Named) { - if nt.Obj().Pkg() == s.pkg { + pkg := nt.Obj().Pkg() + if pkg == s.pkg { s.otherNames[nt.Obj().Name()] = true - } else { + } else if pkg != nil { s.insertImport(nt.Obj().Pkg()) } })