├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── buf.gen.debug.yaml ├── buf.gen.tag.yaml ├── buf.gen.yaml ├── buf.lock ├── buf.yaml ├── debug └── code_generator_request.pb.bin ├── example ├── example.pb.go └── example.proto ├── go.mod ├── go.sum ├── main.go ├── module ├── extract.go ├── extract_test.go ├── replace.go ├── replace_test.go ├── tagger.go └── test │ ├── golden.txt │ └── input.txt └── tagger ├── tagger.pb.go └── tagger.proto /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | .idea/ 14 | .vscode/ 15 | vendor/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Sri Krishna Paritala 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LOCAL_PATH = $(shell pwd) 2 | 3 | .PHONY: example proto install gen-tag test 4 | 5 | example: proto install 6 | protoc -I /usr/local/include \ 7 | -I ${LOCAL_PATH} \ 8 | --gotag_out=xxx="graphql+\"-\" bson+\"-\"":. example/example.proto 9 | 10 | proto: 11 | protoc -I /usr/local/include \ 12 | -I ${LOCAL_PATH} \ 13 | --go_out=:. example/example.proto 14 | 15 | install: 16 | go install . 17 | 18 | gen-tag: 19 | buf generate 20 | buf generate --template=buf.gen.tag.yaml 21 | buf generate --template=buf.gen.debug.yaml --path tagger 22 | 23 | test: 24 | go test ./... 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # protoc-gen-gotag (PGGT) 2 | 3 | PGGT is a protoc plugin used to add/replace struct tags on generated protobuf messages. 4 | 5 | The project maintenance and evolution has been embraced by [@ucpr](https://github.com/ucpr), [@mesmerx](https://github.com/mesmerx) and [@Kavuti](https://github.com/Kavuti). 6 | 7 | Get it using 8 | 9 | ``` 10 | go install github.com/srikrsna/protoc-gen-gotag@latest 11 | ``` 12 | 13 | It supports the following features, 14 | 15 | ## Add/Replace Tags 16 | 17 | New tags like xml, sql, bson etc... can be added to struct messages of protobuf. Example 18 | ```proto 19 | syntax = "proto3"; 20 | 21 | package example; 22 | 23 | import "tagger/tagger.proto"; 24 | 25 | message Example { 26 | string with_new_tags = 1 [(tagger.tags) = "graphql:\"withNewTags,optional\"" ]; 27 | string with_new_multiple = 2 [(tagger.tags) = "graphql:\"withNewTags,optional\" xml:\"multi,omitempty\"" ]; 28 | 29 | string replace_default = 3 [(tagger.tags) = "json:\"replacePrevious\""] ; 30 | 31 | oneof one_of { 32 | option (tagger.oneof_tags) = "graphql:\"withNewTags,optional\""; 33 | string a = 5 [(tagger.tags) = "json:\"A\""]; 34 | int32 b_jk = 6 [(tagger.tags) = "json:\"b_Jk\""]; 35 | } 36 | } 37 | 38 | message SecondMessage { 39 | string with_new_tags = 1 [(tagger.tags) = "graphql:\"withNewTags,optional\"" ]; 40 | string with_new_multiple = 2 [(tagger.tags) = "graphql:\"withNewTags,optional\" xml:\"multi,omitempty\"" ]; 41 | 42 | string replace_default = 3 [(tagger.tags) = "json:\"replacePrevious\""] ; 43 | } 44 | ``` 45 | 46 | Then struct tags can be added by running this command **after** the regular protobuf generation command. 47 | 48 | ```bash 49 | protoc -I /usr/local/include \ 50 | -I . \ 51 | --gotag_out=:. example/example.proto 52 | ``` 53 | 54 | In the above example tags like graphql and xml will be added whereas existing tags such as json are replaced with the supplied values. 55 | 56 | ## Auto add tags on field 57 | 58 | Automatically add custom tags to message field using provided transformer. 59 | It will compile the tag as ```tag:"snaked_key_name"``` by default if no transformer is being provide. 60 | To provide transformer, use: ```tagName-as-transformer``` instruction when running `gotag` 61 | 62 | ```bash 63 | protoc -I /usr/local/include \ 64 | -I . \ 65 | --gotag_out=auto="form+db-as-camel":. example/example.proto 66 | ``` 67 | 68 | The above command will add two addtional tags (form and db) for each field. The form tag will be lower_snake_case and db tag will be lowerCamelCase 69 | 70 | Supported transformers: 71 | 72 | | Keys | Action | Ex | 73 | | -------------------------------------------------------- | --------------------------------- | ------------------- | 74 | | "lower_snake", "lower_snake_case", "snake", "snake_case" | Make lower snake case key | someKey -> some_key | 75 | | "upper_snake", "upper_snake_case" | Make upper snake case key | someKey -> Some_key | 76 | | "lower_camel", "lower_camel_case", "camel", "camel_case" | Make lower camel case key | someKey -> someKey | 77 | | "upper_camel", "upper_camel_case" | Make upper camel case key | someKey -> SomeKey | 78 | | "dot_notation", "dot", "lower_dot_notation", "lower_dot" | Make lower cased dot notation key | someKey -> some.key | 79 | | "upper_dot", "upper_dot_notation" | Make upper cased dot notation key | someKey -> Some.Key | 80 | 81 | ## Add tags to XXX* fields 82 | 83 | It is very useful to ignore XXX* fields in protobuf generated messages. The go protocol buffer compiler adds ```json:"-"``` tag to all XXX* fields. Additional tags can be added to these fields using the 'xxx' option of PGGT. It can be done like this. All '+' characters will be replaced with ':'. 84 | 85 | ```bash 86 | protoc -I /usr/local/include \ 87 | -I . \ 88 | --gotag_out=xxx="graphql+\"-\" bson+\"-\"":. example/example.proto 89 | ``` 90 | 91 | ## Output to a directory other than the current directory 92 | 93 | When outputting to a directory other than the current directory, you will need to pass the output path twice using 94 | the "outdir" parameter. If you experience any `no such file or directory`, errors, try adding the "outdir" flag. 95 | ```bash 96 | protoc -I /usr/local/include \ 97 | -I ./pkg \ 98 | --gotag_out=outdir="./pkg":./pkg example/example.proto 99 | ``` 100 | 101 | ### Note 102 | 103 | This should always run after protocol buffer compiler has run. The command such as the one below will fail/produce unexpected results. 104 | 105 | ```bash 106 | protoc -I /usr/local/include \ 107 | -I . \ 108 | --go_out=:. \ 109 | --gotag_out=xxx="graphql+\"-\" bson+\"-\"":. example/example.proto 110 | ``` 111 | -------------------------------------------------------------------------------- /buf.gen.debug.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - name: debug 4 | out: . 5 | opt: ./debug 6 | -------------------------------------------------------------------------------- /buf.gen.tag.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - name: gotag 4 | out: . 5 | opt: paths=source_relative,xxx=graphql+"-" bson+"-" 6 | -------------------------------------------------------------------------------- /buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - name: go 4 | out: . 5 | opt: paths=source_relative 6 | -------------------------------------------------------------------------------- /buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: googleapis 6 | repository: googleapis 7 | commit: 62f35d8aed1149c291d606d958a7ce32 8 | -------------------------------------------------------------------------------- /buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | name: buf.build/srikrsna/protoc-gen-gotag 3 | deps: 4 | - buf.build/googleapis/googleapis 5 | 6 | breaking: 7 | use: 8 | - FILE 9 | 10 | lint: 11 | use: 12 | - BASIC 13 | - FILE_LOWER_SNAKE_CASE 14 | except: 15 | - ENUM_NO_ALLOW_ALIAS 16 | - IMPORT_NO_PUBLIC 17 | - PACKAGE_DIRECTORY_MATCH 18 | - PACKAGE_SAME_DIRECTORY 19 | -------------------------------------------------------------------------------- /debug/code_generator_request.pb.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srikrsna/protoc-gen-gotag/1f853e57000cb16a6be08466a4f3275611ab366f/debug/code_generator_request.pb.bin -------------------------------------------------------------------------------- /example/example.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.32.0 4 | // protoc (unknown) 5 | // source: example/example.proto 6 | 7 | package example 8 | 9 | import ( 10 | _ "github.com/srikrsna/protoc-gen-gotag/tagger" 11 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 12 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 13 | reflect "reflect" 14 | sync "sync" 15 | ) 16 | 17 | const ( 18 | // Verify that this generated code is sufficiently up-to-date. 19 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 20 | // Verify that runtime/protoimpl is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 22 | ) 23 | 24 | type Example struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | 29 | WithNewTags string `protobuf:"bytes,1,opt,name=with_new_tags,json=withNewTags,proto3" json:"with_new_tags,omitempty" graphql:"withNewTags,optional"` 30 | WithNewMultiple string `protobuf:"bytes,2,opt,name=with_new_multiple,json=withNewMultiple,proto3" json:"with_new_multiple,omitempty" graphql:"withNewTags,optional" xml:"multi,omitempty"` 31 | ReplaceDefault *string `protobuf:"bytes,3,opt,name=replace_default,json=replaceDefault,proto3,oneof" json:"replacePrevious"` 32 | // Types that are assignable to OneOf: 33 | // 34 | // *Example_A 35 | // *Example_BJk 36 | OneOf isExample_OneOf `protobuf_oneof:"one_of" graphql:"withNewTags,optional"` 37 | } 38 | 39 | func (x *Example) Reset() { 40 | *x = Example{} 41 | if protoimpl.UnsafeEnabled { 42 | mi := &file_example_example_proto_msgTypes[0] 43 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 44 | ms.StoreMessageInfo(mi) 45 | } 46 | } 47 | 48 | func (x *Example) String() string { 49 | return protoimpl.X.MessageStringOf(x) 50 | } 51 | 52 | func (*Example) ProtoMessage() {} 53 | 54 | func (x *Example) ProtoReflect() protoreflect.Message { 55 | mi := &file_example_example_proto_msgTypes[0] 56 | if protoimpl.UnsafeEnabled && x != nil { 57 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 58 | if ms.LoadMessageInfo() == nil { 59 | ms.StoreMessageInfo(mi) 60 | } 61 | return ms 62 | } 63 | return mi.MessageOf(x) 64 | } 65 | 66 | // Deprecated: Use Example.ProtoReflect.Descriptor instead. 67 | func (*Example) Descriptor() ([]byte, []int) { 68 | return file_example_example_proto_rawDescGZIP(), []int{0} 69 | } 70 | 71 | func (x *Example) GetWithNewTags() string { 72 | if x != nil { 73 | return x.WithNewTags 74 | } 75 | return "" 76 | } 77 | 78 | func (x *Example) GetWithNewMultiple() string { 79 | if x != nil { 80 | return x.WithNewMultiple 81 | } 82 | return "" 83 | } 84 | 85 | func (x *Example) GetReplaceDefault() string { 86 | if x != nil && x.ReplaceDefault != nil { 87 | return *x.ReplaceDefault 88 | } 89 | return "" 90 | } 91 | 92 | func (m *Example) GetOneOf() isExample_OneOf { 93 | if m != nil { 94 | return m.OneOf 95 | } 96 | return nil 97 | } 98 | 99 | func (x *Example) GetA() string { 100 | if x, ok := x.GetOneOf().(*Example_A); ok { 101 | return x.A 102 | } 103 | return "" 104 | } 105 | 106 | func (x *Example) GetBJk() int32 { 107 | if x, ok := x.GetOneOf().(*Example_BJk); ok { 108 | return x.BJk 109 | } 110 | return 0 111 | } 112 | 113 | type isExample_OneOf interface { 114 | isExample_OneOf() 115 | } 116 | 117 | type Example_A struct { 118 | A string `protobuf:"bytes,5,opt,name=a,proto3,oneof" json:"A"` 119 | } 120 | 121 | type Example_BJk struct { 122 | BJk int32 `protobuf:"varint,6,opt,name=b_jk,json=bJk,proto3,oneof" json:"b_Jk"` 123 | } 124 | 125 | func (*Example_A) isExample_OneOf() {} 126 | 127 | func (*Example_BJk) isExample_OneOf() {} 128 | 129 | type SecondMessage struct { 130 | state protoimpl.MessageState 131 | sizeCache protoimpl.SizeCache 132 | unknownFields protoimpl.UnknownFields 133 | 134 | WithNewTags string `protobuf:"bytes,1,opt,name=with_new_tags,json=withNewTags,proto3" json:"with_new_tags,omitempty" graphql:"withNewTags,optional"` 135 | WithNewMultiple string `protobuf:"bytes,2,opt,name=with_new_multiple,json=withNewMultiple,proto3" json:"with_new_multiple,omitempty" graphql:"withNewTags,optional" xml:"multi,omitempty"` 136 | ReplaceDefault string `protobuf:"bytes,3,opt,name=replace_default,json=replaceDefault,proto3" json:"replacePrevious"` 137 | } 138 | 139 | func (x *SecondMessage) Reset() { 140 | *x = SecondMessage{} 141 | if protoimpl.UnsafeEnabled { 142 | mi := &file_example_example_proto_msgTypes[1] 143 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 144 | ms.StoreMessageInfo(mi) 145 | } 146 | } 147 | 148 | func (x *SecondMessage) String() string { 149 | return protoimpl.X.MessageStringOf(x) 150 | } 151 | 152 | func (*SecondMessage) ProtoMessage() {} 153 | 154 | func (x *SecondMessage) ProtoReflect() protoreflect.Message { 155 | mi := &file_example_example_proto_msgTypes[1] 156 | if protoimpl.UnsafeEnabled && x != nil { 157 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 158 | if ms.LoadMessageInfo() == nil { 159 | ms.StoreMessageInfo(mi) 160 | } 161 | return ms 162 | } 163 | return mi.MessageOf(x) 164 | } 165 | 166 | // Deprecated: Use SecondMessage.ProtoReflect.Descriptor instead. 167 | func (*SecondMessage) Descriptor() ([]byte, []int) { 168 | return file_example_example_proto_rawDescGZIP(), []int{1} 169 | } 170 | 171 | func (x *SecondMessage) GetWithNewTags() string { 172 | if x != nil { 173 | return x.WithNewTags 174 | } 175 | return "" 176 | } 177 | 178 | func (x *SecondMessage) GetWithNewMultiple() string { 179 | if x != nil { 180 | return x.WithNewMultiple 181 | } 182 | return "" 183 | } 184 | 185 | func (x *SecondMessage) GetReplaceDefault() string { 186 | if x != nil { 187 | return x.ReplaceDefault 188 | } 189 | return "" 190 | } 191 | 192 | type ThirdExample struct { 193 | state protoimpl.MessageState 194 | sizeCache protoimpl.SizeCache 195 | unknownFields protoimpl.UnknownFields 196 | 197 | InnerExample *ThirdExample_InnerExample `protobuf:"bytes,1,opt,name=inner_example,json=innerExample,proto3" json:"inner"` 198 | } 199 | 200 | func (x *ThirdExample) Reset() { 201 | *x = ThirdExample{} 202 | if protoimpl.UnsafeEnabled { 203 | mi := &file_example_example_proto_msgTypes[2] 204 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 205 | ms.StoreMessageInfo(mi) 206 | } 207 | } 208 | 209 | func (x *ThirdExample) String() string { 210 | return protoimpl.X.MessageStringOf(x) 211 | } 212 | 213 | func (*ThirdExample) ProtoMessage() {} 214 | 215 | func (x *ThirdExample) ProtoReflect() protoreflect.Message { 216 | mi := &file_example_example_proto_msgTypes[2] 217 | if protoimpl.UnsafeEnabled && x != nil { 218 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 219 | if ms.LoadMessageInfo() == nil { 220 | ms.StoreMessageInfo(mi) 221 | } 222 | return ms 223 | } 224 | return mi.MessageOf(x) 225 | } 226 | 227 | // Deprecated: Use ThirdExample.ProtoReflect.Descriptor instead. 228 | func (*ThirdExample) Descriptor() ([]byte, []int) { 229 | return file_example_example_proto_rawDescGZIP(), []int{2} 230 | } 231 | 232 | func (x *ThirdExample) GetInnerExample() *ThirdExample_InnerExample { 233 | if x != nil { 234 | return x.InnerExample 235 | } 236 | return nil 237 | } 238 | 239 | type ThirdExample_InnerExample struct { 240 | state protoimpl.MessageState 241 | sizeCache protoimpl.SizeCache 242 | unknownFields protoimpl.UnknownFields 243 | 244 | Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"yes"` 245 | Yes int32 `protobuf:"varint,2,opt,name=yes,proto3" json:"id"` 246 | } 247 | 248 | func (x *ThirdExample_InnerExample) Reset() { 249 | *x = ThirdExample_InnerExample{} 250 | if protoimpl.UnsafeEnabled { 251 | mi := &file_example_example_proto_msgTypes[3] 252 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 253 | ms.StoreMessageInfo(mi) 254 | } 255 | } 256 | 257 | func (x *ThirdExample_InnerExample) String() string { 258 | return protoimpl.X.MessageStringOf(x) 259 | } 260 | 261 | func (*ThirdExample_InnerExample) ProtoMessage() {} 262 | 263 | func (x *ThirdExample_InnerExample) ProtoReflect() protoreflect.Message { 264 | mi := &file_example_example_proto_msgTypes[3] 265 | if protoimpl.UnsafeEnabled && x != nil { 266 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 267 | if ms.LoadMessageInfo() == nil { 268 | ms.StoreMessageInfo(mi) 269 | } 270 | return ms 271 | } 272 | return mi.MessageOf(x) 273 | } 274 | 275 | // Deprecated: Use ThirdExample_InnerExample.ProtoReflect.Descriptor instead. 276 | func (*ThirdExample_InnerExample) Descriptor() ([]byte, []int) { 277 | return file_example_example_proto_rawDescGZIP(), []int{2, 0} 278 | } 279 | 280 | func (x *ThirdExample_InnerExample) GetId() string { 281 | if x != nil { 282 | return x.Id 283 | } 284 | return "" 285 | } 286 | 287 | func (x *ThirdExample_InnerExample) GetYes() int32 { 288 | if x != nil { 289 | return x.Yes 290 | } 291 | return 0 292 | } 293 | 294 | var File_example_example_proto protoreflect.FileDescriptor 295 | 296 | var file_example_example_proto_rawDesc = []byte{ 297 | 0x0a, 0x15, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 298 | 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 299 | 0x1a, 0x13, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x2f, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x2e, 300 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8d, 0x03, 0x0a, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 301 | 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x74, 0x61, 302 | 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, 0x9a, 0x84, 0x9e, 0x03, 0x1e, 0x67, 303 | 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x3a, 0x22, 0x77, 0x69, 0x74, 0x68, 0x4e, 0x65, 0x77, 0x54, 304 | 0x61, 0x67, 0x73, 0x2c, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x52, 0x0b, 0x77, 305 | 0x69, 0x74, 0x68, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x67, 0x73, 0x12, 0x65, 0x0a, 0x11, 0x77, 0x69, 306 | 0x74, 0x68, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x18, 307 | 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x39, 0x9a, 0x84, 0x9e, 0x03, 0x34, 0x67, 0x72, 0x61, 0x70, 308 | 0x68, 0x71, 0x6c, 0x3a, 0x22, 0x77, 0x69, 0x74, 0x68, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x67, 0x73, 309 | 0x2c, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x20, 0x78, 0x6d, 0x6c, 0x3a, 0x22, 310 | 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2c, 0x6f, 0x6d, 0x69, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x22, 311 | 0x52, 0x0f, 0x77, 0x69, 0x74, 0x68, 0x4e, 0x65, 0x77, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 312 | 0x65, 0x12, 0x49, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x65, 0x66, 313 | 0x61, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1b, 0x9a, 0x84, 0x9e, 0x03, 314 | 0x16, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x50, 0x72, 315 | 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x22, 0x48, 0x01, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6c, 0x61, 316 | 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x01, 317 | 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0x9a, 0x84, 0x9e, 0x03, 0x08, 0x6a, 0x73, 318 | 0x6f, 0x6e, 0x3a, 0x22, 0x41, 0x22, 0x48, 0x00, 0x52, 0x01, 0x61, 0x12, 0x25, 0x0a, 0x04, 0x62, 319 | 0x5f, 0x6a, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x42, 0x10, 0x9a, 0x84, 0x9e, 0x03, 0x0b, 320 | 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x62, 0x5f, 0x4a, 0x6b, 0x22, 0x48, 0x00, 0x52, 0x03, 0x62, 321 | 0x4a, 0x6b, 0x42, 0x2d, 0x0a, 0x06, 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x66, 0x12, 0x23, 0x9a, 0x84, 322 | 0x9e, 0x03, 0x1e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x3a, 0x22, 0x77, 0x69, 0x74, 0x68, 323 | 0x4e, 0x65, 0x77, 0x54, 0x61, 0x67, 0x73, 0x2c, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 324 | 0x22, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x65, 325 | 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x85, 0x02, 0x0a, 0x0d, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 326 | 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x77, 0x69, 0x74, 0x68, 0x5f, 327 | 0x6e, 0x65, 0x77, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, 328 | 0x9a, 0x84, 0x9e, 0x03, 0x1e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x3a, 0x22, 0x77, 0x69, 329 | 0x74, 0x68, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x67, 0x73, 0x2c, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 330 | 0x61, 0x6c, 0x22, 0x52, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x67, 0x73, 331 | 0x12, 0x65, 0x0a, 0x11, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x75, 0x6c, 332 | 0x74, 0x69, 0x70, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x39, 0x9a, 0x84, 0x9e, 333 | 0x03, 0x34, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x3a, 0x22, 0x77, 0x69, 0x74, 0x68, 0x4e, 334 | 0x65, 0x77, 0x54, 0x61, 0x67, 0x73, 0x2c, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 335 | 0x20, 0x78, 0x6d, 0x6c, 0x3a, 0x22, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2c, 0x6f, 0x6d, 0x69, 0x74, 336 | 0x65, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x52, 0x0f, 0x77, 0x69, 0x74, 0x68, 0x4e, 0x65, 0x77, 0x4d, 337 | 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x12, 0x44, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6c, 0x61, 338 | 0x63, 0x65, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 339 | 0x42, 0x1b, 0x9a, 0x84, 0x9e, 0x03, 0x16, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x72, 0x65, 0x70, 340 | 0x6c, 0x61, 0x63, 0x65, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x22, 0x52, 0x0e, 0x72, 341 | 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0xbd, 0x01, 342 | 0x0a, 0x0c, 0x54, 0x68, 0x69, 0x72, 0x64, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x5a, 343 | 0x0a, 0x0d, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, 344 | 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 345 | 0x54, 0x68, 0x69, 0x72, 0x64, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x49, 0x6e, 0x6e, 346 | 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x11, 0x9a, 0x84, 0x9e, 0x03, 0x0c, 347 | 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x22, 0x52, 0x0c, 0x69, 0x6e, 348 | 0x6e, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x1a, 0x51, 0x0a, 0x0c, 0x49, 0x6e, 349 | 0x6e, 0x65, 0x72, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x02, 0x69, 0x64, 350 | 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0f, 0x9a, 0x84, 0x9e, 0x03, 0x0a, 0x6a, 0x73, 0x6f, 351 | 0x6e, 0x3a, 0x22, 0x79, 0x65, 0x73, 0x22, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x03, 0x79, 352 | 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x42, 0x0e, 0x9a, 0x84, 0x9e, 0x03, 0x09, 0x6a, 353 | 0x73, 0x6f, 0x6e, 0x3a, 0x22, 0x69, 0x64, 0x22, 0x52, 0x03, 0x79, 0x65, 0x73, 0x42, 0x2e, 0x5a, 354 | 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x72, 0x69, 0x6b, 355 | 0x72, 0x73, 0x6e, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 356 | 0x67, 0x6f, 0x74, 0x61, 0x67, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x62, 0x06, 0x70, 357 | 0x72, 0x6f, 0x74, 0x6f, 0x33, 358 | } 359 | 360 | var ( 361 | file_example_example_proto_rawDescOnce sync.Once 362 | file_example_example_proto_rawDescData = file_example_example_proto_rawDesc 363 | ) 364 | 365 | func file_example_example_proto_rawDescGZIP() []byte { 366 | file_example_example_proto_rawDescOnce.Do(func() { 367 | file_example_example_proto_rawDescData = protoimpl.X.CompressGZIP(file_example_example_proto_rawDescData) 368 | }) 369 | return file_example_example_proto_rawDescData 370 | } 371 | 372 | var file_example_example_proto_msgTypes = make([]protoimpl.MessageInfo, 4) 373 | var file_example_example_proto_goTypes = []interface{}{ 374 | (*Example)(nil), // 0: example.Example 375 | (*SecondMessage)(nil), // 1: example.SecondMessage 376 | (*ThirdExample)(nil), // 2: example.ThirdExample 377 | (*ThirdExample_InnerExample)(nil), // 3: example.ThirdExample.InnerExample 378 | } 379 | var file_example_example_proto_depIdxs = []int32{ 380 | 3, // 0: example.ThirdExample.inner_example:type_name -> example.ThirdExample.InnerExample 381 | 1, // [1:1] is the sub-list for method output_type 382 | 1, // [1:1] is the sub-list for method input_type 383 | 1, // [1:1] is the sub-list for extension type_name 384 | 1, // [1:1] is the sub-list for extension extendee 385 | 0, // [0:1] is the sub-list for field type_name 386 | } 387 | 388 | func init() { file_example_example_proto_init() } 389 | func file_example_example_proto_init() { 390 | if File_example_example_proto != nil { 391 | return 392 | } 393 | if !protoimpl.UnsafeEnabled { 394 | file_example_example_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 395 | switch v := v.(*Example); i { 396 | case 0: 397 | return &v.state 398 | case 1: 399 | return &v.sizeCache 400 | case 2: 401 | return &v.unknownFields 402 | default: 403 | return nil 404 | } 405 | } 406 | file_example_example_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 407 | switch v := v.(*SecondMessage); i { 408 | case 0: 409 | return &v.state 410 | case 1: 411 | return &v.sizeCache 412 | case 2: 413 | return &v.unknownFields 414 | default: 415 | return nil 416 | } 417 | } 418 | file_example_example_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 419 | switch v := v.(*ThirdExample); i { 420 | case 0: 421 | return &v.state 422 | case 1: 423 | return &v.sizeCache 424 | case 2: 425 | return &v.unknownFields 426 | default: 427 | return nil 428 | } 429 | } 430 | file_example_example_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { 431 | switch v := v.(*ThirdExample_InnerExample); i { 432 | case 0: 433 | return &v.state 434 | case 1: 435 | return &v.sizeCache 436 | case 2: 437 | return &v.unknownFields 438 | default: 439 | return nil 440 | } 441 | } 442 | } 443 | file_example_example_proto_msgTypes[0].OneofWrappers = []interface{}{ 444 | (*Example_A)(nil), 445 | (*Example_BJk)(nil), 446 | } 447 | type x struct{} 448 | out := protoimpl.TypeBuilder{ 449 | File: protoimpl.DescBuilder{ 450 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 451 | RawDescriptor: file_example_example_proto_rawDesc, 452 | NumEnums: 0, 453 | NumMessages: 4, 454 | NumExtensions: 0, 455 | NumServices: 0, 456 | }, 457 | GoTypes: file_example_example_proto_goTypes, 458 | DependencyIndexes: file_example_example_proto_depIdxs, 459 | MessageInfos: file_example_example_proto_msgTypes, 460 | }.Build() 461 | File_example_example_proto = out.File 462 | file_example_example_proto_rawDesc = nil 463 | file_example_example_proto_goTypes = nil 464 | file_example_example_proto_depIdxs = nil 465 | } 466 | -------------------------------------------------------------------------------- /example/example.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package example; 4 | 5 | import "tagger/tagger.proto"; 6 | 7 | option go_package = "github.com/srikrsna/protoc-gen-gotag/example"; 8 | 9 | message Example { 10 | string with_new_tags = 1 [(tagger.tags) = "graphql:\"withNewTags,optional\"" ]; 11 | string with_new_multiple = 2 [(tagger.tags) = "graphql:\"withNewTags,optional\" xml:\"multi,omitempty\"" ]; 12 | 13 | optional string replace_default = 3 [(tagger.tags) = "json:\"replacePrevious\""] ; 14 | 15 | oneof one_of { 16 | option (tagger.oneof_tags) = "graphql:\"withNewTags,optional\""; 17 | string a = 5 [(tagger.tags) = "json:\"A\""]; 18 | int32 b_jk = 6 [(tagger.tags) = "json:\"b_Jk\""]; 19 | } 20 | } 21 | 22 | message SecondMessage { 23 | string with_new_tags = 1 [(tagger.tags) = "graphql:\"withNewTags,optional\"" ]; 24 | string with_new_multiple = 2 [(tagger.tags) = "graphql:\"withNewTags,optional\" xml:\"multi,omitempty\"" ]; 25 | 26 | string replace_default = 3 [(tagger.tags) = "json:\"replacePrevious\""] ; 27 | } 28 | 29 | message ThirdExample { 30 | message InnerExample { 31 | string id = 1 [(tagger.tags) = "json:\"yes\""]; 32 | int32 yes = 2 [(tagger.tags) = "json:\"id\""]; 33 | } 34 | 35 | InnerExample inner_example = 1 [(tagger.tags) = "json:\"inner\""]; 36 | } -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/srikrsna/protoc-gen-gotag 2 | 3 | go 1.16 4 | 5 | retract v0.6.0 6 | 7 | require ( 8 | github.com/fatih/structtag v1.2.0 9 | github.com/lyft/protoc-gen-star/v2 v2.0.3 10 | github.com/spf13/afero v1.5.1 11 | golang.org/x/text v0.3.8 // indirect 12 | google.golang.org/protobuf v1.34.1 13 | ) 14 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= 4 | github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= 5 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 6 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 7 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 8 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 9 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 10 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 11 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 12 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 13 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 14 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 15 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 16 | github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 17 | github.com/lyft/protoc-gen-star/v2 v2.0.3 h1:/3+/2sWyXeMLzKd1bX+ixWKgEMsULrIivpDsuaF441o= 18 | github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= 19 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 20 | github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= 21 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 22 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 23 | github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= 24 | github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg= 25 | github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= 26 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 27 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 28 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 29 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 30 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 31 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 32 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 33 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 34 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= 35 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 36 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 37 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 38 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 39 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 40 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 41 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 42 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 43 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 44 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 45 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 46 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 47 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= 48 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 49 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 50 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 51 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 52 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 53 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 54 | golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= 55 | golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 56 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 57 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 58 | golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= 59 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 60 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 61 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 62 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 63 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 64 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 65 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 66 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 67 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 68 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 69 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 70 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 71 | google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= 72 | google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 73 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 74 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 75 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 76 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 77 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | pgs "github.com/lyft/protoc-gen-star/v2" 5 | pgsgo "github.com/lyft/protoc-gen-star/v2/lang/go" 6 | "google.golang.org/protobuf/types/pluginpb" 7 | 8 | "github.com/srikrsna/protoc-gen-gotag/module" 9 | ) 10 | 11 | func main() { 12 | opt := uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) 13 | 14 | pgs.Init( 15 | pgs.DebugEnv("GOTAG_DEBUG"), 16 | pgs.SupportedFeatures(&opt), 17 | ). 18 | RegisterModule(module.New()). 19 | RegisterPostProcessor(pgsgo.GoFmt()). 20 | Render() 21 | } 22 | -------------------------------------------------------------------------------- /module/extract.go: -------------------------------------------------------------------------------- 1 | package module 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/fatih/structtag" 7 | pgs "github.com/lyft/protoc-gen-star/v2" 8 | pgsgo "github.com/lyft/protoc-gen-star/v2/lang/go" 9 | 10 | "github.com/srikrsna/protoc-gen-gotag/tagger" 11 | ) 12 | 13 | type tagExtractor struct { 14 | pgs.Visitor 15 | pgs.DebuggerCommon 16 | pgsgo.Context 17 | 18 | tags map[string]map[string]*structtag.Tags 19 | autoAddTags map[string]func(name pgs.Name) pgs.Name 20 | } 21 | 22 | func newTagExtractor(d pgs.DebuggerCommon, ctx pgsgo.Context, autoTags []string) *tagExtractor { 23 | v := &tagExtractor{DebuggerCommon: d, Context: ctx, autoAddTags: map[string]func(name pgs.Name) pgs.Name{}} 24 | v.Visitor = pgs.PassThroughVisitor(v) 25 | for _, autoTag := range autoTags { 26 | info := strings.Split(autoTag, "-as-") 27 | tagName := info[0] 28 | if len(info) == 1 { 29 | v.autoAddTags[tagName] = pgs.Name.LowerSnakeCase 30 | } else { 31 | switch strings.ToLower(info[1]) { 32 | case "lower_snake", "lower_snake_case", "snake", "snake_case": 33 | v.autoAddTags[tagName] = pgs.Name.LowerSnakeCase 34 | case "upper_snake", "upper_snake_case": 35 | v.autoAddTags[tagName] = pgs.Name.UpperSnakeCase 36 | case "lower_camel", "lower_camel_case", "camel", "camel_case": 37 | v.autoAddTags[tagName] = pgs.Name.LowerCamelCase 38 | case "upper_camel", "upper_camel_case": 39 | v.autoAddTags[tagName] = pgs.Name.UpperCamelCase 40 | case "dot_notation", "dot", "lower_dot_notation", "lower_dot": 41 | v.autoAddTags[tagName] = pgs.Name.LowerDotNotation 42 | case "upper_dot", "upper_dot_notation": 43 | v.autoAddTags[tagName] = pgs.Name.UpperDotNotation 44 | } 45 | } 46 | 47 | } 48 | return v 49 | } 50 | 51 | func (v *tagExtractor) VisitOneOf(o pgs.OneOf) (pgs.Visitor, error) { 52 | var tval string 53 | ok, err := o.Extension(tagger.E_OneofTags, &tval) 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | msgName := v.Context.Name(o.Message()).String() 59 | 60 | if v.tags[msgName] == nil { 61 | v.tags[msgName] = map[string]*structtag.Tags{} 62 | } 63 | 64 | if !ok { 65 | return v, nil 66 | } 67 | 68 | tags, err := structtag.Parse(tval) 69 | if err != nil { 70 | return nil, err 71 | } 72 | 73 | v.tags[msgName][v.Context.Name(o).String()] = tags 74 | 75 | return v, nil 76 | } 77 | 78 | func (v *tagExtractor) VisitField(f pgs.Field) (pgs.Visitor, error) { 79 | var tval string 80 | ok, err := f.Extension(tagger.E_Tags, &tval) 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | msgName := v.Context.Name(f.Message()).String() 86 | if f.InOneOf() && !f.Descriptor().GetProto3Optional() { 87 | msgName = f.Message().Name().UpperCamelCase().String() + "_" + f.Name().UpperCamelCase().String() 88 | } 89 | 90 | if v.tags[msgName] == nil { 91 | v.tags[msgName] = map[string]*structtag.Tags{} 92 | } 93 | 94 | tags := structtag.Tags{} 95 | if len(v.autoAddTags) > 0 { 96 | for tag, transform := range v.autoAddTags { 97 | t := structtag.Tag{ 98 | Key: tag, 99 | Name: transform(v.Context.Name(f)).String(), 100 | Options: nil, 101 | } 102 | if err := tags.Set(&t); err != nil { 103 | v.DebuggerCommon.Fail("Error without tag", err) 104 | } 105 | } 106 | } 107 | 108 | if !ok { 109 | v.tags[msgName][v.Context.Name(f).String()] = &tags 110 | return v, nil 111 | } 112 | 113 | newTags, err := structtag.Parse(tval) 114 | v.CheckErr(err) 115 | for _, tag := range newTags.Tags() { 116 | if err := tags.Set(tag); err != nil { 117 | v.DebuggerCommon.Fail("Error with tag: ", err) 118 | } 119 | } 120 | 121 | v.tags[msgName][v.Context.Name(f).String()] = &tags 122 | 123 | return v, nil 124 | } 125 | 126 | func (v *tagExtractor) Extract(f pgs.File) StructTags { 127 | v.tags = map[string]map[string]*structtag.Tags{} 128 | 129 | v.CheckErr(pgs.Walk(v, f)) 130 | 131 | return v.tags 132 | } 133 | -------------------------------------------------------------------------------- /module/extract_test.go: -------------------------------------------------------------------------------- 1 | package module_test 2 | 3 | import ( 4 | "bytes" 5 | "os" 6 | "testing" 7 | 8 | pgs "github.com/lyft/protoc-gen-star/v2" 9 | "github.com/spf13/afero" 10 | "github.com/srikrsna/protoc-gen-gotag/module" 11 | ) 12 | 13 | func TestExtract(t *testing.T) { 14 | req, err := os.Open("../debug/code_generator_request.pb.bin") 15 | if err != nil { 16 | t.Fatal(err) 17 | } 18 | 19 | fs := afero.NewMemMapFs() 20 | res := &bytes.Buffer{} 21 | 22 | pgs.Init( 23 | pgs.ProtocInput(req), 24 | pgs.ProtocOutput(res), 25 | pgs.FileSystem(fs), 26 | ).RegisterModule(module.New()).Render() 27 | } 28 | -------------------------------------------------------------------------------- /module/replace.go: -------------------------------------------------------------------------------- 1 | package module 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | "sort" 7 | "strings" 8 | 9 | "github.com/fatih/structtag" 10 | ) 11 | 12 | type StructTags map[string]map[string]*structtag.Tags 13 | 14 | func (s StructTags) AddTagsToXXXFields(tags *structtag.Tags) { 15 | xtags := map[string]*structtag.Tags{ 16 | "XXX_NoUnkeyedLiteral": tags, 17 | "XXX_unrecognized": tags, 18 | "XXX_sizecache": tags, 19 | } 20 | 21 | for o := range s { 22 | if s[o] == nil { 23 | s[o] = map[string]*structtag.Tags{} 24 | } 25 | 26 | for k, v := range xtags { 27 | s[o][k] = v 28 | } 29 | } 30 | } 31 | 32 | // Retag updates the existing tags with the map passed and modifies existing tags if any of the keys are matched. 33 | // First key to the tags argument is the name of the struct, the second key corresponds to field names. 34 | func Retag(n ast.Node, tags StructTags) error { 35 | r := retag{} 36 | f := func(n ast.Node) ast.Visitor { 37 | if r.err != nil { 38 | return nil 39 | } 40 | 41 | if tp, ok := n.(*ast.TypeSpec); ok { 42 | r.tags = tags[tp.Name.String()] 43 | return r 44 | } 45 | 46 | return nil 47 | } 48 | 49 | ast.Walk(structVisitor{f}, n) 50 | 51 | return r.err 52 | } 53 | 54 | type structVisitor struct { 55 | visitor func(n ast.Node) ast.Visitor 56 | } 57 | 58 | func (v structVisitor) Visit(n ast.Node) ast.Visitor { 59 | if tp, ok := n.(*ast.TypeSpec); ok { 60 | if _, ok := tp.Type.(*ast.StructType); ok { 61 | ast.Walk(v.visitor(n), n) 62 | return nil // This will ensure this struct is no longer traversed 63 | } 64 | } 65 | return v 66 | } 67 | 68 | type retag struct { 69 | err error 70 | tags map[string]*structtag.Tags 71 | } 72 | 73 | func (v retag) Visit(n ast.Node) ast.Visitor { 74 | if v.err != nil { 75 | return nil 76 | } 77 | 78 | if f, ok := n.(*ast.Field); ok { 79 | if len(f.Names) == 0 { 80 | return nil 81 | } 82 | newTags := v.tags[f.Names[0].String()] 83 | if newTags == nil { 84 | return nil 85 | } 86 | 87 | if f.Tag == nil { 88 | f.Tag = &ast.BasicLit{ 89 | Kind: token.STRING, 90 | } 91 | } 92 | 93 | oldTags, err := structtag.Parse(strings.Trim(f.Tag.Value, "`")) 94 | if err != nil { 95 | v.err = err 96 | return nil 97 | } 98 | 99 | sort.Stable(newTags) // sort tags according to keys 100 | for _, t := range newTags.Tags() { 101 | oldTags.Set(t) 102 | } 103 | 104 | f.Tag.Value = "`" + oldTags.String() + "`" 105 | 106 | return nil 107 | } 108 | 109 | return v 110 | } 111 | -------------------------------------------------------------------------------- /module/replace_test.go: -------------------------------------------------------------------------------- 1 | package module_test 2 | 3 | import ( 4 | "bytes" 5 | "flag" 6 | "go/parser" 7 | "go/printer" 8 | "go/token" 9 | "io" 10 | "io/ioutil" 11 | "os" 12 | "testing" 13 | 14 | "github.com/fatih/structtag" 15 | 16 | "github.com/srikrsna/protoc-gen-gotag/module" 17 | ) 18 | 19 | var replaceOut = flag.Bool("tag-rep", false, "") 20 | 21 | func TestRetag(t *testing.T) { 22 | fs := token.NewFileSet() 23 | 24 | n, err := parser.ParseFile(fs, "./test/input.txt", nil, parser.ParseComments) 25 | if err != nil { 26 | t.Fatal(err) 27 | } 28 | 29 | module.Retag(n, map[string]map[string]*structtag.Tags{ 30 | "Simple": { 31 | "Single": tagMust(structtag.Parse(`sql:"-,omitempty"`)), 32 | "Multiple": tagMust(structtag.Parse(`xml:"-,omitempty" sql:"ke,op" bson:"ke,op"`)), 33 | "None": tagMust(structtag.Parse(`json:"none,omitempty"`)), 34 | }, 35 | }) 36 | 37 | var buf bytes.Buffer 38 | if err := printer.Fprint(&buf, fs, n); err != nil { 39 | t.Fatal(err) 40 | } 41 | 42 | if *replaceOut { 43 | f, err := os.Create("./test/golden.txt") 44 | if err != nil { 45 | t.Fatal(err) 46 | } 47 | defer f.Close() 48 | 49 | if _, err := io.Copy(f, &buf); err != nil { 50 | t.Fatal(err) 51 | } 52 | 53 | return 54 | } 55 | 56 | out, err := ioutil.ReadFile("./test/golden.txt") 57 | if err != nil { 58 | t.Fatal(err) 59 | } 60 | 61 | if !bytes.Equal(out, buf.Bytes()) { 62 | t.Error("output does not match golden file") 63 | } 64 | } 65 | 66 | func tagMust(t *structtag.Tags, err error) *structtag.Tags { 67 | if err != nil { 68 | panic(err) 69 | } 70 | return t 71 | } 72 | -------------------------------------------------------------------------------- /module/tagger.go: -------------------------------------------------------------------------------- 1 | package module 2 | 3 | import ( 4 | "fmt" 5 | "go/parser" 6 | "go/printer" 7 | "go/token" 8 | "path/filepath" 9 | "strings" 10 | 11 | "github.com/fatih/structtag" 12 | pgs "github.com/lyft/protoc-gen-star/v2" 13 | pgsgo "github.com/lyft/protoc-gen-star/v2/lang/go" 14 | ) 15 | 16 | type mod struct { 17 | *pgs.ModuleBase 18 | pgsgo.Context 19 | } 20 | 21 | func New() pgs.Module { 22 | return &mod{ModuleBase: &pgs.ModuleBase{}} 23 | } 24 | 25 | func (m *mod) InitContext(c pgs.BuildContext) { 26 | m.ModuleBase.InitContext(c) 27 | m.Context = pgsgo.InitContext(c.Parameters()) 28 | } 29 | 30 | func (mod) Name() string { 31 | return "gotag" 32 | } 33 | 34 | func (m mod) Execute(targets map[string]pgs.File, packages map[string]pgs.Package) []pgs.Artifact { 35 | xtv := m.Parameters().Str("xxx") 36 | 37 | xtv = strings.Replace(xtv, "+", ":", -1) 38 | 39 | xt, err := structtag.Parse(xtv) 40 | m.CheckErr(err) 41 | 42 | autoTag := m.Parameters().Str("auto") 43 | var autoTags []string 44 | if autoTag != "" { 45 | autoTags = strings.Split(autoTag, "+") 46 | } 47 | 48 | module := m.Parameters().Str("module") 49 | 50 | extractor := newTagExtractor(m, m.Context, autoTags) 51 | 52 | for _, f := range targets { 53 | tags := extractor.Extract(f) 54 | 55 | tags.AddTagsToXXXFields(xt) 56 | 57 | gfname := m.Context.OutputPath(f).SetExt(".go").String() 58 | 59 | outdir := m.Parameters().Str("outdir") 60 | filename := gfname 61 | if outdir != "" { 62 | filename = filepath.Join(outdir, gfname) 63 | } 64 | 65 | if module != "" { 66 | 67 | filename = strings.ReplaceAll(filename, string(filepath.Separator), "/") 68 | trim := module + "/" 69 | if !strings.HasPrefix(filename, trim) { 70 | m.Debug(fmt.Sprintf("%v: generated file does not match prefix %q", filename, module)) 71 | m.Exit(1) 72 | } 73 | filename = strings.TrimPrefix(filename, trim) 74 | } 75 | 76 | fs := token.NewFileSet() 77 | fn, err := parser.ParseFile(fs, filename, nil, parser.ParseComments) 78 | m.CheckErr(err) 79 | 80 | m.CheckErr(Retag(fn, tags)) 81 | 82 | var buf strings.Builder 83 | m.CheckErr(printer.Fprint(&buf, fs, fn)) 84 | 85 | m.OverwriteGeneratorFile(filename, buf.String()) 86 | } 87 | 88 | return m.Artifacts() 89 | } 90 | -------------------------------------------------------------------------------- /module/test/golden.txt: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Simple struct { 4 | Single string `json:"key,option" sql:"-,omitempty"` 5 | Multiple *string `json:"ke,op" xml:"-,omitempty" bson:"ke,op" sql:"ke,op"` 6 | None int32 `json:"none,omitempty"` 7 | } 8 | -------------------------------------------------------------------------------- /module/test/input.txt: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Simple struct { 4 | Single string `json:"key,option"` 5 | Multiple *string `json:"ke,op" xml:"ke,op"` 6 | None int32 7 | } 8 | -------------------------------------------------------------------------------- /tagger/tagger.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.32.0 4 | // protoc (unknown) 5 | // source: tagger/tagger.proto 6 | 7 | package tagger 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | descriptorpb "google.golang.org/protobuf/types/descriptorpb" 13 | reflect "reflect" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | var file_tagger_tagger_proto_extTypes = []protoimpl.ExtensionInfo{ 24 | { 25 | ExtendedType: (*descriptorpb.FieldOptions)(nil), 26 | ExtensionType: (*string)(nil), 27 | Field: 847939, 28 | Name: "tagger.tags", 29 | Tag: "bytes,847939,opt,name=tags", 30 | Filename: "tagger/tagger.proto", 31 | }, 32 | { 33 | ExtendedType: (*descriptorpb.OneofOptions)(nil), 34 | ExtensionType: (*string)(nil), 35 | Field: 847939, 36 | Name: "tagger.oneof_tags", 37 | Tag: "bytes,847939,opt,name=oneof_tags", 38 | Filename: "tagger/tagger.proto", 39 | }, 40 | } 41 | 42 | // Extension fields to descriptorpb.FieldOptions. 43 | var ( 44 | // Multiple Tags can be specified. 45 | // 46 | // optional string tags = 847939; 47 | E_Tags = &file_tagger_tagger_proto_extTypes[0] 48 | ) 49 | 50 | // Extension fields to descriptorpb.OneofOptions. 51 | var ( 52 | // Multiple Tags can be specified. 53 | // 54 | // optional string oneof_tags = 847939; 55 | E_OneofTags = &file_tagger_tagger_proto_extTypes[1] 56 | ) 57 | 58 | var File_tagger_tagger_proto protoreflect.FileDescriptor 59 | 60 | var file_tagger_tagger_proto_rawDesc = []byte{ 61 | 0x0a, 0x13, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x2f, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x2e, 62 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x1a, 0x20, 0x67, 63 | 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 64 | 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, 65 | 0x33, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 66 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 67 | 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xc3, 0xe0, 0x33, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 68 | 0x74, 0x61, 0x67, 0x73, 0x3a, 0x3e, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x74, 0x61, 69 | 0x67, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 70 | 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 71 | 0x73, 0x18, 0xc3, 0xe0, 0x33, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 72 | 0x54, 0x61, 0x67, 0x73, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 73 | 0x6f, 0x6d, 0x2f, 0x73, 0x72, 0x69, 0x6b, 0x72, 0x73, 0x6e, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 74 | 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x74, 0x61, 0x67, 0x2f, 0x74, 0x61, 0x67, 75 | 0x67, 0x65, 0x72, 0x3b, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 76 | 0x6f, 0x33, 77 | } 78 | 79 | var file_tagger_tagger_proto_goTypes = []interface{}{ 80 | (*descriptorpb.FieldOptions)(nil), // 0: google.protobuf.FieldOptions 81 | (*descriptorpb.OneofOptions)(nil), // 1: google.protobuf.OneofOptions 82 | } 83 | var file_tagger_tagger_proto_depIdxs = []int32{ 84 | 0, // 0: tagger.tags:extendee -> google.protobuf.FieldOptions 85 | 1, // 1: tagger.oneof_tags:extendee -> google.protobuf.OneofOptions 86 | 2, // [2:2] is the sub-list for method output_type 87 | 2, // [2:2] is the sub-list for method input_type 88 | 2, // [2:2] is the sub-list for extension type_name 89 | 0, // [0:2] is the sub-list for extension extendee 90 | 0, // [0:0] is the sub-list for field type_name 91 | } 92 | 93 | func init() { file_tagger_tagger_proto_init() } 94 | func file_tagger_tagger_proto_init() { 95 | if File_tagger_tagger_proto != nil { 96 | return 97 | } 98 | type x struct{} 99 | out := protoimpl.TypeBuilder{ 100 | File: protoimpl.DescBuilder{ 101 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 102 | RawDescriptor: file_tagger_tagger_proto_rawDesc, 103 | NumEnums: 0, 104 | NumMessages: 0, 105 | NumExtensions: 2, 106 | NumServices: 0, 107 | }, 108 | GoTypes: file_tagger_tagger_proto_goTypes, 109 | DependencyIndexes: file_tagger_tagger_proto_depIdxs, 110 | ExtensionInfos: file_tagger_tagger_proto_extTypes, 111 | }.Build() 112 | File_tagger_tagger_proto = out.File 113 | file_tagger_tagger_proto_rawDesc = nil 114 | file_tagger_tagger_proto_goTypes = nil 115 | file_tagger_tagger_proto_depIdxs = nil 116 | } 117 | -------------------------------------------------------------------------------- /tagger/tagger.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package tagger; 4 | 5 | import "google/protobuf/descriptor.proto"; 6 | 7 | option go_package = "github.com/srikrsna/protoc-gen-gotag/tagger;tagger"; 8 | 9 | // Tags are applied at the field level 10 | extend google.protobuf.FieldOptions { 11 | // Multiple Tags can be specified. 12 | string tags = 847939; 13 | } 14 | 15 | extend google.protobuf.OneofOptions { 16 | // Multiple Tags can be specified. 17 | string oneof_tags = 847939; 18 | } 19 | --------------------------------------------------------------------------------