From 482a696c5a6aa68c112f4b8a110e4b1b03c4827c Mon Sep 17 00:00:00 2001 From: Jansen Date: Fri, 1 Mar 2019 16:49:31 +0800 Subject: [PATCH 1/4] add support for `proteus:"(protobuf field id)"` in golang tag --- protobuf/transform.go | 6 ++++++ scanner/package.go | 1 + scanner/scanner.go | 13 +++++++++++++ 3 files changed, 20 insertions(+) diff --git a/protobuf/transform.go b/protobuf/transform.go index 1fe6bf2..ef40bed 100644 --- a/protobuf/transform.go +++ b/protobuf/transform.go @@ -256,6 +256,12 @@ func (t *Transformer) transformField(pkg *Package, msg *Message, field *scanner. Repeated: repeated, } + // If this field has set pos in tag, + // use customize protobuf positin. + if field.Pos != 0 { + f.Pos = field.Pos + } + // []byte is the only repeated type that maps to // a non-repeated type in protobuf, so we handle // it a bit differently. diff --git a/scanner/package.go b/scanner/package.go index 0ffbf5a..1e1e0e7 100644 --- a/scanner/package.go +++ b/scanner/package.go @@ -302,6 +302,7 @@ type Field struct { Docs Name string Type Type + Pos int } // Func is either a function or a method. Receiver will be nil in functions, diff --git a/scanner/scanner.go b/scanner/scanner.go index 5fd4c23..2611a41 100644 --- a/scanner/scanner.go +++ b/scanner/scanner.go @@ -7,6 +7,7 @@ import ( "os" "path/filepath" "sort" + "strconv" "strings" "sync" @@ -294,6 +295,7 @@ func scanStruct(s *Struct, elem *types.Struct) *Struct { f := &Field{ Name: v.Name(), Type: scanType(v.Type()), + Pos: getProtoID(v, tags), } if f.Type == nil { continue @@ -390,6 +392,17 @@ func isIgnoredField(f *types.Var, tags []string) bool { return !f.Exported() || (len(tags) > 0 && tags[0] == "-") } +func getProtoID(f *types.Var, tags []string) int { + if len(tags) == 0 { + return 0 + } + i, err := strconv.Atoi(tags[0]) + if err != nil { + return 0 + } + return i +} + func objectsInScope(scope *types.Scope) (objs []types.Object) { for _, n := range scope.Names() { obj := scope.Lookup(n) From 6204512868b36f6a577ff8bb83b39689c83f18a4 Mon Sep 17 00:00:00 2001 From: Jansen Date: Sat, 2 Mar 2019 11:25:05 +0800 Subject: [PATCH 2/4] Use proteus:",101" notation Thanks to dennwc for advice it may be better to use proteus:",101" notation - it will be easier to extend later. --- scanner/scanner.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scanner/scanner.go b/scanner/scanner.go index 2611a41..e933425 100644 --- a/scanner/scanner.go +++ b/scanner/scanner.go @@ -393,10 +393,10 @@ func isIgnoredField(f *types.Var, tags []string) bool { } func getProtoID(f *types.Var, tags []string) int { - if len(tags) == 0 { + if len(tags) < 2 { return 0 } - i, err := strconv.Atoi(tags[0]) + i, err := strconv.Atoi(tags[1]) if err != nil { return 0 } From 0abc69f87cd77d1366bae49e30ba459f48e398ac Mon Sep 17 00:00:00 2001 From: Denys Smirnov Date: Fri, 1 Mar 2019 19:08:21 +0200 Subject: [PATCH 3/4] ci: bump go version Signed-off-by: Denys Smirnov --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index eb0b2df..59a638d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: go go: - - 1.7 - - 1.8 + - 1.10.x + - 1.11.x - tip matrix: From 16df9b11a759a56b75f0d11dd27d4d4cb1cd32d4 Mon Sep 17 00:00:00 2001 From: Jansen Date: Sat, 2 Mar 2019 12:58:37 +0800 Subject: [PATCH 4/4] Add `proteus:",101"` test and example add test in transform_test and scanner_test. add an example of use. --- example/categories/categories.go | 5 +++++ protobuf/transform_test.go | 24 ++++++++++++++++++++++++ scanner/scanner_test.go | 30 ++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/example/categories/categories.go b/example/categories/categories.go index 39e6d49..96eca06 100644 --- a/example/categories/categories.go +++ b/example/categories/categories.go @@ -5,4 +5,9 @@ package categories type CategoryOptions struct { ShowPrices bool CanBuy bool + // The next field was deleted. + // Field3 int + + // 4th field, use `proteus:",4"` forward compatible + Field4 int `proteus:",4"` } diff --git a/protobuf/transform_test.go b/protobuf/transform_test.go index 1e16da1..75ea44b 100644 --- a/protobuf/transform_test.go +++ b/protobuf/transform_test.go @@ -270,6 +270,7 @@ func (s *TransformerSuite) TestTransformField() { name string typ scanner.Type expected *Field + pos int }{ { "Foo", @@ -279,6 +280,7 @@ func (s *TransformerSuite) TestTransformField() { Type: NewBasic("int64"), Options: Options{"(gogoproto.casttype)": NewStringValue("int")}, }, + 0, }, { "Bar", @@ -288,6 +290,7 @@ func (s *TransformerSuite) TestTransformField() { Type: NewBasic("bytes"), Options: Options{}, }, + 0, }, { "BazBar", @@ -298,6 +301,7 @@ func (s *TransformerSuite) TestTransformField() { Repeated: true, Options: Options{"(gogoproto.casttype)": NewStringValue("int")}, }, + 0, }, { "CustomID", @@ -310,6 +314,7 @@ func (s *TransformerSuite) TestTransformField() { "(gogoproto.casttype)": NewStringValue("int"), }, }, + 0, }, { "NullableType", @@ -319,6 +324,7 @@ func (s *TransformerSuite) TestTransformField() { Type: NewNamed("my.pckg", "hello"), Options: Options{}, }, + 0, }, { "NonNullableType", @@ -330,11 +336,13 @@ func (s *TransformerSuite) TestTransformField() { "(gogoproto.nullable)": NewLiteralValue("false"), }, }, + 0, }, { "Invalid", scanner.NewBasic("complex64"), nil, + 0, }, { "MyEnum", @@ -344,6 +352,7 @@ func (s *TransformerSuite) TestTransformField() { Type: NewNamed("my.pckg", "MyEnum"), Options: Options{}, }, + 0, }, { "MyAlias", @@ -361,6 +370,7 @@ func (s *TransformerSuite) TestTransformField() { "(gogoproto.casttype)": NewStringValue("my/pckg.MyAlias"), }, }, + 0, }, { "MyRepeatedAlias", @@ -376,6 +386,18 @@ func (s *TransformerSuite) TestTransformField() { ), Options: Options{}, }, + 0, + }, + { + "ProtoID", + scanner.NewBasic("int64"), + &Field{ + Name: "proto_id", + Type: NewBasic("int64"), + Options: Options{"(gogoproto.customname)": NewStringValue("ProtoID")}, + Pos: 101, + }, + 101, }, } @@ -387,6 +409,7 @@ func (s *TransformerSuite) TestTransformField() { f := s.t.transformField(&Package{}, &Message{}, &scanner.Field{ Name: c.name, Type: c.typ, + Pos: c.pos, }, 0) if c.expected == nil { s.Nil(f, c.name) @@ -394,6 +417,7 @@ func (s *TransformerSuite) TestTransformField() { s.Equal(c.expected.Name, f.Name, fmt.Sprintf("Name in %s", c.name)) s.assertType(c.expected.Type, f.Type, c.name) s.Equal(c.expected.Options, f.Options, fmt.Sprintf("Options in %s", c.name)) + s.Equal(c.expected.Pos, f.Pos, fmt.Sprintf("Proto id in %d", c.pos)) } } } diff --git a/scanner/scanner_test.go b/scanner/scanner_test.go index b18af67..c8e5c37 100644 --- a/scanner/scanner_test.go +++ b/scanner/scanner_test.go @@ -157,6 +157,36 @@ func TestScanStruct(t *testing.T) { }, }, }, + { + "struct with proto field id tag", + types.NewStruct( + []*types.Var{ + mkField("Foo", types.Typ[types.Int], false), + }, + []string{`proteus:",101"`}, + ), + &Struct{ + Fields: []*Field{ + {Name: "Foo", Type: NewBasic("int"), Pos: 101}, + }, + }, + }, + { + "invalid struct with proto field id tag", + types.NewStruct( + []*types.Var{ + mkField("Foo", types.Typ[types.Int], false), + mkField("Bar", types.Typ[types.Int], false), + }, + []string{`proteus:","`, `proteus:",lol"`}, + ), + &Struct{ + Fields: []*Field{ + {Name: "Foo", Type: NewBasic("int"), Pos: 0}, + {Name: "Bar", Type: NewBasic("int"), Pos: 0}, + }, + }, + }, { "struct with unsupported type", types.NewStruct(