github.com/cosmos/cosmos-proto@v1.0.0-beta.3/cmd/protoc-gen-go-pulsar/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"log"
     7  	"strings"
     8  
     9  	_ "github.com/cosmos/cosmos-proto/features/fastreflection"
    10  	_ "github.com/cosmos/cosmos-proto/features/protoc"
    11  	"github.com/cosmos/cosmos-proto/generator"
    12  	"google.golang.org/protobuf/reflect/protoreflect"
    13  
    14  	"google.golang.org/protobuf/compiler/protogen"
    15  	"google.golang.org/protobuf/types/pluginpb"
    16  )
    17  
    18  type ObjectSet map[protogen.GoIdent]bool
    19  
    20  func (o ObjectSet) String() string {
    21  	return fmt.Sprintf("%#v", o)
    22  }
    23  
    24  func (o ObjectSet) Set(s string) error {
    25  	idx := strings.LastIndexByte(s, '.')
    26  	if idx < 0 {
    27  		return fmt.Errorf("invalid object name: %q", s)
    28  	}
    29  
    30  	ident := protogen.GoIdent{
    31  		GoImportPath: protogen.GoImportPath(s[0:idx]),
    32  		GoName:       s[idx+1:],
    33  	}
    34  	o[ident] = true
    35  	return nil
    36  }
    37  
    38  func main() {
    39  	var features string
    40  	poolable := make(ObjectSet)
    41  
    42  	var f flag.FlagSet
    43  	f.Var(poolable, "pool", "use memory pooling for this object")
    44  	f.StringVar(&features, "features", "all", "list of features to generate (separated by '+')")
    45  
    46  	protogen.Options{ParamFunc: f.Set}.Run(func(plugin *protogen.Plugin) error {
    47  		processedMessages := make(map[protoreflect.FullName]struct{})
    48  		for _, file := range plugin.Files {
    49  			if !file.Generate {
    50  				continue
    51  			}
    52  			for _, message := range file.Messages {
    53  				rewriteMessageField(message, processedMessages)
    54  			}
    55  		}
    56  		return generateAllFiles(plugin, strings.Split(features, "+"), poolable)
    57  	})
    58  }
    59  
    60  var SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
    61  
    62  func generateAllFiles(plugin *protogen.Plugin, featureNames []string, poolable ObjectSet) error {
    63  	ext := &generator.Extensions{Poolable: poolable}
    64  	gen, err := generator.NewGenerator(plugin.Files, featureNames, ext)
    65  	if err != nil {
    66  		return err
    67  	}
    68  
    69  	for _, file := range plugin.Files {
    70  		if !file.Generate {
    71  			continue
    72  		}
    73  
    74  		gf := plugin.NewGeneratedFile(file.GeneratedFilenamePrefix+".pulsar.go", file.GoImportPath)
    75  		gf.P("// Code generated by protoc-gen-go-pulsar. DO NOT EDIT.")
    76  		gf.P("package ", file.GoPackageName)
    77  		if !gen.GenerateFile(plugin, gf, file) {
    78  			gf.Skip()
    79  		}
    80  	}
    81  
    82  	// plugin.SupportedFeatures = SupportedFeatures
    83  	return nil
    84  }
    85  
    86  var reservedFieldNames = map[string]struct{}{
    87  	"Descriptor":   {},
    88  	"Type":         {},
    89  	"New":          {},
    90  	"Interface":    {},
    91  	"Range":        {},
    92  	"Has":          {},
    93  	"Clear":        {},
    94  	"Get":          {},
    95  	"Set":          {},
    96  	"Mutable":      {},
    97  	"NewField":     {},
    98  	"WhichOneof":   {},
    99  	"GetUnknown":   {},
   100  	"SetUnknown":   {},
   101  	"IsValid":      {},
   102  	"ProtoMethods": {},
   103  }
   104  
   105  func rewriteMessageField(message *protogen.Message, processed map[protoreflect.FullName]struct{}) {
   106  	// skip already processed messages, useful for recursive messages
   107  	if _, done := processed[message.Desc.FullName()]; done {
   108  		return
   109  	}
   110  	// skip map entries
   111  	if message.Desc.IsMapEntry() {
   112  		return
   113  	}
   114  
   115  	for _, field := range message.Fields {
   116  		_, reserved := reservedFieldNames[field.GoName]
   117  		if !reserved {
   118  			continue
   119  		}
   120  		log.Printf("Message %s contains the reserved field name %s which conflicts with protoreflect.Message interface implementation.\nThis field will be suffixed with an underscore '_'.\nIf you can change the message field name, please do so.\nIn a future iteration of pulsar we may make a breaking change to this practice in order to be compliant with field naming of the original golang protobuf implementation.", message.Desc.FullName(), field.Desc.FullName())
   121  		field.GoName = field.GoName + "_"
   122  	}
   123  	processed[message.Desc.FullName()] = struct{}{}
   124  
   125  	for _, nestedMessage := range message.Messages {
   126  		rewriteMessageField(nestedMessage, processed)
   127  	}
   128  }