@@ -39,6 +39,22 @@ const (
39
39
// generateOneofWrapperMethods specifies whether to generate
40
40
// XXX_OneofWrappers methods on messages with oneofs.
41
41
generateOneofWrapperMethods = false
42
+
43
+ // generateNoUnkeyedLiteralFields specifies whether to generate
44
+ // the XXX_NoUnkeyedLiteral field.
45
+ generateNoUnkeyedLiteralFields = false
46
+
47
+ // generateExportedSizeCacheFields specifies whether to generate an exported
48
+ // XXX_sizecache field instead of an unexported sizeCache field.
49
+ generateExportedSizeCacheFields = false
50
+
51
+ // generateExportedUnknownFields specifies whether to generate an exported
52
+ // XXX_unrecognized field instead of an unexported unknownFields field.
53
+ generateExportedUnknownFields = false
54
+
55
+ // generateExportedExtensionFields specifies whether to generate an exported
56
+ // XXX_InternalExtensions field instead of an unexported extensionFields field.
57
+ generateExportedExtensionFields = false
42
58
)
43
59
44
60
const (
@@ -54,11 +70,28 @@ const (
54
70
type fileInfo struct {
55
71
* protogen.File
56
72
57
- allEnums []* protogen.Enum
58
- allEnumsByPtr map [* protogen.Enum ]int // value is index into allEnums
59
- allMessages []* protogen.Message
60
- allMessagesByPtr map [* protogen.Message ]int // value is index into allMessages
61
- allExtensions []* protogen.Extension
73
+ allEnums []* protogen.Enum
74
+ allMessages []* protogen.Message
75
+ allExtensions []* protogen.Extension
76
+
77
+ allEnumsByPtr map [* protogen.Enum ]int // value is index into allEnums
78
+ allMessagesByPtr map [* protogen.Message ]int // value is index into allMessages
79
+ allMessageFieldsByPtr map [* protogen.Message ]* structFields
80
+ }
81
+
82
+ type structFields struct {
83
+ count int
84
+ unexported map [int ]string
85
+ }
86
+
87
+ func (sf * structFields ) append (name string ) {
88
+ if r , _ := utf8 .DecodeRuneInString (name ); ! unicode .IsUpper (r ) {
89
+ if sf .unexported == nil {
90
+ sf .unexported = make (map [int ]string )
91
+ }
92
+ sf .unexported [sf .count ] = name
93
+ }
94
+ sf .count ++
62
95
}
63
96
64
97
// GenerateFile generates the contents of a .pb.go file.
@@ -90,8 +123,10 @@ func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.Generated
90
123
}
91
124
if len (f .allMessages ) > 0 {
92
125
f .allMessagesByPtr = make (map [* protogen.Message ]int )
126
+ f .allMessageFieldsByPtr = make (map [* protogen.Message ]* structFields )
93
127
for i , m := range f .allMessages {
94
128
f .allMessagesByPtr [m ] = i
129
+ f .allMessageFieldsByPtr [m ] = new (structFields )
95
130
}
96
131
}
97
132
@@ -347,15 +382,28 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
347
382
}
348
383
g .Annotate (message .GoIdent .GoName , message .Location )
349
384
g .P ("type " , message .GoIdent , " struct {" )
385
+ sf := f .allMessageFieldsByPtr [message ]
350
386
for _ , field := range message .Fields {
351
387
if field .Oneof != nil {
352
388
// It would be a bit simpler to iterate over the oneofs below,
353
389
// but generating the field here keeps the contents of the Go
354
390
// struct in the same order as the contents of the source
355
391
// .proto file.
356
- if field == field .Oneof .Fields [0 ] {
357
- genOneofField (gen , g , f , message , field .Oneof )
392
+ oneof := field .Oneof
393
+ if field != oneof .Fields [0 ] {
394
+ continue // already generated oneof field for first entry
395
+ }
396
+ if g .PrintLeadingComments (oneof .Location ) {
397
+ g .P ("//" )
398
+ }
399
+ g .P ("// Types that are valid to be assigned to " , oneofFieldName (oneof ), ":" )
400
+ for _ , field := range oneof .Fields {
401
+ g .PrintLeadingComments (field .Location )
402
+ g .P ("//\t *" , fieldOneofType (field ))
358
403
}
404
+ g .Annotate (message .GoIdent .GoName + "." + oneofFieldName (oneof ), oneof .Location )
405
+ g .P (oneofFieldName (oneof ), " " , oneofInterfaceName (oneof ), " `protobuf_oneof:\" " , oneof .Desc .Name (), "\" `" )
406
+ sf .append (oneofFieldName (oneof ))
359
407
continue
360
408
}
361
409
g .PrintLeadingComments (field .Location )
@@ -378,19 +426,42 @@ func genMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, me
378
426
g .Annotate (message .GoIdent .GoName + "." + field .GoName , field .Location )
379
427
g .P (field .GoName , " " , goType , " `" , strings .Join (tags , " " ), "`" ,
380
428
deprecationComment (field .Desc .Options ().(* descriptorpb.FieldOptions ).GetDeprecated ()))
429
+ sf .append (field .GoName )
381
430
}
382
- g .P ("XXX_NoUnkeyedLiteral struct{} `json:\" -\" `" )
383
431
432
+ if generateNoUnkeyedLiteralFields {
433
+ g .P ("XXX_NoUnkeyedLiteral" , " struct{} `json:\" -\" `" )
434
+ sf .append ("XXX_NoUnkeyedLiteral" )
435
+ }
436
+ if generateExportedSizeCacheFields {
437
+ g .P ("XXX_sizecache" , " " , protoimplPackage .Ident ("SizeCache" ), " `json:\" -\" `" )
438
+ sf .append ("XXX_sizecache" )
439
+ } else {
440
+ g .P ("sizeCache" , " " , protoimplPackage .Ident ("SizeCache" ))
441
+ sf .append ("sizeCache" )
442
+ }
443
+ if generateExportedUnknownFields {
444
+ g .P ("XXX_unrecognized" , " " , protoimplPackage .Ident ("UnknownFields" ), " `json:\" -\" `" )
445
+ sf .append ("XXX_unrecognized" )
446
+ } else {
447
+ g .P ("unknownFields" , " " , protoimplPackage .Ident ("UnknownFields" ))
448
+ sf .append ("unknownFields" )
449
+ }
384
450
if message .Desc .ExtensionRanges ().Len () > 0 {
451
+ // TODO: Remove this tag when we drop v1 support.
385
452
var tags []string
386
453
if message .Desc .Options ().(* descriptorpb.MessageOptions ).GetMessageSetWireFormat () {
387
454
tags = append (tags , `protobuf_messageset:"1"` )
388
455
}
389
- tags = append (tags , `json:"-"` )
390
- g .P ("XXX_InternalExtensions " , protoimplPackage .Ident ("ExtensionFields" ), " `" , strings .Join (tags , " " ), "`" )
456
+ if generateExportedExtensionFields {
457
+ tags = append (tags , `json:"-"` )
458
+ g .P ("XXX_InternalExtensions" , " " , protoimplPackage .Ident ("ExtensionFields" ), " `" , strings .Join (tags , " " ), "`" )
459
+ sf .append ("XXX_InternalExtensions" )
460
+ } else {
461
+ g .P ("extensionFields" , " " , protoimplPackage .Ident ("ExtensionFields" ), " `" , strings .Join (tags , " " ), "`" )
462
+ sf .append ("extensionFields" )
463
+ }
391
464
}
392
- g .P ("XXX_unrecognized " , protoimplPackage .Ident ("UnknownFields" ), " `json:\" -\" `" )
393
- g .P ("XXX_sizecache " , protoimplPackage .Ident ("SizeCache" ), " `json:\" -\" `" )
394
465
g .P ("}" )
395
466
g .P ()
396
467
@@ -744,20 +815,6 @@ var wellKnownTypes = map[protoreflect.FullName]bool{
744
815
"google.protobuf.Value" : true ,
745
816
}
746
817
747
- // genOneofField generates the struct field for a oneof.
748
- func genOneofField (gen * protogen.Plugin , g * protogen.GeneratedFile , f * fileInfo , message * protogen.Message , oneof * protogen.Oneof ) {
749
- if g .PrintLeadingComments (oneof .Location ) {
750
- g .P ("//" )
751
- }
752
- g .P ("// Types that are valid to be assigned to " , oneofFieldName (oneof ), ":" )
753
- for _ , field := range oneof .Fields {
754
- g .PrintLeadingComments (field .Location )
755
- g .P ("//\t *" , fieldOneofType (field ))
756
- }
757
- g .Annotate (message .GoIdent .GoName + "." + oneofFieldName (oneof ), oneof .Location )
758
- g .P (oneofFieldName (oneof ), " " , oneofInterfaceName (oneof ), " `protobuf_oneof:\" " , oneof .Desc .Name (), "\" `" )
759
- }
760
-
761
818
// genOneofGetter generate a Get method for a oneof.
762
819
func genOneofGetter (gen * protogen.Plugin , g * protogen.GeneratedFile , f * fileInfo , message * protogen.Message , oneof * protogen.Oneof ) {
763
820
g .Annotate (message .GoIdent .GoName + ".Get" + oneof .GoName , oneof .Location )
0 commit comments