Skip to content

Commit

Permalink
Merge pull request #176 from Mik-/race-condition-check
Browse files Browse the repository at this point in the history
fix: error with multiple files and custom options
  • Loading branch information
moul committed Sep 20, 2021
2 parents cd11a74 + 7db2a54 commit 605df25
Show file tree
Hide file tree
Showing 12 changed files with 283 additions and 345 deletions.
2 changes: 1 addition & 1 deletion examples/dummy/output/export.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"build-date": "2021-04-12T10:42:31.388860713Z",
"build-date": "2021-09-20T21:06:55.930665067Z",
"build-hostname": "fwrz",
"build-user": "moul",
"pwd": "/home/moul/go/src/moul.io/protoc-gen-gotemplate/examples/dummy",
Expand Down
2 changes: 1 addition & 1 deletion examples/go-generate/gen/example.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions examples/helpers/example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
{{abbrev 5 "hello world"}}: he...
{{abbrevboth 5 10 "1234 5678 9123"}}: ...5678...
{{initials "First Try"}}: FT
{{randNumeric 3}}: 616
{{randNumeric 3}}: 565
{{- /*{{wrap 80 $someText}}*/}}:
{{wrapWith 5 "\t" "Hello World"}}: Hello World
{{contains "cat" "catch"}}: true
Expand All @@ -46,7 +46,7 @@
{{regexSplit "z+" "pizza" -1}}: [pi a]

# Get one specific method on array method using index
{{ index .Service.Method 1 }}: name:"Iii" input_type:".dummy.Dummy2" output_type:".dummy.Dummy1" options:<>
{{ index .Service.Method 1 }}: name:"Iii" input_type:".dummy.Dummy2" output_type:".dummy.Dummy1" options:{}

# Sprig: advanced
{{if contains "cat" "catch"}}yes{{else}}no{{end}}: yes
Expand Down
2 changes: 1 addition & 1 deletion examples/import/output/models/article/article.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/import/output/models/common/common.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions examples/sitemap/sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
<loc>/posts</loc>
<priority>0.5</priority>
<changefreq>monthly</changefreq>
<lastmod>2021-04-12</lastmod>
<lastmod>2021-09-20</lastmod>
</url>
<url>
<loc>/authors</loc>
<priority>0.5</priority>
<changefreq>monthly</changefreq>
<lastmod>2021-04-12</lastmod>
<lastmod>2021-09-20</lastmod>
</url>
<url>
<loc>/comments</loc>
<priority>0.5</priority>
<changefreq>monthly</changefreq>
<lastmod>2021-04-12</lastmod>
<lastmod>2021-09-20</lastmod>
</url>
</urlset>
3 changes: 2 additions & 1 deletion go.mod

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

253 changes: 253 additions & 0 deletions helpers/custom_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
package pgghelpers

import (
"fmt"
"sync"

"github.com/golang/protobuf/proto" // nolint:staticcheck
"github.com/golang/protobuf/protoc-gen-go/descriptor"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl"
)

var protoregistryMutex sync.Mutex

// getExtension returns the value of an extension.
//
// If the extension with the given ID is not already registered, it will be made up.
func getExtension(extendedMessage proto.Message, extendedType proto.Message, fieldID int32, fieldType interface{}) (interface{}, error) {
// To prevent concurrent map read/write while querying the registry and registring new extensions, request a lock.
protoregistryMutex.Lock()
defer protoregistryMutex.Unlock()

// Query the registry for the given Message and field ID.
eds := make(map[int32]*protoimpl.ExtensionInfo)
protoregistry.GlobalTypes.RangeExtensionsByMessage(protoimpl.X.MessageDescriptorOf(extendedMessage).FullName(), func(xt protoreflect.ExtensionType) bool {
if xd, ok := xt.(*protoimpl.ExtensionInfo); ok {
eds[int32(xt.TypeDescriptor().Number())] = xd
}

return true
})
extensionInfo := eds[fieldID]

// Create the extension, if it was not yet found.
if extensionInfo == nil {
// Infer the struct tag type from field type.
tagType := "varint"
if _, ok := fieldType.(*string); ok {
tagType = "bytes"
}

extensionInfo = &proto.ExtensionDesc{
ExtendedType: extendedType,
ExtensionType: fieldType,
Field: fieldID,
Tag: fmt.Sprintf("%s,%d", tagType, fieldID),
Name: fmt.Sprintf("%d", fieldID),
}
err := protoregistry.GlobalTypes.RegisterExtension(extensionInfo)
if err != nil {
return nil, fmt.Errorf("error registering extension: %w", err)
}
}

return proto.GetExtension(extendedMessage, extensionInfo)
}

// stringMethodOptionsExtension extracts method options of a string type.
// To define your own extensions see:
// https://developers.google.com/protocol-buffers/docs/proto#customoptions
// Typically the fieldID of private extensions should be in the range:
// 50000-99999
func stringMethodOptionsExtension(fieldID int32, f *descriptor.MethodDescriptorProto) string {
if f == nil || f.Options == nil {
return ""
}

var extendedType *descriptor.MethodOptions
var fieldType *string

ext, err := getExtension(f.Options, extendedType, fieldID, fieldType)
if err != nil {
return ""
}

if str, ok := ext.(*string); ok {
return *str
}

return ""
}

// boolMethodOptionsExtension extracts method options of a boolean type.
func boolMethodOptionsExtension(fieldID int32, f *descriptor.MethodDescriptorProto) bool {
if f == nil || f.Options == nil {
return false
}

var extendedType *descriptor.MethodOptions
var fieldType *bool

ext, err := getExtension(f.Options, extendedType, fieldID, fieldType)
if err != nil {
return false
}

if b, ok := ext.(*bool); ok {
return *b
}

return false
}

// stringFileOptionsExtension extracts file options of a string type.
// To define your own extensions see:
// https://developers.google.com/protocol-buffers/docs/proto#customoptions
// Typically the fieldID of private extensions should be in the range:
// 50000-99999
func stringFileOptionsExtension(fieldID int32, f *descriptor.FileDescriptorProto) string {
if f == nil || f.Options == nil {
return ""
}

var extendedType *descriptor.FileOptions
var fieldType *string

ext, err := getExtension(f.Options, extendedType, fieldID, fieldType)
if err != nil {
return ""
}

if str, ok := ext.(*string); ok {
return *str
}

return ""
}

func stringFieldExtension(fieldID int32, f *descriptor.FieldDescriptorProto) string {
if f == nil || f.Options == nil {
return ""
}

var extendedType *descriptor.FieldOptions
var fieldType *string

ext, err := getExtension(f.Options, extendedType, fieldID, fieldType)
if err != nil {
return ""
}

str, ok := ext.(*string)
if !ok {
return ""
}

return *str
}

func int64FieldExtension(fieldID int32, f *descriptor.FieldDescriptorProto) int64 {
if f == nil || f.Options == nil {
return 0
}

var extendedType *descriptor.FieldOptions
var fieldType *int64

ext, err := getExtension(f.Options, extendedType, fieldID, fieldType)
if err != nil {
return 0
}

i, ok := ext.(*int64)
if !ok {
return 0
}

return *i
}

func int64MessageExtension(fieldID int32, f *descriptor.DescriptorProto) int64 {
if f == nil || f.Options == nil {
return 0
}

var extendedType *descriptor.MessageOptions
var fieldType *int64

ext, err := getExtension(f.Options, extendedType, fieldID, fieldType)
if err != nil {
return 0
}

i, ok := ext.(*int64)
if !ok {
return 0
}

return *i
}

func stringMessageExtension(fieldID int32, f *descriptor.DescriptorProto) string {
if f == nil || f.Options == nil {
return ""
}

var extendedType *descriptor.MessageOptions
var fieldType *string

ext, err := getExtension(f.Options, extendedType, fieldID, fieldType)
if err != nil {
return ""
}

str, ok := ext.(*string)
if !ok {
return ""
}

return *str
}

func boolFieldExtension(fieldID int32, f *descriptor.FieldDescriptorProto) bool {
if f == nil || f.Options == nil {
return false
}

var extendedType *descriptor.FieldOptions
var fieldType *bool

ext, err := getExtension(f.Options, extendedType, fieldID, fieldType)
if err != nil {
return false
}

b, ok := ext.(*bool)
if !ok {
return false
}

return *b
}

func boolMessageExtension(fieldID int32, f *descriptor.DescriptorProto) bool {
if f == nil || f.Options == nil {
return false
}
var extendedType *descriptor.MessageOptions
var fieldType *bool

ext, err := getExtension(f.Options, extendedType, fieldID, fieldType)
if err != nil {
return false
}

b, ok := ext.(*bool)
if !ok {
return false
}

return *b
}

0 comments on commit 605df25

Please sign in to comment.