...

Source file src/github.com/gogo/protobuf/protoc-gen-gogo/generator/generator.go

Documentation: github.com/gogo/protobuf/protoc-gen-gogo/generator

     1  // Protocol Buffers for Go with Gadgets
     2  //
     3  // Copyright (c) 2013, The GoGo Authors. All rights reserved.
     4  // http://github.com/gogo/protobuf
     5  //
     6  // Go support for Protocol Buffers - Google's data interchange format
     7  //
     8  // Copyright 2010 The Go Authors.  All rights reserved.
     9  // https://github.com/golang/protobuf
    10  //
    11  // Redistribution and use in source and binary forms, with or without
    12  // modification, are permitted provided that the following conditions are
    13  // met:
    14  //
    15  //     * Redistributions of source code must retain the above copyright
    16  // notice, this list of conditions and the following disclaimer.
    17  //     * Redistributions in binary form must reproduce the above
    18  // copyright notice, this list of conditions and the following disclaimer
    19  // in the documentation and/or other materials provided with the
    20  // distribution.
    21  //     * Neither the name of Google Inc. nor the names of its
    22  // contributors may be used to endorse or promote products derived from
    23  // this software without specific prior written permission.
    24  //
    25  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    26  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    27  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    28  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    29  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    30  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    31  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    32  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    33  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    34  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    35  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    36  
    37  /*
    38  	The code generator for the plugin for the Google protocol buffer compiler.
    39  	It generates Go code from the protocol buffer description files read by the
    40  	main routine.
    41  */
    42  package generator
    43  
    44  import (
    45  	"bufio"
    46  	"bytes"
    47  	"compress/gzip"
    48  	"crypto/sha256"
    49  	"encoding/hex"
    50  	"fmt"
    51  	"go/ast"
    52  	"go/build"
    53  	"go/parser"
    54  	"go/printer"
    55  	"go/token"
    56  	"log"
    57  	"os"
    58  	"path"
    59  	"sort"
    60  	"strconv"
    61  	"strings"
    62  	"unicode"
    63  	"unicode/utf8"
    64  
    65  	"github.com/gogo/protobuf/gogoproto"
    66  	"github.com/gogo/protobuf/proto"
    67  	descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
    68  	"github.com/gogo/protobuf/protoc-gen-gogo/generator/internal/remap"
    69  	plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin"
    70  )
    71  
    72  // generatedCodeVersion indicates a version of the generated code.
    73  // It is incremented whenever an incompatibility between the generated code and
    74  // proto package is introduced; the generated code references
    75  // a constant, proto.ProtoPackageIsVersionN (where N is generatedCodeVersion).
    76  const generatedCodeVersion = 3
    77  
    78  // A Plugin provides functionality to add to the output during Go code generation,
    79  // such as to produce RPC stubs.
    80  type Plugin interface {
    81  	// Name identifies the plugin.
    82  	Name() string
    83  	// Init is called once after data structures are built but before
    84  	// code generation begins.
    85  	Init(g *Generator)
    86  	// Generate produces the code generated by the plugin for this file,
    87  	// except for the imports, by calling the generator's methods P, In, and Out.
    88  	Generate(file *FileDescriptor)
    89  	// GenerateImports produces the import declarations for this file.
    90  	// It is called after Generate.
    91  	GenerateImports(file *FileDescriptor)
    92  }
    93  
    94  type pluginSlice []Plugin
    95  
    96  func (ps pluginSlice) Len() int {
    97  	return len(ps)
    98  }
    99  
   100  func (ps pluginSlice) Less(i, j int) bool {
   101  	return ps[i].Name() < ps[j].Name()
   102  }
   103  
   104  func (ps pluginSlice) Swap(i, j int) {
   105  	ps[i], ps[j] = ps[j], ps[i]
   106  }
   107  
   108  var plugins pluginSlice
   109  
   110  // RegisterPlugin installs a (second-order) plugin to be run when the Go output is generated.
   111  // It is typically called during initialization.
   112  func RegisterPlugin(p Plugin) {
   113  	plugins = append(plugins, p)
   114  }
   115  
   116  // A GoImportPath is the import path of a Go package. e.g., "google.golang.org/genproto/protobuf".
   117  type GoImportPath string
   118  
   119  func (p GoImportPath) String() string { return strconv.Quote(string(p)) }
   120  
   121  // A GoPackageName is the name of a Go package. e.g., "protobuf".
   122  type GoPackageName string
   123  
   124  // Each type we import as a protocol buffer (other than FileDescriptorProto) needs
   125  // a pointer to the FileDescriptorProto that represents it.  These types achieve that
   126  // wrapping by placing each Proto inside a struct with the pointer to its File. The
   127  // structs have the same names as their contents, with "Proto" removed.
   128  // FileDescriptor is used to store the things that it points to.
   129  
   130  // The file and package name method are common to messages and enums.
   131  type common struct {
   132  	file *FileDescriptor // File this object comes from.
   133  }
   134  
   135  // GoImportPath is the import path of the Go package containing the type.
   136  func (c *common) GoImportPath() GoImportPath {
   137  	return c.file.importPath
   138  }
   139  
   140  func (c *common) File() *FileDescriptor { return c.file }
   141  
   142  func fileIsProto3(file *descriptor.FileDescriptorProto) bool {
   143  	return file.GetSyntax() == "proto3"
   144  }
   145  
   146  func (c *common) proto3() bool { return fileIsProto3(c.file.FileDescriptorProto) }
   147  
   148  // Descriptor represents a protocol buffer message.
   149  type Descriptor struct {
   150  	common
   151  	*descriptor.DescriptorProto
   152  	parent   *Descriptor            // The containing message, if any.
   153  	nested   []*Descriptor          // Inner messages, if any.
   154  	enums    []*EnumDescriptor      // Inner enums, if any.
   155  	ext      []*ExtensionDescriptor // Extensions, if any.
   156  	typename []string               // Cached typename vector.
   157  	index    int                    // The index into the container, whether the file or another message.
   158  	path     string                 // The SourceCodeInfo path as comma-separated integers.
   159  	group    bool
   160  }
   161  
   162  // TypeName returns the elements of the dotted type name.
   163  // The package name is not part of this name.
   164  func (d *Descriptor) TypeName() []string {
   165  	if d.typename != nil {
   166  		return d.typename
   167  	}
   168  	n := 0
   169  	for parent := d; parent != nil; parent = parent.parent {
   170  		n++
   171  	}
   172  	s := make([]string, n)
   173  	for parent := d; parent != nil; parent = parent.parent {
   174  		n--
   175  		s[n] = parent.GetName()
   176  	}
   177  	d.typename = s
   178  	return s
   179  }
   180  
   181  func (d *Descriptor) allowOneof() bool {
   182  	return true
   183  }
   184  
   185  // EnumDescriptor describes an enum. If it's at top level, its parent will be nil.
   186  // Otherwise it will be the descriptor of the message in which it is defined.
   187  type EnumDescriptor struct {
   188  	common
   189  	*descriptor.EnumDescriptorProto
   190  	parent   *Descriptor // The containing message, if any.
   191  	typename []string    // Cached typename vector.
   192  	index    int         // The index into the container, whether the file or a message.
   193  	path     string      // The SourceCodeInfo path as comma-separated integers.
   194  }
   195  
   196  // TypeName returns the elements of the dotted type name.
   197  // The package name is not part of this name.
   198  func (e *EnumDescriptor) TypeName() (s []string) {
   199  	if e.typename != nil {
   200  		return e.typename
   201  	}
   202  	name := e.GetName()
   203  	if e.parent == nil {
   204  		s = make([]string, 1)
   205  	} else {
   206  		pname := e.parent.TypeName()
   207  		s = make([]string, len(pname)+1)
   208  		copy(s, pname)
   209  	}
   210  	s[len(s)-1] = name
   211  	e.typename = s
   212  	return s
   213  }
   214  
   215  // alias provides the TypeName corrected for the application of any naming
   216  // extensions on the enum type. It should be used for generating references to
   217  // the Go types and for calculating prefixes.
   218  func (e *EnumDescriptor) alias() (s []string) {
   219  	s = e.TypeName()
   220  	if gogoproto.IsEnumCustomName(e.EnumDescriptorProto) {
   221  		s[len(s)-1] = gogoproto.GetEnumCustomName(e.EnumDescriptorProto)
   222  	}
   223  
   224  	return
   225  }
   226  
   227  // Everything but the last element of the full type name, CamelCased.
   228  // The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... .
   229  func (e *EnumDescriptor) prefix() string {
   230  	typeName := e.alias()
   231  	if e.parent == nil {
   232  		// If the enum is not part of a message, the prefix is just the type name.
   233  		return CamelCase(typeName[len(typeName)-1]) + "_"
   234  	}
   235  	return CamelCaseSlice(typeName[0:len(typeName)-1]) + "_"
   236  }
   237  
   238  // The integer value of the named constant in this enumerated type.
   239  func (e *EnumDescriptor) integerValueAsString(name string) string {
   240  	for _, c := range e.Value {
   241  		if c.GetName() == name {
   242  			return fmt.Sprint(c.GetNumber())
   243  		}
   244  	}
   245  	log.Fatal("cannot find value for enum constant")
   246  	return ""
   247  }
   248  
   249  // ExtensionDescriptor describes an extension. If it's at top level, its parent will be nil.
   250  // Otherwise it will be the descriptor of the message in which it is defined.
   251  type ExtensionDescriptor struct {
   252  	common
   253  	*descriptor.FieldDescriptorProto
   254  	parent *Descriptor // The containing message, if any.
   255  }
   256  
   257  // TypeName returns the elements of the dotted type name.
   258  // The package name is not part of this name.
   259  func (e *ExtensionDescriptor) TypeName() (s []string) {
   260  	name := e.GetName()
   261  	if e.parent == nil {
   262  		// top-level extension
   263  		s = make([]string, 1)
   264  	} else {
   265  		pname := e.parent.TypeName()
   266  		s = make([]string, len(pname)+1)
   267  		copy(s, pname)
   268  	}
   269  	s[len(s)-1] = name
   270  	return s
   271  }
   272  
   273  // DescName returns the variable name used for the generated descriptor.
   274  func (e *ExtensionDescriptor) DescName() string {
   275  	// The full type name.
   276  	typeName := e.TypeName()
   277  	// Each scope of the extension is individually CamelCased, and all are joined with "_" with an "E_" prefix.
   278  	for i, s := range typeName {
   279  		typeName[i] = CamelCase(s)
   280  	}
   281  	return "E_" + strings.Join(typeName, "_")
   282  }
   283  
   284  // ImportedDescriptor describes a type that has been publicly imported from another file.
   285  type ImportedDescriptor struct {
   286  	common
   287  	o Object
   288  }
   289  
   290  func (id *ImportedDescriptor) TypeName() []string { return id.o.TypeName() }
   291  
   292  // FileDescriptor describes an protocol buffer descriptor file (.proto).
   293  // It includes slices of all the messages and enums defined within it.
   294  // Those slices are constructed by WrapTypes.
   295  type FileDescriptor struct {
   296  	*descriptor.FileDescriptorProto
   297  	desc []*Descriptor          // All the messages defined in this file.
   298  	enum []*EnumDescriptor      // All the enums defined in this file.
   299  	ext  []*ExtensionDescriptor // All the top-level extensions defined in this file.
   300  	imp  []*ImportedDescriptor  // All types defined in files publicly imported by this file.
   301  
   302  	// Comments, stored as a map of path (comma-separated integers) to the comment.
   303  	comments map[string]*descriptor.SourceCodeInfo_Location
   304  
   305  	// The full list of symbols that are exported,
   306  	// as a map from the exported object to its symbols.
   307  	// This is used for supporting public imports.
   308  	exported map[Object][]symbol
   309  
   310  	importPath  GoImportPath  // Import path of this file's package.
   311  	packageName GoPackageName // Name of this file's Go package.
   312  
   313  	proto3 bool // whether to generate proto3 code for this file
   314  }
   315  
   316  // VarName is the variable name we'll use in the generated code to refer
   317  // to the compressed bytes of this descriptor. It is not exported, so
   318  // it is only valid inside the generated package.
   319  func (d *FileDescriptor) VarName() string {
   320  	h := sha256.Sum256([]byte(d.GetName()))
   321  	return fmt.Sprintf("fileDescriptor_%s", hex.EncodeToString(h[:8]))
   322  }
   323  
   324  // goPackageOption interprets the file's go_package option.
   325  // If there is no go_package, it returns ("", "", false).
   326  // If there's a simple name, it returns ("", pkg, true).
   327  // If the option implies an import path, it returns (impPath, pkg, true).
   328  func (d *FileDescriptor) goPackageOption() (impPath GoImportPath, pkg GoPackageName, ok bool) {
   329  	opt := d.GetOptions().GetGoPackage()
   330  	if opt == "" {
   331  		return "", "", false
   332  	}
   333  	// A semicolon-delimited suffix delimits the import path and package name.
   334  	sc := strings.Index(opt, ";")
   335  	if sc >= 0 {
   336  		return GoImportPath(opt[:sc]), cleanPackageName(opt[sc+1:]), true
   337  	}
   338  	// The presence of a slash implies there's an import path.
   339  	slash := strings.LastIndex(opt, "/")
   340  	if slash >= 0 {
   341  		return GoImportPath(opt), cleanPackageName(opt[slash+1:]), true
   342  	}
   343  	return "", cleanPackageName(opt), true
   344  }
   345  
   346  // goFileName returns the output name for the generated Go file.
   347  func (d *FileDescriptor) goFileName(pathType pathType) string {
   348  	name := *d.Name
   349  	if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" {
   350  		name = name[:len(name)-len(ext)]
   351  	}
   352  	name += ".pb.go"
   353  
   354  	if pathType == pathTypeSourceRelative {
   355  		return name
   356  	}
   357  
   358  	// Does the file have a "go_package" option?
   359  	// If it does, it may override the filename.
   360  	if impPath, _, ok := d.goPackageOption(); ok && impPath != "" {
   361  		// Replace the existing dirname with the declared import path.
   362  		_, name = path.Split(name)
   363  		name = path.Join(string(impPath), name)
   364  		return name
   365  	}
   366  
   367  	return name
   368  }
   369  
   370  func (d *FileDescriptor) addExport(obj Object, sym symbol) {
   371  	d.exported[obj] = append(d.exported[obj], sym)
   372  }
   373  
   374  // symbol is an interface representing an exported Go symbol.
   375  type symbol interface {
   376  	// GenerateAlias should generate an appropriate alias
   377  	// for the symbol from the named package.
   378  	GenerateAlias(g *Generator, filename string, pkg GoPackageName)
   379  }
   380  
   381  type messageSymbol struct {
   382  	sym                         string
   383  	hasExtensions, isMessageSet bool
   384  	oneofTypes                  []string
   385  }
   386  
   387  type getterSymbol struct {
   388  	name     string
   389  	typ      string
   390  	typeName string // canonical name in proto world; empty for proto.Message and similar
   391  	genType  bool   // whether typ contains a generated type (message/group/enum)
   392  }
   393  
   394  func (ms *messageSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) {
   395  	g.P("// ", ms.sym, " from public import ", filename)
   396  	g.P("type ", ms.sym, " = ", pkg, ".", ms.sym)
   397  	for _, name := range ms.oneofTypes {
   398  		g.P("type ", name, " = ", pkg, ".", name)
   399  	}
   400  }
   401  
   402  type enumSymbol struct {
   403  	name   string
   404  	proto3 bool // Whether this came from a proto3 file.
   405  }
   406  
   407  func (es enumSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) {
   408  	s := es.name
   409  	g.P("// ", s, " from public import ", filename)
   410  	g.P("type ", s, " = ", pkg, ".", s)
   411  	g.P("var ", s, "_name = ", pkg, ".", s, "_name")
   412  	g.P("var ", s, "_value = ", pkg, ".", s, "_value")
   413  }
   414  
   415  type constOrVarSymbol struct {
   416  	sym  string
   417  	typ  string // either "const" or "var"
   418  	cast string // if non-empty, a type cast is required (used for enums)
   419  }
   420  
   421  func (cs constOrVarSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) {
   422  	v := string(pkg) + "." + cs.sym
   423  	if cs.cast != "" {
   424  		v = cs.cast + "(" + v + ")"
   425  	}
   426  	g.P(cs.typ, " ", cs.sym, " = ", v)
   427  }
   428  
   429  // Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects.
   430  type Object interface {
   431  	GoImportPath() GoImportPath
   432  	TypeName() []string
   433  	File() *FileDescriptor
   434  }
   435  
   436  // Generator is the type whose methods generate the output, stored in the associated response structure.
   437  type Generator struct {
   438  	*bytes.Buffer
   439  
   440  	Request  *plugin.CodeGeneratorRequest  // The input.
   441  	Response *plugin.CodeGeneratorResponse // The output.
   442  
   443  	Param             map[string]string // Command-line parameters.
   444  	PackageImportPath string            // Go import path of the package we're generating code for
   445  	ImportPrefix      string            // String to prefix to imported package file names.
   446  	ImportMap         map[string]string // Mapping from .proto file name to import path
   447  
   448  	Pkg map[string]string // The names under which we import support packages
   449  
   450  	outputImportPath GoImportPath                   // Package we're generating code for.
   451  	allFiles         []*FileDescriptor              // All files in the tree
   452  	allFilesByName   map[string]*FileDescriptor     // All files by filename.
   453  	genFiles         []*FileDescriptor              // Those files we will generate output for.
   454  	file             *FileDescriptor                // The file we are compiling now.
   455  	packageNames     map[GoImportPath]GoPackageName // Imported package names in the current file.
   456  	usedPackages     map[GoImportPath]bool          // Packages used in current file.
   457  	usedPackageNames map[GoPackageName]bool         // Package names used in the current file.
   458  	addedImports     map[GoImportPath]bool          // Additional imports to emit.`
   459  	typeNameToObject map[string]Object              // Key is a fully-qualified name in input syntax.
   460  	init             []string                       // Lines to emit in the init function.
   461  	indent           string
   462  	pathType         pathType // How to generate output filenames.
   463  	writeOutput      bool
   464  	annotateCode     bool                                       // whether to store annotations
   465  	annotations      []*descriptor.GeneratedCodeInfo_Annotation // annotations to store
   466  
   467  	customImports  []string
   468  	writtenImports map[string]bool // For de-duplicating written imports
   469  }
   470  
   471  type pathType int
   472  
   473  const (
   474  	pathTypeImport pathType = iota
   475  	pathTypeSourceRelative
   476  )
   477  
   478  // New creates a new generator and allocates the request and response protobufs.
   479  func New() *Generator {
   480  	g := new(Generator)
   481  	g.Buffer = new(bytes.Buffer)
   482  	g.Request = new(plugin.CodeGeneratorRequest)
   483  	g.Response = new(plugin.CodeGeneratorResponse)
   484  	g.writtenImports = make(map[string]bool)
   485  	g.addedImports = make(map[GoImportPath]bool)
   486  	return g
   487  }
   488  
   489  // Error reports a problem, including an error, and exits the program.
   490  func (g *Generator) Error(err error, msgs ...string) {
   491  	s := strings.Join(msgs, " ") + ":" + err.Error()
   492  	log.Print("protoc-gen-gogo: error:", s)
   493  	os.Exit(1)
   494  }
   495  
   496  // Fail reports a problem and exits the program.
   497  func (g *Generator) Fail(msgs ...string) {
   498  	s := strings.Join(msgs, " ")
   499  	log.Print("protoc-gen-gogo: error:", s)
   500  	os.Exit(1)
   501  }
   502  
   503  // CommandLineParameters breaks the comma-separated list of key=value pairs
   504  // in the parameter (a member of the request protobuf) into a key/value map.
   505  // It then sets file name mappings defined by those entries.
   506  func (g *Generator) CommandLineParameters(parameter string) {
   507  	g.Param = make(map[string]string)
   508  	for _, p := range strings.Split(parameter, ",") {
   509  		if i := strings.Index(p, "="); i < 0 {
   510  			g.Param[p] = ""
   511  		} else {
   512  			g.Param[p[0:i]] = p[i+1:]
   513  		}
   514  	}
   515  
   516  	g.ImportMap = make(map[string]string)
   517  	pluginList := "none" // Default list of plugin names to enable (empty means all).
   518  	for k, v := range g.Param {
   519  		switch k {
   520  		case "import_prefix":
   521  			g.ImportPrefix = v
   522  		case "import_path":
   523  			g.PackageImportPath = v
   524  		case "paths":
   525  			switch v {
   526  			case "import":
   527  				g.pathType = pathTypeImport
   528  			case "source_relative":
   529  				g.pathType = pathTypeSourceRelative
   530  			default:
   531  				g.Fail(fmt.Sprintf(`Unknown path type %q: want "import" or "source_relative".`, v))
   532  			}
   533  		case "plugins":
   534  			pluginList = v
   535  		case "annotate_code":
   536  			if v == "true" {
   537  				g.annotateCode = true
   538  			}
   539  		default:
   540  			if len(k) > 0 && k[0] == 'M' {
   541  				g.ImportMap[k[1:]] = v
   542  			}
   543  		}
   544  	}
   545  	if pluginList == "" {
   546  		return
   547  	}
   548  	if pluginList == "none" {
   549  		pluginList = ""
   550  	}
   551  	gogoPluginNames := []string{"unmarshal", "unsafeunmarshaler", "union", "stringer", "size", "protosizer", "populate", "marshalto", "unsafemarshaler", "gostring", "face", "equal", "enumstringer", "embedcheck", "description", "defaultcheck", "oneofcheck", "compare"}
   552  	pluginList = strings.Join(append(gogoPluginNames, pluginList), "+")
   553  	if pluginList != "" {
   554  		// Amend the set of plugins.
   555  		enabled := make(map[string]bool)
   556  		for _, name := range strings.Split(pluginList, "+") {
   557  			enabled[name] = true
   558  		}
   559  		var nplugins pluginSlice
   560  		for _, p := range plugins {
   561  			if enabled[p.Name()] {
   562  				nplugins = append(nplugins, p)
   563  			}
   564  		}
   565  		sort.Sort(nplugins)
   566  		plugins = nplugins
   567  	}
   568  }
   569  
   570  // DefaultPackageName returns the package name printed for the object.
   571  // If its file is in a different package, it returns the package name we're using for this file, plus ".".
   572  // Otherwise it returns the empty string.
   573  func (g *Generator) DefaultPackageName(obj Object) string {
   574  	importPath := obj.GoImportPath()
   575  	if importPath == g.outputImportPath {
   576  		return ""
   577  	}
   578  	return string(g.GoPackageName(importPath)) + "."
   579  }
   580  
   581  // GoPackageName returns the name used for a package.
   582  func (g *Generator) GoPackageName(importPath GoImportPath) GoPackageName {
   583  	if name, ok := g.packageNames[importPath]; ok {
   584  		return name
   585  	}
   586  	name := cleanPackageName(baseName(string(importPath)))
   587  	for i, orig := 1, name; g.usedPackageNames[name] || isGoPredeclaredIdentifier[string(name)]; i++ {
   588  		name = orig + GoPackageName(strconv.Itoa(i))
   589  	}
   590  	if g.packageNames == nil {
   591  		g.packageNames = make(map[GoImportPath]GoPackageName)
   592  	}
   593  	g.packageNames[importPath] = name
   594  	if g.usedPackageNames == nil {
   595  		g.usedPackageNames = make(map[GoPackageName]bool)
   596  	}
   597  	g.usedPackageNames[name] = true
   598  	return name
   599  }
   600  
   601  // AddImport adds a package to the generated file's import section.
   602  // It returns the name used for the package.
   603  func (g *Generator) AddImport(importPath GoImportPath) GoPackageName {
   604  	g.addedImports[importPath] = true
   605  	return g.GoPackageName(importPath)
   606  }
   607  
   608  var globalPackageNames = map[GoPackageName]bool{
   609  	"fmt":   true,
   610  	"math":  true,
   611  	"proto": true,
   612  }
   613  
   614  // Create and remember a guaranteed unique package name. Pkg is the candidate name.
   615  // The FileDescriptor parameter is unused.
   616  func RegisterUniquePackageName(pkg string, f *FileDescriptor) string {
   617  	name := cleanPackageName(pkg)
   618  	for i, orig := 1, name; globalPackageNames[name]; i++ {
   619  		name = orig + GoPackageName(strconv.Itoa(i))
   620  	}
   621  	globalPackageNames[name] = true
   622  	return string(name)
   623  }
   624  
   625  var isGoKeyword = map[string]bool{
   626  	"break":       true,
   627  	"case":        true,
   628  	"chan":        true,
   629  	"const":       true,
   630  	"continue":    true,
   631  	"default":     true,
   632  	"else":        true,
   633  	"defer":       true,
   634  	"fallthrough": true,
   635  	"for":         true,
   636  	"func":        true,
   637  	"go":          true,
   638  	"goto":        true,
   639  	"if":          true,
   640  	"import":      true,
   641  	"interface":   true,
   642  	"map":         true,
   643  	"package":     true,
   644  	"range":       true,
   645  	"return":      true,
   646  	"select":      true,
   647  	"struct":      true,
   648  	"switch":      true,
   649  	"type":        true,
   650  	"var":         true,
   651  }
   652  
   653  var isGoPredeclaredIdentifier = map[string]bool{
   654  	"append":     true,
   655  	"bool":       true,
   656  	"byte":       true,
   657  	"cap":        true,
   658  	"close":      true,
   659  	"complex":    true,
   660  	"complex128": true,
   661  	"complex64":  true,
   662  	"copy":       true,
   663  	"delete":     true,
   664  	"error":      true,
   665  	"false":      true,
   666  	"float32":    true,
   667  	"float64":    true,
   668  	"imag":       true,
   669  	"int":        true,
   670  	"int16":      true,
   671  	"int32":      true,
   672  	"int64":      true,
   673  	"int8":       true,
   674  	"iota":       true,
   675  	"len":        true,
   676  	"make":       true,
   677  	"new":        true,
   678  	"nil":        true,
   679  	"panic":      true,
   680  	"print":      true,
   681  	"println":    true,
   682  	"real":       true,
   683  	"recover":    true,
   684  	"rune":       true,
   685  	"string":     true,
   686  	"true":       true,
   687  	"uint":       true,
   688  	"uint16":     true,
   689  	"uint32":     true,
   690  	"uint64":     true,
   691  	"uint8":      true,
   692  	"uintptr":    true,
   693  }
   694  
   695  func cleanPackageName(name string) GoPackageName {
   696  	name = strings.Map(badToUnderscore, name)
   697  	// Identifier must not be keyword: insert _.
   698  	if isGoKeyword[name] {
   699  		name = "_" + name
   700  	}
   701  	// Identifier must not begin with digit: insert _.
   702  	if r, _ := utf8.DecodeRuneInString(name); unicode.IsDigit(r) {
   703  		name = "_" + name
   704  	}
   705  	return GoPackageName(name)
   706  }
   707  
   708  // defaultGoPackage returns the package name to use,
   709  // derived from the import path of the package we're building code for.
   710  func (g *Generator) defaultGoPackage() GoPackageName {
   711  	p := g.PackageImportPath
   712  	if i := strings.LastIndex(p, "/"); i >= 0 {
   713  		p = p[i+1:]
   714  	}
   715  	return cleanPackageName(p)
   716  }
   717  
   718  // SetPackageNames sets the package name for this run.
   719  // The package name must agree across all files being generated.
   720  // It also defines unique package names for all imported files.
   721  func (g *Generator) SetPackageNames() {
   722  	g.outputImportPath = g.genFiles[0].importPath
   723  
   724  	defaultPackageNames := make(map[GoImportPath]GoPackageName)
   725  	for _, f := range g.genFiles {
   726  		if _, p, ok := f.goPackageOption(); ok {
   727  			defaultPackageNames[f.importPath] = p
   728  		}
   729  	}
   730  	for _, f := range g.genFiles {
   731  		if _, p, ok := f.goPackageOption(); ok {
   732  			// Source file: option go_package = "quux/bar";
   733  			f.packageName = p
   734  		} else if p, ok := defaultPackageNames[f.importPath]; ok {
   735  			// A go_package option in another file in the same package.
   736  			//
   737  			// This is a poor choice in general, since every source file should
   738  			// contain a go_package option. Supported mainly for historical
   739  			// compatibility.
   740  			f.packageName = p
   741  		} else if p := g.defaultGoPackage(); p != "" {
   742  			// Command-line: import_path=quux/bar.
   743  			//
   744  			// The import_path flag sets a package name for files which don't
   745  			// contain a go_package option.
   746  			f.packageName = p
   747  		} else if p := f.GetPackage(); p != "" {
   748  			// Source file: package quux.bar;
   749  			f.packageName = cleanPackageName(p)
   750  		} else {
   751  			// Source filename.
   752  			f.packageName = cleanPackageName(baseName(f.GetName()))
   753  		}
   754  	}
   755  
   756  	// Check that all files have a consistent package name and import path.
   757  	for _, f := range g.genFiles[1:] {
   758  		if a, b := g.genFiles[0].importPath, f.importPath; a != b {
   759  			g.Fail(fmt.Sprintf("inconsistent package import paths: %v, %v", a, b))
   760  		}
   761  		if a, b := g.genFiles[0].packageName, f.packageName; a != b {
   762  			g.Fail(fmt.Sprintf("inconsistent package names: %v, %v", a, b))
   763  		}
   764  	}
   765  
   766  	// Names of support packages. These never vary (if there are conflicts,
   767  	// we rename the conflicting package), so this could be removed someday.
   768  	g.Pkg = map[string]string{
   769  		"fmt":          "fmt",
   770  		"math":         "math",
   771  		"proto":        "proto",
   772  		"golang_proto": "golang_proto",
   773  	}
   774  }
   775  
   776  // WrapTypes walks the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos
   777  // and FileDescriptorProtos into file-referenced objects within the Generator.
   778  // It also creates the list of files to generate and so should be called before GenerateAllFiles.
   779  func (g *Generator) WrapTypes() {
   780  	g.allFiles = make([]*FileDescriptor, 0, len(g.Request.ProtoFile))
   781  	g.allFilesByName = make(map[string]*FileDescriptor, len(g.allFiles))
   782  	genFileNames := make(map[string]bool)
   783  	for _, n := range g.Request.FileToGenerate {
   784  		genFileNames[n] = true
   785  	}
   786  	for _, f := range g.Request.ProtoFile {
   787  		fd := &FileDescriptor{
   788  			FileDescriptorProto: f,
   789  			exported:            make(map[Object][]symbol),
   790  			proto3:              fileIsProto3(f),
   791  		}
   792  		// The import path may be set in a number of ways.
   793  		if substitution, ok := g.ImportMap[f.GetName()]; ok {
   794  			// Command-line: M=foo.proto=quux/bar.
   795  			//
   796  			// Explicit mapping of source file to import path.
   797  			fd.importPath = GoImportPath(substitution)
   798  		} else if genFileNames[f.GetName()] && g.PackageImportPath != "" {
   799  			// Command-line: import_path=quux/bar.
   800  			//
   801  			// The import_path flag sets the import path for every file that
   802  			// we generate code for.
   803  			fd.importPath = GoImportPath(g.PackageImportPath)
   804  		} else if p, _, _ := fd.goPackageOption(); p != "" {
   805  			// Source file: option go_package = "quux/bar";
   806  			//
   807  			// The go_package option sets the import path. Most users should use this.
   808  			fd.importPath = p
   809  		} else {
   810  			// Source filename.
   811  			//
   812  			// Last resort when nothing else is available.
   813  			fd.importPath = GoImportPath(path.Dir(f.GetName()))
   814  		}
   815  		// We must wrap the descriptors before we wrap the enums
   816  		fd.desc = wrapDescriptors(fd)
   817  		g.buildNestedDescriptors(fd.desc)
   818  		fd.enum = wrapEnumDescriptors(fd, fd.desc)
   819  		g.buildNestedEnums(fd.desc, fd.enum)
   820  		fd.ext = wrapExtensions(fd)
   821  		extractComments(fd)
   822  		g.allFiles = append(g.allFiles, fd)
   823  		g.allFilesByName[f.GetName()] = fd
   824  	}
   825  	for _, fd := range g.allFiles {
   826  		fd.imp = wrapImported(fd, g)
   827  	}
   828  
   829  	g.genFiles = make([]*FileDescriptor, 0, len(g.Request.FileToGenerate))
   830  	for _, fileName := range g.Request.FileToGenerate {
   831  		fd := g.allFilesByName[fileName]
   832  		if fd == nil {
   833  			g.Fail("could not find file named", fileName)
   834  		}
   835  		g.genFiles = append(g.genFiles, fd)
   836  	}
   837  }
   838  
   839  // Scan the descriptors in this file.  For each one, build the slice of nested descriptors
   840  func (g *Generator) buildNestedDescriptors(descs []*Descriptor) {
   841  	for _, desc := range descs {
   842  		if len(desc.NestedType) != 0 {
   843  			for _, nest := range descs {
   844  				if nest.parent == desc {
   845  					desc.nested = append(desc.nested, nest)
   846  				}
   847  			}
   848  			if len(desc.nested) != len(desc.NestedType) {
   849  				g.Fail("internal error: nesting failure for", desc.GetName())
   850  			}
   851  		}
   852  	}
   853  }
   854  
   855  func (g *Generator) buildNestedEnums(descs []*Descriptor, enums []*EnumDescriptor) {
   856  	for _, desc := range descs {
   857  		if len(desc.EnumType) != 0 {
   858  			for _, enum := range enums {
   859  				if enum.parent == desc {
   860  					desc.enums = append(desc.enums, enum)
   861  				}
   862  			}
   863  			if len(desc.enums) != len(desc.EnumType) {
   864  				g.Fail("internal error: enum nesting failure for", desc.GetName())
   865  			}
   866  		}
   867  	}
   868  }
   869  
   870  // Construct the Descriptor
   871  func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *Descriptor {
   872  	d := &Descriptor{
   873  		common:          common{file},
   874  		DescriptorProto: desc,
   875  		parent:          parent,
   876  		index:           index,
   877  	}
   878  	if parent == nil {
   879  		d.path = fmt.Sprintf("%d,%d", messagePath, index)
   880  	} else {
   881  		d.path = fmt.Sprintf("%s,%d,%d", parent.path, messageMessagePath, index)
   882  	}
   883  
   884  	// The only way to distinguish a group from a message is whether
   885  	// the containing message has a TYPE_GROUP field that matches.
   886  	if parent != nil {
   887  		parts := d.TypeName()
   888  		if file.Package != nil {
   889  			parts = append([]string{*file.Package}, parts...)
   890  		}
   891  		exp := "." + strings.Join(parts, ".")
   892  		for _, field := range parent.Field {
   893  			if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetTypeName() == exp {
   894  				d.group = true
   895  				break
   896  			}
   897  		}
   898  	}
   899  
   900  	for _, field := range desc.Extension {
   901  		d.ext = append(d.ext, &ExtensionDescriptor{common{file}, field, d})
   902  	}
   903  
   904  	return d
   905  }
   906  
   907  // Return a slice of all the Descriptors defined within this file
   908  func wrapDescriptors(file *FileDescriptor) []*Descriptor {
   909  	sl := make([]*Descriptor, 0, len(file.MessageType)+10)
   910  	for i, desc := range file.MessageType {
   911  		sl = wrapThisDescriptor(sl, desc, nil, file, i)
   912  	}
   913  	return sl
   914  }
   915  
   916  // Wrap this Descriptor, recursively
   917  func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) []*Descriptor {
   918  	sl = append(sl, newDescriptor(desc, parent, file, index))
   919  	me := sl[len(sl)-1]
   920  	for i, nested := range desc.NestedType {
   921  		sl = wrapThisDescriptor(sl, nested, me, file, i)
   922  	}
   923  	return sl
   924  }
   925  
   926  // Construct the EnumDescriptor
   927  func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *EnumDescriptor {
   928  	ed := &EnumDescriptor{
   929  		common:              common{file},
   930  		EnumDescriptorProto: desc,
   931  		parent:              parent,
   932  		index:               index,
   933  	}
   934  	if parent == nil {
   935  		ed.path = fmt.Sprintf("%d,%d", enumPath, index)
   936  	} else {
   937  		ed.path = fmt.Sprintf("%s,%d,%d", parent.path, messageEnumPath, index)
   938  	}
   939  	return ed
   940  }
   941  
   942  // Return a slice of all the EnumDescriptors defined within this file
   943  func wrapEnumDescriptors(file *FileDescriptor, descs []*Descriptor) []*EnumDescriptor {
   944  	sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
   945  	// Top-level enums.
   946  	for i, enum := range file.EnumType {
   947  		sl = append(sl, newEnumDescriptor(enum, nil, file, i))
   948  	}
   949  	// Enums within messages. Enums within embedded messages appear in the outer-most message.
   950  	for _, nested := range descs {
   951  		for i, enum := range nested.EnumType {
   952  			sl = append(sl, newEnumDescriptor(enum, nested, file, i))
   953  		}
   954  	}
   955  	return sl
   956  }
   957  
   958  // Return a slice of all the top-level ExtensionDescriptors defined within this file.
   959  func wrapExtensions(file *FileDescriptor) []*ExtensionDescriptor {
   960  	var sl []*ExtensionDescriptor
   961  	for _, field := range file.Extension {
   962  		sl = append(sl, &ExtensionDescriptor{common{file}, field, nil})
   963  	}
   964  	return sl
   965  }
   966  
   967  // Return a slice of all the types that are publicly imported into this file.
   968  func wrapImported(file *FileDescriptor, g *Generator) (sl []*ImportedDescriptor) {
   969  	for _, index := range file.PublicDependency {
   970  		df := g.fileByName(file.Dependency[index])
   971  		for _, d := range df.desc {
   972  			if d.GetOptions().GetMapEntry() {
   973  				continue
   974  			}
   975  			sl = append(sl, &ImportedDescriptor{common{file}, d})
   976  		}
   977  		for _, e := range df.enum {
   978  			sl = append(sl, &ImportedDescriptor{common{file}, e})
   979  		}
   980  		for _, ext := range df.ext {
   981  			sl = append(sl, &ImportedDescriptor{common{file}, ext})
   982  		}
   983  	}
   984  	return
   985  }
   986  
   987  func extractComments(file *FileDescriptor) {
   988  	file.comments = make(map[string]*descriptor.SourceCodeInfo_Location)
   989  	for _, loc := range file.GetSourceCodeInfo().GetLocation() {
   990  		if loc.LeadingComments == nil {
   991  			continue
   992  		}
   993  		var p []string
   994  		for _, n := range loc.Path {
   995  			p = append(p, strconv.Itoa(int(n)))
   996  		}
   997  		file.comments[strings.Join(p, ",")] = loc
   998  	}
   999  }
  1000  
  1001  // BuildTypeNameMap builds the map from fully qualified type names to objects.
  1002  // The key names for the map come from the input data, which puts a period at the beginning.
  1003  // It should be called after SetPackageNames and before GenerateAllFiles.
  1004  func (g *Generator) BuildTypeNameMap() {
  1005  	g.typeNameToObject = make(map[string]Object)
  1006  	for _, f := range g.allFiles {
  1007  		// The names in this loop are defined by the proto world, not us, so the
  1008  		// package name may be empty.  If so, the dotted package name of X will
  1009  		// be ".X"; otherwise it will be ".pkg.X".
  1010  		dottedPkg := "." + f.GetPackage()
  1011  		if dottedPkg != "." {
  1012  			dottedPkg += "."
  1013  		}
  1014  		for _, enum := range f.enum {
  1015  			name := dottedPkg + dottedSlice(enum.TypeName())
  1016  			g.typeNameToObject[name] = enum
  1017  		}
  1018  		for _, desc := range f.desc {
  1019  			name := dottedPkg + dottedSlice(desc.TypeName())
  1020  			g.typeNameToObject[name] = desc
  1021  		}
  1022  	}
  1023  }
  1024  
  1025  // ObjectNamed, given a fully-qualified input type name as it appears in the input data,
  1026  // returns the descriptor for the message or enum with that name.
  1027  func (g *Generator) ObjectNamed(typeName string) Object {
  1028  	o, ok := g.typeNameToObject[typeName]
  1029  	if !ok {
  1030  		g.Fail("can't find object with type", typeName)
  1031  	}
  1032  	return o
  1033  }
  1034  
  1035  // AnnotatedAtoms is a list of atoms (as consumed by P) that records the file name and proto AST path from which they originated.
  1036  type AnnotatedAtoms struct {
  1037  	source string
  1038  	path   string
  1039  	atoms  []interface{}
  1040  }
  1041  
  1042  // Annotate records the file name and proto AST path of a list of atoms
  1043  // so that a later call to P can emit a link from each atom to its origin.
  1044  func Annotate(file *FileDescriptor, path string, atoms ...interface{}) *AnnotatedAtoms {
  1045  	return &AnnotatedAtoms{source: *file.Name, path: path, atoms: atoms}
  1046  }
  1047  
  1048  // printAtom prints the (atomic, non-annotation) argument to the generated output.
  1049  func (g *Generator) printAtom(v interface{}) {
  1050  	switch v := v.(type) {
  1051  	case string:
  1052  		g.WriteString(v)
  1053  	case *string:
  1054  		g.WriteString(*v)
  1055  	case bool:
  1056  		fmt.Fprint(g, v)
  1057  	case *bool:
  1058  		fmt.Fprint(g, *v)
  1059  	case int:
  1060  		fmt.Fprint(g, v)
  1061  	case *int32:
  1062  		fmt.Fprint(g, *v)
  1063  	case *int64:
  1064  		fmt.Fprint(g, *v)
  1065  	case float64:
  1066  		fmt.Fprint(g, v)
  1067  	case *float64:
  1068  		fmt.Fprint(g, *v)
  1069  	case GoPackageName:
  1070  		g.WriteString(string(v))
  1071  	case GoImportPath:
  1072  		g.WriteString(strconv.Quote(string(v)))
  1073  	default:
  1074  		g.Fail(fmt.Sprintf("unknown type in printer: %T", v))
  1075  	}
  1076  }
  1077  
  1078  // P prints the arguments to the generated output.  It handles strings and int32s, plus
  1079  // handling indirections because they may be *string, etc.  Any inputs of type AnnotatedAtoms may emit
  1080  // annotations in a .meta file in addition to outputting the atoms themselves (if g.annotateCode
  1081  // is true).
  1082  func (g *Generator) P(str ...interface{}) {
  1083  	if !g.writeOutput {
  1084  		return
  1085  	}
  1086  	g.WriteString(g.indent)
  1087  	for _, v := range str {
  1088  		switch v := v.(type) {
  1089  		case *AnnotatedAtoms:
  1090  			begin := int32(g.Len())
  1091  			for _, v := range v.atoms {
  1092  				g.printAtom(v)
  1093  			}
  1094  			if g.annotateCode {
  1095  				end := int32(g.Len())
  1096  				var path []int32
  1097  				for _, token := range strings.Split(v.path, ",") {
  1098  					val, err := strconv.ParseInt(token, 10, 32)
  1099  					if err != nil {
  1100  						g.Fail("could not parse proto AST path: ", err.Error())
  1101  					}
  1102  					path = append(path, int32(val))
  1103  				}
  1104  				g.annotations = append(g.annotations, &descriptor.GeneratedCodeInfo_Annotation{
  1105  					Path:       path,
  1106  					SourceFile: &v.source,
  1107  					Begin:      &begin,
  1108  					End:        &end,
  1109  				})
  1110  			}
  1111  		default:
  1112  			g.printAtom(v)
  1113  		}
  1114  	}
  1115  	g.WriteByte('\n')
  1116  }
  1117  
  1118  // addInitf stores the given statement to be printed inside the file's init function.
  1119  // The statement is given as a format specifier and arguments.
  1120  func (g *Generator) addInitf(stmt string, a ...interface{}) {
  1121  	g.init = append(g.init, fmt.Sprintf(stmt, a...))
  1122  }
  1123  
  1124  func (g *Generator) PrintImport(alias GoPackageName, pkg GoImportPath) {
  1125  	statement := string(alias) + " " + strconv.Quote(string(pkg))
  1126  	if g.writtenImports[statement] {
  1127  		return
  1128  	}
  1129  	g.P(statement)
  1130  	g.writtenImports[statement] = true
  1131  }
  1132  
  1133  // In Indents the output one tab stop.
  1134  func (g *Generator) In() { g.indent += "\t" }
  1135  
  1136  // Out unindents the output one tab stop.
  1137  func (g *Generator) Out() {
  1138  	if len(g.indent) > 0 {
  1139  		g.indent = g.indent[1:]
  1140  	}
  1141  }
  1142  
  1143  // GenerateAllFiles generates the output for all the files we're outputting.
  1144  func (g *Generator) GenerateAllFiles() {
  1145  	// Initialize the plugins
  1146  	for _, p := range plugins {
  1147  		p.Init(g)
  1148  	}
  1149  	// Generate the output. The generator runs for every file, even the files
  1150  	// that we don't generate output for, so that we can collate the full list
  1151  	// of exported symbols to support public imports.
  1152  	genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles))
  1153  	for _, file := range g.genFiles {
  1154  		genFileMap[file] = true
  1155  	}
  1156  	for _, file := range g.allFiles {
  1157  		g.Reset()
  1158  		g.annotations = nil
  1159  		g.writeOutput = genFileMap[file]
  1160  		g.generate(file)
  1161  		if !g.writeOutput {
  1162  			continue
  1163  		}
  1164  		fname := file.goFileName(g.pathType)
  1165  		g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
  1166  			Name:    proto.String(fname),
  1167  			Content: proto.String(g.String()),
  1168  		})
  1169  		if g.annotateCode {
  1170  			// Store the generated code annotations in text, as the protoc plugin protocol requires that
  1171  			// strings contain valid UTF-8.
  1172  			g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
  1173  				Name:    proto.String(file.goFileName(g.pathType) + ".meta"),
  1174  				Content: proto.String(proto.CompactTextString(&descriptor.GeneratedCodeInfo{Annotation: g.annotations})),
  1175  			})
  1176  		}
  1177  	}
  1178  }
  1179  
  1180  // Run all the plugins associated with the file.
  1181  func (g *Generator) runPlugins(file *FileDescriptor) {
  1182  	for _, p := range plugins {
  1183  		p.Generate(file)
  1184  	}
  1185  }
  1186  
  1187  // Fill the response protocol buffer with the generated output for all the files we're
  1188  // supposed to generate.
  1189  func (g *Generator) generate(file *FileDescriptor) {
  1190  	g.customImports = make([]string, 0)
  1191  	g.file = file
  1192  	g.usedPackages = make(map[GoImportPath]bool)
  1193  	g.packageNames = make(map[GoImportPath]GoPackageName)
  1194  	g.usedPackageNames = make(map[GoPackageName]bool)
  1195  	g.addedImports = make(map[GoImportPath]bool)
  1196  	for name := range globalPackageNames {
  1197  		g.usedPackageNames[name] = true
  1198  	}
  1199  
  1200  	g.P("// This is a compile-time assertion to ensure that this generated file")
  1201  	g.P("// is compatible with the proto package it is being compiled against.")
  1202  	g.P("// A compilation error at this line likely means your copy of the")
  1203  	g.P("// proto package needs to be updated.")
  1204  	if gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
  1205  		g.P("const _ = ", g.Pkg["proto"], ".GoGoProtoPackageIsVersion", generatedCodeVersion, " // please upgrade the proto package")
  1206  	} else {
  1207  		g.P("const _ = ", g.Pkg["proto"], ".ProtoPackageIsVersion", generatedCodeVersion, " // please upgrade the proto package")
  1208  	}
  1209  	g.P()
  1210  	// Reset on each file
  1211  	g.writtenImports = make(map[string]bool)
  1212  	for _, td := range g.file.imp {
  1213  		g.generateImported(td)
  1214  	}
  1215  	for _, enum := range g.file.enum {
  1216  		g.generateEnum(enum)
  1217  	}
  1218  	for _, desc := range g.file.desc {
  1219  		// Don't generate virtual messages for maps.
  1220  		if desc.GetOptions().GetMapEntry() {
  1221  			continue
  1222  		}
  1223  		g.generateMessage(desc)
  1224  	}
  1225  	for _, ext := range g.file.ext {
  1226  		g.generateExtension(ext)
  1227  	}
  1228  	g.generateInitFunction()
  1229  	g.generateFileDescriptor(file)
  1230  
  1231  	// Run the plugins before the imports so we know which imports are necessary.
  1232  	g.runPlugins(file)
  1233  
  1234  	// Generate header and imports last, though they appear first in the output.
  1235  	rem := g.Buffer
  1236  	remAnno := g.annotations
  1237  	g.Buffer = new(bytes.Buffer)
  1238  	g.annotations = nil
  1239  	g.generateHeader()
  1240  	g.generateImports()
  1241  	if !g.writeOutput {
  1242  		return
  1243  	}
  1244  	// Adjust the offsets for annotations displaced by the header and imports.
  1245  	for _, anno := range remAnno {
  1246  		*anno.Begin += int32(g.Len())
  1247  		*anno.End += int32(g.Len())
  1248  		g.annotations = append(g.annotations, anno)
  1249  	}
  1250  	g.Write(rem.Bytes())
  1251  
  1252  	// Reformat generated code and patch annotation locations.
  1253  	fset := token.NewFileSet()
  1254  	original := g.Bytes()
  1255  	if g.annotateCode {
  1256  		// make a copy independent of g; we'll need it after Reset.
  1257  		original = append([]byte(nil), original...)
  1258  	}
  1259  	fileAST, err := parser.ParseFile(fset, "", original, parser.ParseComments)
  1260  	if err != nil {
  1261  		// Print out the bad code with line numbers.
  1262  		// This should never happen in practice, but it can while changing generated code,
  1263  		// so consider this a debugging aid.
  1264  		var src bytes.Buffer
  1265  		s := bufio.NewScanner(bytes.NewReader(original))
  1266  		for line := 1; s.Scan(); line++ {
  1267  			fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes())
  1268  		}
  1269  		if serr := s.Err(); serr != nil {
  1270  			g.Fail("bad Go source code was generated:", err.Error(), "\n"+string(original))
  1271  		} else {
  1272  			g.Fail("bad Go source code was generated:", err.Error(), "\n"+src.String())
  1273  		}
  1274  	}
  1275  	ast.SortImports(fset, fileAST)
  1276  	g.Reset()
  1277  	err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, fileAST)
  1278  	if err != nil {
  1279  		g.Fail("generated Go source code could not be reformatted:", err.Error())
  1280  	}
  1281  	if g.annotateCode {
  1282  		m, err := remap.Compute(original, g.Bytes())
  1283  		if err != nil {
  1284  			g.Fail("formatted generated Go source code could not be mapped back to the original code:", err.Error())
  1285  		}
  1286  		for _, anno := range g.annotations {
  1287  			new, ok := m.Find(int(*anno.Begin), int(*anno.End))
  1288  			if !ok {
  1289  				g.Fail("span in formatted generated Go source code could not be mapped back to the original code")
  1290  			}
  1291  			*anno.Begin = int32(new.Pos)
  1292  			*anno.End = int32(new.End)
  1293  		}
  1294  	}
  1295  }
  1296  
  1297  // Generate the header, including package definition
  1298  func (g *Generator) generateHeader() {
  1299  	g.P("// Code generated by protoc-gen-gogo. DO NOT EDIT.")
  1300  	if g.file.GetOptions().GetDeprecated() {
  1301  		g.P("// ", *g.file.Name, " is a deprecated file.")
  1302  	} else {
  1303  		g.P("// source: ", *g.file.Name)
  1304  	}
  1305  	g.P()
  1306  	g.PrintComments(strconv.Itoa(packagePath))
  1307  	g.P()
  1308  	g.P("package ", g.file.packageName)
  1309  	g.P()
  1310  }
  1311  
  1312  // deprecationComment is the standard comment added to deprecated
  1313  // messages, fields, enums, and enum values.
  1314  var deprecationComment = "// Deprecated: Do not use."
  1315  
  1316  // PrintComments prints any comments from the source .proto file.
  1317  // The path is a comma-separated list of integers.
  1318  // It returns an indication of whether any comments were printed.
  1319  // See descriptor.proto for its format.
  1320  func (g *Generator) PrintComments(path string) bool {
  1321  	if !g.writeOutput {
  1322  		return false
  1323  	}
  1324  	if c, ok := g.makeComments(path); ok {
  1325  		g.P(c)
  1326  		return true
  1327  	}
  1328  	return false
  1329  }
  1330  
  1331  // makeComments generates the comment string for the field, no "\n" at the end
  1332  func (g *Generator) makeComments(path string) (string, bool) {
  1333  	loc, ok := g.file.comments[path]
  1334  	if !ok {
  1335  		return "", false
  1336  	}
  1337  	w := new(bytes.Buffer)
  1338  	nl := ""
  1339  	for _, line := range strings.Split(strings.TrimSuffix(loc.GetLeadingComments(), "\n"), "\n") {
  1340  		fmt.Fprintf(w, "%s//%s", nl, line)
  1341  		nl = "\n"
  1342  	}
  1343  	return w.String(), true
  1344  }
  1345  
  1346  // Comments returns any comments from the source .proto file and empty string if comments not found.
  1347  // The path is a comma-separated list of intergers.
  1348  // See descriptor.proto for its format.
  1349  func (g *Generator) Comments(path string) string {
  1350  	loc, ok := g.file.comments[path]
  1351  	if !ok {
  1352  		return ""
  1353  	}
  1354  	text := strings.TrimSuffix(loc.GetLeadingComments(), "\n")
  1355  	return text
  1356  }
  1357  
  1358  func (g *Generator) fileByName(filename string) *FileDescriptor {
  1359  	return g.allFilesByName[filename]
  1360  }
  1361  
  1362  // weak returns whether the ith import of the current file is a weak import.
  1363  func (g *Generator) weak(i int32) bool {
  1364  	for _, j := range g.file.WeakDependency {
  1365  		if j == i {
  1366  			return true
  1367  		}
  1368  	}
  1369  	return false
  1370  }
  1371  
  1372  // Generate the imports
  1373  func (g *Generator) generateImports() {
  1374  	imports := make(map[GoImportPath]GoPackageName)
  1375  	for i, s := range g.file.Dependency {
  1376  		fd := g.fileByName(s)
  1377  		importPath := fd.importPath
  1378  		// Do not import our own package.
  1379  		if importPath == g.file.importPath {
  1380  			continue
  1381  		}
  1382  		// Do not import weak imports.
  1383  		if g.weak(int32(i)) {
  1384  			continue
  1385  		}
  1386  		// Do not import a package twice.
  1387  		if _, ok := imports[importPath]; ok {
  1388  			continue
  1389  		}
  1390  		// We need to import all the dependencies, even if we don't reference them,
  1391  		// because other code and tools depend on having the full transitive closure
  1392  		// of protocol buffer types in the binary.
  1393  		packageName := g.GoPackageName(importPath)
  1394  		if _, ok := g.usedPackages[importPath]; !ok {
  1395  			packageName = "_"
  1396  		}
  1397  		imports[importPath] = packageName
  1398  	}
  1399  	for importPath := range g.addedImports {
  1400  		imports[importPath] = g.GoPackageName(importPath)
  1401  	}
  1402  	// We almost always need a proto import.  Rather than computing when we
  1403  	// do, which is tricky when there's a plugin, just import it and
  1404  	// reference it later. The same argument applies to the fmt and math packages.
  1405  	g.P("import (")
  1406  	g.PrintImport(GoPackageName(g.Pkg["fmt"]), "fmt")
  1407  	g.PrintImport(GoPackageName(g.Pkg["math"]), "math")
  1408  	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) {
  1409  		g.PrintImport(GoPackageName(g.Pkg["proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/gogo/protobuf/proto"))
  1410  		if gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
  1411  			g.PrintImport(GoPackageName(g.Pkg["golang_proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/golang/protobuf/proto"))
  1412  		}
  1413  	} else {
  1414  		g.PrintImport(GoPackageName(g.Pkg["proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/golang/protobuf/proto"))
  1415  	}
  1416  	for importPath, packageName := range imports {
  1417  		g.P(packageName, " ", GoImportPath(g.ImportPrefix)+importPath)
  1418  	}
  1419  	// Custom gogo imports
  1420  	for _, s := range g.customImports {
  1421  		s1 := strings.Map(badToUnderscore, s)
  1422  		g.PrintImport(GoPackageName(s1), GoImportPath(s))
  1423  	}
  1424  	// gogo plugin imports
  1425  	// TODO: may need to worry about uniqueness across plugins and could change this
  1426  	// to use the `addedImports` technique
  1427  	for _, p := range plugins {
  1428  		p.GenerateImports(g.file)
  1429  	}
  1430  	g.P(")")
  1431  
  1432  	g.P("// Reference imports to suppress errors if they are not otherwise used.")
  1433  	g.P("var _ = ", g.Pkg["proto"], ".Marshal")
  1434  	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
  1435  		g.P("var _ = ", g.Pkg["golang_proto"], ".Marshal")
  1436  	}
  1437  	g.P("var _ = ", g.Pkg["fmt"], ".Errorf")
  1438  	g.P("var _ = ", g.Pkg["math"], ".Inf")
  1439  	for _, cimport := range g.customImports {
  1440  		if cimport == "time" {
  1441  			g.P("var _ = time.Kitchen")
  1442  			break
  1443  		}
  1444  	}
  1445  	g.P()
  1446  }
  1447  
  1448  func (g *Generator) generateImported(id *ImportedDescriptor) {
  1449  	df := id.o.File()
  1450  	filename := *df.Name
  1451  	if df.importPath == g.file.importPath {
  1452  		// Don't generate type aliases for files in the same Go package as this one.
  1453  		return
  1454  	}
  1455  	if !supportTypeAliases {
  1456  		g.Fail(fmt.Sprintf("%s: public imports require at least go1.9", filename))
  1457  	}
  1458  	g.usedPackages[df.importPath] = true
  1459  
  1460  	for _, sym := range df.exported[id.o] {
  1461  		sym.GenerateAlias(g, filename, g.GoPackageName(df.importPath))
  1462  	}
  1463  	g.P()
  1464  }
  1465  
  1466  // Generate the enum definitions for this EnumDescriptor.
  1467  func (g *Generator) generateEnum(enum *EnumDescriptor) {
  1468  	// The full type name
  1469  	typeName := enum.alias()
  1470  	// The full type name, CamelCased.
  1471  	ccTypeName := CamelCaseSlice(typeName)
  1472  	ccPrefix := enum.prefix()
  1473  
  1474  	deprecatedEnum := ""
  1475  	if enum.GetOptions().GetDeprecated() {
  1476  		deprecatedEnum = deprecationComment
  1477  	}
  1478  
  1479  	g.PrintComments(enum.path)
  1480  	if !gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
  1481  		ccPrefix = ""
  1482  	}
  1483  
  1484  	if gogoproto.HasEnumDecl(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
  1485  		g.P("type ", Annotate(enum.file, enum.path, ccTypeName), " int32", deprecatedEnum)
  1486  		g.file.addExport(enum, enumSymbol{ccTypeName, enum.proto3()})
  1487  		g.P("const (")
  1488  		g.In()
  1489  		for i, e := range enum.Value {
  1490  			etorPath := fmt.Sprintf("%s,%d,%d", enum.path, enumValuePath, i)
  1491  			g.PrintComments(etorPath)
  1492  
  1493  			deprecatedValue := ""
  1494  			if e.GetOptions().GetDeprecated() {
  1495  				deprecatedValue = deprecationComment
  1496  			}
  1497  			name := *e.Name
  1498  			if gogoproto.IsEnumValueCustomName(e) {
  1499  				name = gogoproto.GetEnumValueCustomName(e)
  1500  			}
  1501  			name = ccPrefix + name
  1502  
  1503  			g.P(Annotate(enum.file, etorPath, name), " ", ccTypeName, " = ", e.Number, " ", deprecatedValue)
  1504  			g.file.addExport(enum, constOrVarSymbol{name, "const", ccTypeName})
  1505  		}
  1506  		g.Out()
  1507  		g.P(")")
  1508  	}
  1509  	g.P()
  1510  	g.P("var ", ccTypeName, "_name = map[int32]string{")
  1511  	g.In()
  1512  	generated := make(map[int32]bool) // avoid duplicate values
  1513  	for _, e := range enum.Value {
  1514  		duplicate := ""
  1515  		if _, present := generated[*e.Number]; present {
  1516  			duplicate = "// Duplicate value: "
  1517  		}
  1518  		g.P(duplicate, e.Number, ": ", strconv.Quote(*e.Name), ",")
  1519  		generated[*e.Number] = true
  1520  	}
  1521  	g.Out()
  1522  	g.P("}")
  1523  	g.P()
  1524  	g.P("var ", ccTypeName, "_value = map[string]int32{")
  1525  	g.In()
  1526  	for _, e := range enum.Value {
  1527  		g.P(strconv.Quote(*e.Name), ": ", e.Number, ",")
  1528  	}
  1529  	g.Out()
  1530  	g.P("}")
  1531  	g.P()
  1532  
  1533  	if !enum.proto3() {
  1534  		g.P("func (x ", ccTypeName, ") Enum() *", ccTypeName, " {")
  1535  		g.In()
  1536  		g.P("p := new(", ccTypeName, ")")
  1537  		g.P("*p = x")
  1538  		g.P("return p")
  1539  		g.Out()
  1540  		g.P("}")
  1541  		g.P()
  1542  	}
  1543  
  1544  	if gogoproto.IsGoEnumStringer(g.file.FileDescriptorProto, enum.EnumDescriptorProto) {
  1545  		g.P("func (x ", ccTypeName, ") String() string {")
  1546  		g.In()
  1547  		g.P("return ", g.Pkg["proto"], ".EnumName(", ccTypeName, "_name, int32(x))")
  1548  		g.Out()
  1549  		g.P("}")
  1550  		g.P()
  1551  	}
  1552  
  1553  	if !enum.proto3() && !gogoproto.IsGoEnumStringer(g.file.FileDescriptorProto, enum.EnumDescriptorProto) {
  1554  		g.P("func (x ", ccTypeName, ") MarshalJSON() ([]byte, error) {")
  1555  		g.In()
  1556  		g.P("return ", g.Pkg["proto"], ".MarshalJSONEnum(", ccTypeName, "_name, int32(x))")
  1557  		g.Out()
  1558  		g.P("}")
  1559  		g.P()
  1560  	}
  1561  	if !enum.proto3() {
  1562  		g.P("func (x *", ccTypeName, ") UnmarshalJSON(data []byte) error {")
  1563  		g.In()
  1564  		g.P("value, err := ", g.Pkg["proto"], ".UnmarshalJSONEnum(", ccTypeName, `_value, data, "`, ccTypeName, `")`)
  1565  		g.P("if err != nil {")
  1566  		g.In()
  1567  		g.P("return err")
  1568  		g.Out()
  1569  		g.P("}")
  1570  		g.P("*x = ", ccTypeName, "(value)")
  1571  		g.P("return nil")
  1572  		g.Out()
  1573  		g.P("}")
  1574  		g.P()
  1575  	}
  1576  
  1577  	var indexes []string
  1578  	for m := enum.parent; m != nil; m = m.parent {
  1579  		// XXX: skip groups?
  1580  		indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
  1581  	}
  1582  	indexes = append(indexes, strconv.Itoa(enum.index))
  1583  	g.P("func (", ccTypeName, ") EnumDescriptor() ([]byte, []int) {")
  1584  	g.In()
  1585  	g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}")
  1586  	g.Out()
  1587  	g.P("}")
  1588  	g.P()
  1589  	if enum.file.GetPackage() == "google.protobuf" && enum.GetName() == "NullValue" {
  1590  		g.P("func (", ccTypeName, `) XXX_WellKnownType() string { return "`, enum.GetName(), `" }`)
  1591  		g.P()
  1592  	}
  1593  
  1594  	g.generateEnumRegistration(enum)
  1595  }
  1596  
  1597  // The tag is a string like "varint,2,opt,name=fieldname,def=7" that
  1598  // identifies details of the field for the protocol buffer marshaling and unmarshaling
  1599  // code.  The fields are:
  1600  //	wire encoding
  1601  //	protocol tag number
  1602  //	opt,req,rep for optional, required, or repeated
  1603  //	packed whether the encoding is "packed" (optional; repeated primitives only)
  1604  //	name= the original declared name
  1605  //	enum= the name of the enum type if it is an enum-typed field.
  1606  //	proto3 if this field is in a proto3 message
  1607  //	def= string representation of the default value, if any.
  1608  // The default value must be in a representation that can be used at run-time
  1609  // to generate the default value. Thus bools become 0 and 1, for instance.
  1610  func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptorProto, wiretype string) string {
  1611  	optrepreq := ""
  1612  	switch {
  1613  	case isOptional(field):
  1614  		optrepreq = "opt"
  1615  	case isRequired(field):
  1616  		optrepreq = "req"
  1617  	case isRepeated(field):
  1618  		optrepreq = "rep"
  1619  	}
  1620  	var defaultValue string
  1621  	if dv := field.DefaultValue; dv != nil { // set means an explicit default
  1622  		defaultValue = *dv
  1623  		// Some types need tweaking.
  1624  		switch *field.Type {
  1625  		case descriptor.FieldDescriptorProto_TYPE_BOOL:
  1626  			if defaultValue == "true" {
  1627  				defaultValue = "1"
  1628  			} else {
  1629  				defaultValue = "0"
  1630  			}
  1631  		case descriptor.FieldDescriptorProto_TYPE_STRING,
  1632  			descriptor.FieldDescriptorProto_TYPE_BYTES:
  1633  			// Nothing to do. Quoting is done for the whole tag.
  1634  		case descriptor.FieldDescriptorProto_TYPE_ENUM:
  1635  			// For enums we need to provide the integer constant.
  1636  			obj := g.ObjectNamed(field.GetTypeName())
  1637  			if id, ok := obj.(*ImportedDescriptor); ok {
  1638  				// It is an enum that was publicly imported.
  1639  				// We need the underlying type.
  1640  				obj = id.o
  1641  			}
  1642  			enum, ok := obj.(*EnumDescriptor)
  1643  			if !ok {
  1644  				log.Printf("obj is a %T", obj)
  1645  				if id, ok := obj.(*ImportedDescriptor); ok {
  1646  					log.Printf("id.o is a %T", id.o)
  1647  				}
  1648  				g.Fail("unknown enum type", CamelCaseSlice(obj.TypeName()))
  1649  			}
  1650  			defaultValue = enum.integerValueAsString(defaultValue)
  1651  		case descriptor.FieldDescriptorProto_TYPE_FLOAT:
  1652  			if def := defaultValue; def != "inf" && def != "-inf" && def != "nan" {
  1653  				if f, err := strconv.ParseFloat(defaultValue, 32); err == nil {
  1654  					defaultValue = fmt.Sprint(float32(f))
  1655  				}
  1656  			}
  1657  		case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
  1658  			if def := defaultValue; def != "inf" && def != "-inf" && def != "nan" {
  1659  				if f, err := strconv.ParseFloat(defaultValue, 64); err == nil {
  1660  					defaultValue = fmt.Sprint(f)
  1661  				}
  1662  			}
  1663  		}
  1664  		defaultValue = ",def=" + defaultValue
  1665  	}
  1666  	enum := ""
  1667  	if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
  1668  		// We avoid using obj.goPackageNamehe
  1669  		// original (proto-world) package name.
  1670  		obj := g.ObjectNamed(field.GetTypeName())
  1671  		if id, ok := obj.(*ImportedDescriptor); ok {
  1672  			obj = id.o
  1673  		}
  1674  		enum = ",enum="
  1675  		if pkg := obj.File().GetPackage(); pkg != "" {
  1676  			enum += pkg + "."
  1677  		}
  1678  		enum += CamelCaseSlice(obj.TypeName())
  1679  	}
  1680  	packed := ""
  1681  	if (field.Options != nil && field.Options.GetPacked()) ||
  1682  		// Per https://developers.google.com/protocol-buffers/docs/proto3#simple:
  1683  		// "In proto3, repeated fields of scalar numeric types use packed encoding by default."
  1684  		(message.proto3() && (field.Options == nil || field.Options.Packed == nil) &&
  1685  			isRepeated(field) && IsScalar(field)) {
  1686  		packed = ",packed"
  1687  	}
  1688  	fieldName := field.GetName()
  1689  	name := fieldName
  1690  	if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
  1691  		// We must use the type name for groups instead of
  1692  		// the field name to preserve capitalization.
  1693  		// type_name in FieldDescriptorProto is fully-qualified,
  1694  		// but we only want the local part.
  1695  		name = *field.TypeName
  1696  		if i := strings.LastIndex(name, "."); i >= 0 {
  1697  			name = name[i+1:]
  1698  		}
  1699  	}
  1700  	if json := field.GetJsonName(); field.Extendee == nil && json != "" && json != name {
  1701  		// TODO: escaping might be needed, in which case
  1702  		// perhaps this should be in its own "json" tag.
  1703  		name += ",json=" + json
  1704  	}
  1705  	name = ",name=" + name
  1706  
  1707  	embed := ""
  1708  	if gogoproto.IsEmbed(field) {
  1709  		embed = ",embedded=" + fieldName
  1710  	}
  1711  
  1712  	ctype := ""
  1713  	if gogoproto.IsCustomType(field) {
  1714  		ctype = ",customtype=" + gogoproto.GetCustomType(field)
  1715  	}
  1716  
  1717  	casttype := ""
  1718  	if gogoproto.IsCastType(field) {
  1719  		casttype = ",casttype=" + gogoproto.GetCastType(field)
  1720  	}
  1721  
  1722  	castkey := ""
  1723  	if gogoproto.IsCastKey(field) {
  1724  		castkey = ",castkey=" + gogoproto.GetCastKey(field)
  1725  	}
  1726  
  1727  	castvalue := ""
  1728  	if gogoproto.IsCastValue(field) {
  1729  		castvalue = ",castvalue=" + gogoproto.GetCastValue(field)
  1730  		// record the original message type for jsonpb reconstruction
  1731  		desc := g.ObjectNamed(field.GetTypeName())
  1732  		if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() {
  1733  			valueField := d.Field[1]
  1734  			if valueField.IsMessage() {
  1735  				castvalue += ",castvaluetype=" + strings.TrimPrefix(valueField.GetTypeName(), ".")
  1736  			}
  1737  		}
  1738  	}
  1739  
  1740  	if message.proto3() {
  1741  		name += ",proto3"
  1742  	}
  1743  	oneof := ""
  1744  	if field.OneofIndex != nil {
  1745  		oneof = ",oneof"
  1746  	}
  1747  	stdtime := ""
  1748  	if gogoproto.IsStdTime(field) {
  1749  		stdtime = ",stdtime"
  1750  	}
  1751  	stdduration := ""
  1752  	if gogoproto.IsStdDuration(field) {
  1753  		stdduration = ",stdduration"
  1754  	}
  1755  	wktptr := ""
  1756  	if gogoproto.IsWktPtr(field) {
  1757  		wktptr = ",wktptr"
  1758  	}
  1759  	return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  1760  		wiretype,
  1761  		field.GetNumber(),
  1762  		optrepreq,
  1763  		packed,
  1764  		name,
  1765  		enum,
  1766  		oneof,
  1767  		defaultValue,
  1768  		embed,
  1769  		ctype,
  1770  		casttype,
  1771  		castkey,
  1772  		castvalue,
  1773  		stdtime,
  1774  		stdduration,
  1775  		wktptr))
  1776  }
  1777  
  1778  func needsStar(field *descriptor.FieldDescriptorProto, proto3 bool, allowOneOf bool) bool {
  1779  	if isRepeated(field) &&
  1780  		(*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE || gogoproto.IsCustomType(field)) &&
  1781  		(*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) {
  1782  		return false
  1783  	}
  1784  	if *field.Type == descriptor.FieldDescriptorProto_TYPE_BYTES && !gogoproto.IsCustomType(field) {
  1785  		return false
  1786  	}
  1787  	if !gogoproto.IsNullable(field) {
  1788  		return false
  1789  	}
  1790  	if field.OneofIndex != nil && allowOneOf &&
  1791  		(*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
  1792  		(*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) {
  1793  		return false
  1794  	}
  1795  	if proto3 &&
  1796  		(*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
  1797  		(*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) &&
  1798  		!gogoproto.IsCustomType(field) {
  1799  		return false
  1800  	}
  1801  	return true
  1802  }
  1803  
  1804  // TypeName is the printed name appropriate for an item. If the object is in the current file,
  1805  // TypeName drops the package name and underscores the rest.
  1806  // Otherwise the object is from another package; and the result is the underscored
  1807  // package name followed by the item name.
  1808  // The result always has an initial capital.
  1809  func (g *Generator) TypeName(obj Object) string {
  1810  	return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName())
  1811  }
  1812  
  1813  // GoType returns a string representing the type name, and the wire type
  1814  func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
  1815  	// TODO: Options.
  1816  	switch *field.Type {
  1817  	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
  1818  		typ, wire = "float64", "fixed64"
  1819  	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
  1820  		typ, wire = "float32", "fixed32"
  1821  	case descriptor.FieldDescriptorProto_TYPE_INT64:
  1822  		typ, wire = "int64", "varint"
  1823  	case descriptor.FieldDescriptorProto_TYPE_UINT64:
  1824  		typ, wire = "uint64", "varint"
  1825  	case descriptor.FieldDescriptorProto_TYPE_INT32:
  1826  		typ, wire = "int32", "varint"
  1827  	case descriptor.FieldDescriptorProto_TYPE_UINT32:
  1828  		typ, wire = "uint32", "varint"
  1829  	case descriptor.FieldDescriptorProto_TYPE_FIXED64:
  1830  		typ, wire = "uint64", "fixed64"
  1831  	case descriptor.FieldDescriptorProto_TYPE_FIXED32:
  1832  		typ, wire = "uint32", "fixed32"
  1833  	case descriptor.FieldDescriptorProto_TYPE_BOOL:
  1834  		typ, wire = "bool", "varint"
  1835  	case descriptor.FieldDescriptorProto_TYPE_STRING:
  1836  		typ, wire = "string", "bytes"
  1837  	case descriptor.FieldDescriptorProto_TYPE_GROUP:
  1838  		desc := g.ObjectNamed(field.GetTypeName())
  1839  		typ, wire = g.TypeName(desc), "group"
  1840  	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
  1841  		desc := g.ObjectNamed(field.GetTypeName())
  1842  		typ, wire = g.TypeName(desc), "bytes"
  1843  	case descriptor.FieldDescriptorProto_TYPE_BYTES:
  1844  		typ, wire = "[]byte", "bytes"
  1845  	case descriptor.FieldDescriptorProto_TYPE_ENUM:
  1846  		desc := g.ObjectNamed(field.GetTypeName())
  1847  		typ, wire = g.TypeName(desc), "varint"
  1848  	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
  1849  		typ, wire = "int32", "fixed32"
  1850  	case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
  1851  		typ, wire = "int64", "fixed64"
  1852  	case descriptor.FieldDescriptorProto_TYPE_SINT32:
  1853  		typ, wire = "int32", "zigzag32"
  1854  	case descriptor.FieldDescriptorProto_TYPE_SINT64:
  1855  		typ, wire = "int64", "zigzag64"
  1856  	default:
  1857  		g.Fail("unknown type for", field.GetName())
  1858  	}
  1859  	switch {
  1860  	case gogoproto.IsCustomType(field) && gogoproto.IsCastType(field):
  1861  		g.Fail(field.GetName() + " cannot be custom type and cast type")
  1862  	case gogoproto.IsCustomType(field):
  1863  		var packageName string
  1864  		var err error
  1865  		packageName, typ, err = getCustomType(field)
  1866  		if err != nil {
  1867  			g.Fail(err.Error())
  1868  		}
  1869  		if len(packageName) > 0 {
  1870  			g.customImports = append(g.customImports, packageName)
  1871  		}
  1872  	case gogoproto.IsCastType(field):
  1873  		var packageName string
  1874  		var err error
  1875  		packageName, typ, err = getCastType(field)
  1876  		if err != nil {
  1877  			g.Fail(err.Error())
  1878  		}
  1879  		if len(packageName) > 0 {
  1880  			g.customImports = append(g.customImports, packageName)
  1881  		}
  1882  	case gogoproto.IsStdTime(field):
  1883  		g.customImports = append(g.customImports, "time")
  1884  		typ = "time.Time"
  1885  	case gogoproto.IsStdDuration(field):
  1886  		g.customImports = append(g.customImports, "time")
  1887  		typ = "time.Duration"
  1888  	case gogoproto.IsStdDouble(field):
  1889  		typ = "float64"
  1890  	case gogoproto.IsStdFloat(field):
  1891  		typ = "float32"
  1892  	case gogoproto.IsStdInt64(field):
  1893  		typ = "int64"
  1894  	case gogoproto.IsStdUInt64(field):
  1895  		typ = "uint64"
  1896  	case gogoproto.IsStdInt32(field):
  1897  		typ = "int32"
  1898  	case gogoproto.IsStdUInt32(field):
  1899  		typ = "uint32"
  1900  	case gogoproto.IsStdBool(field):
  1901  		typ = "bool"
  1902  	case gogoproto.IsStdString(field):
  1903  		typ = "string"
  1904  	case gogoproto.IsStdBytes(field):
  1905  		typ = "[]byte"
  1906  	}
  1907  	if needsStar(field, g.file.proto3 && field.Extendee == nil, message != nil && message.allowOneof()) {
  1908  		typ = "*" + typ
  1909  	}
  1910  	if isRepeated(field) {
  1911  		typ = "[]" + typ
  1912  	}
  1913  	return
  1914  }
  1915  
  1916  // GoMapDescriptor is a full description of the map output struct.
  1917  type GoMapDescriptor struct {
  1918  	GoType string
  1919  
  1920  	KeyField      *descriptor.FieldDescriptorProto
  1921  	KeyAliasField *descriptor.FieldDescriptorProto
  1922  	KeyTag        string
  1923  
  1924  	ValueField      *descriptor.FieldDescriptorProto
  1925  	ValueAliasField *descriptor.FieldDescriptorProto
  1926  	ValueTag        string
  1927  }
  1928  
  1929  func (g *Generator) GoMapType(d *Descriptor, field *descriptor.FieldDescriptorProto) *GoMapDescriptor {
  1930  	if d == nil {
  1931  		byName := g.ObjectNamed(field.GetTypeName())
  1932  		desc, ok := byName.(*Descriptor)
  1933  		if byName == nil || !ok || !desc.GetOptions().GetMapEntry() {
  1934  			g.Fail(fmt.Sprintf("field %s is not a map", field.GetTypeName()))
  1935  			return nil
  1936  		}
  1937  		d = desc
  1938  	}
  1939  
  1940  	m := &GoMapDescriptor{
  1941  		KeyField:   d.Field[0],
  1942  		ValueField: d.Field[1],
  1943  	}
  1944  
  1945  	// Figure out the Go types and tags for the key and value types.
  1946  	m.KeyAliasField, m.ValueAliasField = g.GetMapKeyField(field, m.KeyField), g.GetMapValueField(field, m.ValueField)
  1947  	keyType, keyWire := g.GoType(d, m.KeyAliasField)
  1948  	valType, valWire := g.GoType(d, m.ValueAliasField)
  1949  
  1950  	m.KeyTag, m.ValueTag = g.goTag(d, m.KeyField, keyWire), g.goTag(d, m.ValueField, valWire)
  1951  
  1952  	if gogoproto.IsCastType(field) {
  1953  		var packageName string
  1954  		var err error
  1955  		packageName, typ, err := getCastType(field)
  1956  		if err != nil {
  1957  			g.Fail(err.Error())
  1958  		}
  1959  		if len(packageName) > 0 {
  1960  			g.customImports = append(g.customImports, packageName)
  1961  		}
  1962  		m.GoType = typ
  1963  		return m
  1964  	}
  1965  
  1966  	// We don't use stars, except for message-typed values.
  1967  	// Message and enum types are the only two possibly foreign types used in maps,
  1968  	// so record their use. They are not permitted as map keys.
  1969  	keyType = strings.TrimPrefix(keyType, "*")
  1970  	switch *m.ValueAliasField.Type {
  1971  	case descriptor.FieldDescriptorProto_TYPE_ENUM:
  1972  		valType = strings.TrimPrefix(valType, "*")
  1973  		g.RecordTypeUse(m.ValueAliasField.GetTypeName())
  1974  	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
  1975  		if !gogoproto.IsNullable(m.ValueAliasField) {
  1976  			valType = strings.TrimPrefix(valType, "*")
  1977  		}
  1978  		if !gogoproto.IsStdType(m.ValueAliasField) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
  1979  			g.RecordTypeUse(m.ValueAliasField.GetTypeName())
  1980  		}
  1981  	default:
  1982  		if gogoproto.IsCustomType(m.ValueAliasField) {
  1983  			if !gogoproto.IsNullable(m.ValueAliasField) {
  1984  				valType = strings.TrimPrefix(valType, "*")
  1985  			}
  1986  			if !gogoproto.IsStdType(field) {
  1987  				g.RecordTypeUse(m.ValueAliasField.GetTypeName())
  1988  			}
  1989  		} else {
  1990  			valType = strings.TrimPrefix(valType, "*")
  1991  		}
  1992  	}
  1993  
  1994  	m.GoType = fmt.Sprintf("map[%s]%s", keyType, valType)
  1995  	return m
  1996  }
  1997  
  1998  func (g *Generator) RecordTypeUse(t string) {
  1999  	if _, ok := g.typeNameToObject[t]; !ok {
  2000  		return
  2001  	}
  2002  	importPath := g.ObjectNamed(t).GoImportPath()
  2003  	if importPath == g.outputImportPath {
  2004  		// Don't record use of objects in our package.
  2005  		return
  2006  	}
  2007  	g.AddImport(importPath)
  2008  	g.usedPackages[importPath] = true
  2009  }
  2010  
  2011  // Method names that may be generated.  Fields with these names get an
  2012  // underscore appended. Any change to this set is a potential incompatible
  2013  // API change because it changes generated field names.
  2014  var methodNames = [...]string{
  2015  	"Reset",
  2016  	"String",
  2017  	"ProtoMessage",
  2018  	"Marshal",
  2019  	"Unmarshal",
  2020  	"ExtensionRangeArray",
  2021  	"ExtensionMap",
  2022  	"Descriptor",
  2023  	"MarshalTo",
  2024  	"Equal",
  2025  	"VerboseEqual",
  2026  	"GoString",
  2027  	"ProtoSize",
  2028  }
  2029  
  2030  // Names of messages in the `google.protobuf` package for which
  2031  // we will generate XXX_WellKnownType methods.
  2032  var wellKnownTypes = map[string]bool{
  2033  	"Any":       true,
  2034  	"Duration":  true,
  2035  	"Empty":     true,
  2036  	"Struct":    true,
  2037  	"Timestamp": true,
  2038  
  2039  	"Value":       true,
  2040  	"ListValue":   true,
  2041  	"DoubleValue": true,
  2042  	"FloatValue":  true,
  2043  	"Int64Value":  true,
  2044  	"UInt64Value": true,
  2045  	"Int32Value":  true,
  2046  	"UInt32Value": true,
  2047  	"BoolValue":   true,
  2048  	"StringValue": true,
  2049  	"BytesValue":  true,
  2050  }
  2051  
  2052  // getterDefault finds the default value for the field to return from a getter,
  2053  // regardless of if it's a built in default or explicit from the source. Returns e.g. "nil", `""`, "Default_MessageType_FieldName"
  2054  func (g *Generator) getterDefault(field *descriptor.FieldDescriptorProto, goMessageType, goTypeName string) string {
  2055  	if isRepeated(field) {
  2056  		return "nil"
  2057  	}
  2058  	if def := field.GetDefaultValue(); def != "" {
  2059  		defaultConstant := g.defaultConstantName(goMessageType, field.GetName())
  2060  		if *field.Type != descriptor.FieldDescriptorProto_TYPE_BYTES {
  2061  			return defaultConstant
  2062  		}
  2063  		return "append([]byte(nil), " + defaultConstant + "...)"
  2064  	}
  2065  	switch *field.Type {
  2066  	case descriptor.FieldDescriptorProto_TYPE_GROUP,
  2067  		descriptor.FieldDescriptorProto_TYPE_MESSAGE:
  2068  		if field.OneofIndex != nil {
  2069  			return "nil"
  2070  		} else {
  2071  			if !gogoproto.IsNullable(field) && (gogoproto.IsStdDuration(field) ||
  2072  				gogoproto.IsStdDouble(field) || gogoproto.IsStdFloat(field) ||
  2073  				gogoproto.IsStdInt64(field) || gogoproto.IsStdUInt64(field) ||
  2074  				gogoproto.IsStdInt32(field) || gogoproto.IsStdUInt32(field)) {
  2075  				return "0"
  2076  			} else if !gogoproto.IsNullable(field) && gogoproto.IsStdBool(field) {
  2077  				return "false"
  2078  			} else if !gogoproto.IsNullable(field) && gogoproto.IsStdString(field) {
  2079  				return "\"\""
  2080  			} else if !gogoproto.IsNullable(field) && gogoproto.IsStdBytes(field) {
  2081  				return "[]byte{}"
  2082  			} else {
  2083  				return goTypeName + "{}"
  2084  			}
  2085  		}
  2086  	case descriptor.FieldDescriptorProto_TYPE_BOOL:
  2087  		return "false"
  2088  	case descriptor.FieldDescriptorProto_TYPE_STRING:
  2089  		return "\"\""
  2090  	case descriptor.FieldDescriptorProto_TYPE_BYTES:
  2091  		// This is only possible for oneof fields.
  2092  		return "nil"
  2093  	case descriptor.FieldDescriptorProto_TYPE_ENUM:
  2094  		// The default default for an enum is the first value in the enum,
  2095  		// not zero.
  2096  		obj := g.ObjectNamed(field.GetTypeName())
  2097  		var enum *EnumDescriptor
  2098  		if id, ok := obj.(*ImportedDescriptor); ok {
  2099  			// The enum type has been publicly imported.
  2100  			enum, _ = id.o.(*EnumDescriptor)
  2101  		} else {
  2102  			enum, _ = obj.(*EnumDescriptor)
  2103  		}
  2104  		if enum == nil {
  2105  			log.Printf("don't know how to generate getter for %s", field.GetName())
  2106  			return "nil"
  2107  		}
  2108  		if len(enum.Value) == 0 {
  2109  			return "0 // empty enum"
  2110  		} else {
  2111  			first := enum.Value[0].GetName()
  2112  			if gogoproto.IsEnumValueCustomName(enum.Value[0]) {
  2113  				first = gogoproto.GetEnumValueCustomName(enum.Value[0])
  2114  			}
  2115  			if gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
  2116  				return g.DefaultPackageName(obj) + enum.prefix() + first
  2117  			} else {
  2118  				return g.DefaultPackageName(obj) + first
  2119  			}
  2120  		}
  2121  	default:
  2122  		return "0"
  2123  	}
  2124  }
  2125  
  2126  // defaultConstantName builds the name of the default constant from the message
  2127  // type name and the untouched field name, e.g. "Default_MessageType_FieldName"
  2128  func (g *Generator) defaultConstantName(goMessageType, protoFieldName string) string {
  2129  	return "Default_" + goMessageType + "_" + CamelCase(protoFieldName)
  2130  }
  2131  
  2132  // The different types of fields in a message and how to actually print them
  2133  // Most of the logic for generateMessage is in the methods of these types.
  2134  //
  2135  // Note that the content of the field is irrelevant, a simpleField can contain
  2136  // anything from a scalar to a group (which is just a message).
  2137  //
  2138  // Extension fields (and message sets) are however handled separately.
  2139  //
  2140  // simpleField - a field that is neiter weak nor oneof, possibly repeated
  2141  // oneofField - field containing list of subfields:
  2142  // - oneofSubField - a field within the oneof
  2143  
  2144  // msgCtx contains the context for the generator functions.
  2145  type msgCtx struct {
  2146  	goName  string      // Go struct name of the message, e.g. MessageName
  2147  	message *Descriptor // The descriptor for the message
  2148  }
  2149  
  2150  // fieldCommon contains data common to all types of fields.
  2151  type fieldCommon struct {
  2152  	goName     string                           // Go name of field, e.g. "FieldName" or "Descriptor_"
  2153  	protoName  string                           // Name of field in proto language, e.g. "field_name" or "descriptor"
  2154  	getterName string                           // Name of the getter, e.g. "GetFieldName" or "GetDescriptor_"
  2155  	goType     string                           // The Go type as a string, e.g. "*int32" or "*OtherMessage"
  2156  	tags       string                           // The tag string/annotation for the type, e.g. `protobuf:"varint,8,opt,name=region_id,json=regionId"`
  2157  	fullPath   string                           // The full path of the field as used by Annotate etc, e.g. "4,0,2,0"
  2158  	protoField *descriptor.FieldDescriptorProto // gogo. Passing in the fieldDescriptor in for gogo options. TODO rethink this, we might need a better way of getting options.
  2159  }
  2160  
  2161  // getProtoName gets the proto name of a field, e.g. "field_name" or "descriptor".
  2162  func (f *fieldCommon) getProtoName() string {
  2163  	return f.protoName
  2164  }
  2165  
  2166  // getGoType returns the go type of the field  as a string, e.g. "*int32".
  2167  func (f *fieldCommon) getGoType() string {
  2168  	return f.goType
  2169  }
  2170  
  2171  // simpleField is not weak, not a oneof, not an extension. Can be required, optional or repeated.
  2172  type simpleField struct {
  2173  	fieldCommon
  2174  	protoTypeName string                               // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration"
  2175  	protoType     descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
  2176  	deprecated    string                               // Deprecation comment, if any, e.g. "// Deprecated: Do not use."
  2177  	getterDef     string                               // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName"
  2178  	protoDef      string                               // Default value as defined in the proto file, e.g "yoshi" or "5"
  2179  	comment       string                               // The full comment for the field, e.g. "// Useful information"
  2180  }
  2181  
  2182  // decl prints the declaration of the field in the struct (if any).
  2183  func (f *simpleField) decl(g *Generator, mc *msgCtx) {
  2184  	g.P(f.comment, Annotate(mc.message.file, f.fullPath, f.goName), "\t", f.goType, "\t`", f.tags, "`", f.deprecated)
  2185  }
  2186  
  2187  // getter prints the getter for the field.
  2188  func (f *simpleField) getter(g *Generator, mc *msgCtx) {
  2189  	oneof := false
  2190  	if !oneof && !gogoproto.HasGoGetters(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2191  		return
  2192  	}
  2193  	if gogoproto.IsEmbed(f.protoField) || gogoproto.IsCustomType(f.protoField) {
  2194  		return
  2195  	}
  2196  	if f.deprecated != "" {
  2197  		g.P(f.deprecated)
  2198  	}
  2199  	g.generateGet(mc, f.protoField, f.protoType, false, f.goName, f.goType, "", "", f.fullPath, f.getterName, f.getterDef)
  2200  }
  2201  
  2202  // setter prints the setter method of the field.
  2203  func (f *simpleField) setter(g *Generator, mc *msgCtx) {
  2204  	// No setter for regular fields yet
  2205  }
  2206  
  2207  // getProtoDef returns the default value explicitly stated in the proto file, e.g "yoshi" or "5".
  2208  func (f *simpleField) getProtoDef() string {
  2209  	return f.protoDef
  2210  }
  2211  
  2212  // getProtoTypeName returns the protobuf type name for the field as returned by field.GetTypeName(), e.g. ".google.protobuf.Duration".
  2213  func (f *simpleField) getProtoTypeName() string {
  2214  	return f.protoTypeName
  2215  }
  2216  
  2217  // getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64.
  2218  func (f *simpleField) getProtoType() descriptor.FieldDescriptorProto_Type {
  2219  	return f.protoType
  2220  }
  2221  
  2222  func (f *simpleField) getProto() *descriptor.FieldDescriptorProto {
  2223  	return f.protoField
  2224  }
  2225  
  2226  // oneofSubFields are kept slize held by each oneofField. They do not appear in the top level slize of fields for the message.
  2227  type oneofSubField struct {
  2228  	fieldCommon
  2229  	protoTypeName string                               // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration"
  2230  	protoType     descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
  2231  	oneofTypeName string                               // Type name of the enclosing struct, e.g. "MessageName_FieldName"
  2232  	fieldNumber   int                                  // Actual field number, as defined in proto, e.g. 12
  2233  	getterDef     string                               // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName"
  2234  	protoDef      string                               // Default value as defined in the proto file, e.g "yoshi" or "5"
  2235  	deprecated    string                               // Deprecation comment, if any.
  2236  }
  2237  
  2238  // typedNil prints a nil casted to the pointer to this field.
  2239  // - for XXX_OneofWrappers
  2240  func (f *oneofSubField) typedNil(g *Generator) {
  2241  	g.P("(*", f.oneofTypeName, ")(nil),")
  2242  }
  2243  
  2244  // getProtoDef returns the default value explicitly stated in the proto file, e.g "yoshi" or "5".
  2245  func (f *oneofSubField) getProtoDef() string {
  2246  	return f.protoDef
  2247  }
  2248  
  2249  // getProtoTypeName returns the protobuf type name for the field as returned by field.GetTypeName(), e.g. ".google.protobuf.Duration".
  2250  func (f *oneofSubField) getProtoTypeName() string {
  2251  	return f.protoTypeName
  2252  }
  2253  
  2254  // getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64.
  2255  func (f *oneofSubField) getProtoType() descriptor.FieldDescriptorProto_Type {
  2256  	return f.protoType
  2257  }
  2258  
  2259  func (f *oneofSubField) getProto() *descriptor.FieldDescriptorProto {
  2260  	return f.protoField
  2261  }
  2262  
  2263  // oneofField represents the oneof on top level.
  2264  // The alternative fields within the oneof are represented by oneofSubField.
  2265  type oneofField struct {
  2266  	fieldCommon
  2267  	subFields []*oneofSubField // All the possible oneof fields
  2268  	comment   string           // The full comment for the field, e.g. "// Types that are valid to be assigned to MyOneof:\n\\"
  2269  }
  2270  
  2271  // decl prints the declaration of the field in the struct (if any).
  2272  func (f *oneofField) decl(g *Generator, mc *msgCtx) {
  2273  	comment := f.comment
  2274  	for _, sf := range f.subFields {
  2275  		comment += "//\t*" + sf.oneofTypeName + "\n"
  2276  	}
  2277  	g.P(comment, Annotate(mc.message.file, f.fullPath, f.goName), " ", f.goType, " `", f.tags, "`")
  2278  }
  2279  
  2280  // getter for a oneof field will print additional discriminators and interfaces for the oneof,
  2281  // also it prints all the getters for the sub fields.
  2282  func (f *oneofField) getter(g *Generator, mc *msgCtx) {
  2283  	oneof := true
  2284  	if !oneof && !gogoproto.HasGoGetters(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2285  		return
  2286  	}
  2287  
  2288  	for _, sf := range f.subFields {
  2289  		if gogoproto.IsEmbed(sf.protoField) || gogoproto.IsCustomType(sf.protoField) {
  2290  			continue
  2291  		}
  2292  		if sf.deprecated != "" {
  2293  			g.P(sf.deprecated)
  2294  		}
  2295  		g.generateGet(mc, sf.protoField, sf.protoType, true, sf.goName, sf.goType, f.goName, sf.oneofTypeName, sf.fullPath, sf.getterName, sf.getterDef)
  2296  	}
  2297  }
  2298  
  2299  // setter prints the setter method of the field.
  2300  func (f *oneofField) setter(g *Generator, mc *msgCtx) {
  2301  	// No setters for oneof yet
  2302  }
  2303  
  2304  // topLevelField interface implemented by all types of fields on the top level (not oneofSubField).
  2305  type topLevelField interface {
  2306  	decl(g *Generator, mc *msgCtx)   // print declaration within the struct
  2307  	getter(g *Generator, mc *msgCtx) // print getter
  2308  	setter(g *Generator, mc *msgCtx) // print setter if applicable
  2309  }
  2310  
  2311  // defField interface implemented by all types of fields that can have defaults (not oneofField, but instead oneofSubField).
  2312  type defField interface {
  2313  	getProtoDef() string                                // default value explicitly stated in the proto file, e.g "yoshi" or "5"
  2314  	getProtoName() string                               // proto name of a field, e.g. "field_name" or "descriptor"
  2315  	getGoType() string                                  // go type of the field  as a string, e.g. "*int32"
  2316  	getProtoTypeName() string                           // protobuf type name for the field, e.g. ".google.protobuf.Duration"
  2317  	getProtoType() descriptor.FieldDescriptorProto_Type // *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
  2318  	getProto() *descriptor.FieldDescriptorProto
  2319  }
  2320  
  2321  // generateDefaultConstants adds constants for default values if needed, which is only if the default value is.
  2322  // explicit in the proto.
  2323  func (g *Generator) generateDefaultConstants(mc *msgCtx, topLevelFields []topLevelField) {
  2324  	// Collect fields that can have defaults
  2325  	dFields := []defField{}
  2326  	for _, pf := range topLevelFields {
  2327  		if f, ok := pf.(*oneofField); ok {
  2328  			for _, osf := range f.subFields {
  2329  				dFields = append(dFields, osf)
  2330  			}
  2331  			continue
  2332  		}
  2333  		dFields = append(dFields, pf.(defField))
  2334  	}
  2335  	for _, df := range dFields {
  2336  		def := df.getProtoDef()
  2337  		if def == "" {
  2338  			continue
  2339  		}
  2340  		if !gogoproto.IsNullable(df.getProto()) {
  2341  			g.Fail("illegal default value: ", df.getProtoName(), " in ", mc.message.GetName(), " is not nullable and is thus not allowed to have a default value")
  2342  		}
  2343  		fieldname := g.defaultConstantName(mc.goName, df.getProtoName())
  2344  		typename := df.getGoType()
  2345  		if typename[0] == '*' {
  2346  			typename = typename[1:]
  2347  		}
  2348  		kind := "const "
  2349  		switch {
  2350  		case typename == "bool":
  2351  		case typename == "string":
  2352  			def = strconv.Quote(def)
  2353  		case typename == "[]byte":
  2354  			def = "[]byte(" + strconv.Quote(unescape(def)) + ")"
  2355  			kind = "var "
  2356  		case def == "inf", def == "-inf", def == "nan":
  2357  			// These names are known to, and defined by, the protocol language.
  2358  			switch def {
  2359  			case "inf":
  2360  				def = "math.Inf(1)"
  2361  			case "-inf":
  2362  				def = "math.Inf(-1)"
  2363  			case "nan":
  2364  				def = "math.NaN()"
  2365  			}
  2366  			if df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_FLOAT {
  2367  				def = "float32(" + def + ")"
  2368  			}
  2369  			kind = "var "
  2370  		case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_FLOAT:
  2371  			if f, err := strconv.ParseFloat(def, 32); err == nil {
  2372  				def = fmt.Sprint(float32(f))
  2373  			}
  2374  		case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_DOUBLE:
  2375  			if f, err := strconv.ParseFloat(def, 64); err == nil {
  2376  				def = fmt.Sprint(f)
  2377  			}
  2378  		case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_ENUM:
  2379  			// Must be an enum.  Need to construct the prefixed name.
  2380  			obj := g.ObjectNamed(df.getProtoTypeName())
  2381  			var enum *EnumDescriptor
  2382  			if id, ok := obj.(*ImportedDescriptor); ok {
  2383  				// The enum type has been publicly imported.
  2384  				enum, _ = id.o.(*EnumDescriptor)
  2385  			} else {
  2386  				enum, _ = obj.(*EnumDescriptor)
  2387  			}
  2388  			if enum == nil {
  2389  				log.Printf("don't know how to generate constant for %s", fieldname)
  2390  				continue
  2391  			}
  2392  
  2393  			// hunt down the actual enum corresponding to the default
  2394  			var enumValue *descriptor.EnumValueDescriptorProto
  2395  			for _, ev := range enum.Value {
  2396  				if def == ev.GetName() {
  2397  					enumValue = ev
  2398  				}
  2399  			}
  2400  
  2401  			if enumValue != nil {
  2402  				if gogoproto.IsEnumValueCustomName(enumValue) {
  2403  					def = gogoproto.GetEnumValueCustomName(enumValue)
  2404  				}
  2405  			} else {
  2406  				g.Fail(fmt.Sprintf("could not resolve default enum value for %v.%v", g.DefaultPackageName(obj), def))
  2407  			}
  2408  
  2409  			if gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
  2410  				def = g.DefaultPackageName(obj) + enum.prefix() + def
  2411  			} else {
  2412  				def = g.DefaultPackageName(obj) + def
  2413  			}
  2414  		}
  2415  		g.P(kind, fieldname, " ", typename, " = ", def)
  2416  		g.file.addExport(mc.message, constOrVarSymbol{fieldname, kind, ""})
  2417  	}
  2418  	g.P()
  2419  }
  2420  
  2421  // generateGet generates the getter for both the simpleField and oneofSubField.
  2422  // We did not want to duplicate the code since it is quite intricate so we came
  2423  // up with this ugly method. At least the logic is in one place. This can be reworked.
  2424  func (g *Generator) generateGet(mc *msgCtx, protoField *descriptor.FieldDescriptorProto, protoType descriptor.FieldDescriptorProto_Type,
  2425  	oneof bool, fname, tname, uname, oneoftname, fullpath, gname, def string) {
  2426  	star := ""
  2427  	if (protoType != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
  2428  		(protoType != descriptor.FieldDescriptorProto_TYPE_GROUP) &&
  2429  		needsStar(protoField, g.file.proto3, mc.message != nil && mc.message.allowOneof()) && tname[0] == '*' {
  2430  		tname = tname[1:]
  2431  		star = "*"
  2432  	}
  2433  	typeDefaultIsNil := false // whether this field type's default value is a literal nil unless specified
  2434  	switch protoType {
  2435  	case descriptor.FieldDescriptorProto_TYPE_BYTES:
  2436  		typeDefaultIsNil = def == "nil"
  2437  	case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE:
  2438  		typeDefaultIsNil = gogoproto.IsNullable(protoField)
  2439  	}
  2440  	if isRepeated(protoField) {
  2441  		typeDefaultIsNil = true
  2442  	}
  2443  	g.P("func (m *", mc.goName, ") ", Annotate(mc.message.file, fullpath, gname), "() "+tname+" {")
  2444  	if !oneof && typeDefaultIsNil {
  2445  		// A bytes field with no explicit default needs less generated code,
  2446  		// as does a message or group field, or a repeated field.
  2447  		g.P("if m != nil {")
  2448  		g.In()
  2449  		g.P("return m." + fname)
  2450  		g.Out()
  2451  		g.P("}")
  2452  		g.P("return nil")
  2453  		g.Out()
  2454  		g.P("}")
  2455  		g.P()
  2456  		return
  2457  	}
  2458  	if !gogoproto.IsNullable(protoField) {
  2459  		g.P("if m != nil {")
  2460  		g.In()
  2461  		g.P("return m." + fname)
  2462  		g.Out()
  2463  		g.P("}")
  2464  	} else if !oneof {
  2465  		if mc.message.proto3() {
  2466  			g.P("if m != nil {")
  2467  		} else {
  2468  			g.P("if m != nil && m." + fname + " != nil {")
  2469  		}
  2470  		g.In()
  2471  		g.P("return " + star + "m." + fname)
  2472  		g.Out()
  2473  		g.P("}")
  2474  	} else {
  2475  		uname := uname
  2476  		tname := oneoftname
  2477  		g.P("if x, ok := m.Get", uname, "().(*", tname, "); ok {")
  2478  		g.P("return x.", fname)
  2479  		g.P("}")
  2480  	}
  2481  	g.P("return ", def)
  2482  	g.Out()
  2483  	g.P("}")
  2484  	g.P()
  2485  }
  2486  
  2487  // generateInternalStructFields just adds the XXX_<something> fields to the message struct.
  2488  func (g *Generator) generateInternalStructFields(mc *msgCtx, topLevelFields []topLevelField) {
  2489  	if gogoproto.HasUnkeyed(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2490  		g.P("XXX_NoUnkeyedLiteral\tstruct{} `json:\"-\"`") // prevent unkeyed struct literals
  2491  	}
  2492  	if len(mc.message.ExtensionRange) > 0 {
  2493  		if gogoproto.HasExtensionsMap(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2494  			messageset := ""
  2495  			if opts := mc.message.Options; opts != nil && opts.GetMessageSetWireFormat() {
  2496  				messageset = "protobuf_messageset:\"1\" "
  2497  			}
  2498  			g.P(g.Pkg["proto"], ".XXX_InternalExtensions `", messageset, "json:\"-\"`")
  2499  		} else {
  2500  			g.P("XXX_extensions\t\t[]byte `protobuf:\"bytes,0,opt\" json:\"-\"`")
  2501  		}
  2502  	}
  2503  	if gogoproto.HasUnrecognized(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2504  		g.P("XXX_unrecognized\t[]byte `json:\"-\"`")
  2505  	}
  2506  	if gogoproto.HasSizecache(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2507  		g.P("XXX_sizecache\tint32 `json:\"-\"`")
  2508  	}
  2509  }
  2510  
  2511  // generateOneofFuncs adds all the utility functions for oneof, including marshalling, unmarshalling and sizer.
  2512  func (g *Generator) generateOneofFuncs(mc *msgCtx, topLevelFields []topLevelField) {
  2513  	ofields := []*oneofField{}
  2514  	for _, f := range topLevelFields {
  2515  		if o, ok := f.(*oneofField); ok {
  2516  			ofields = append(ofields, o)
  2517  		}
  2518  	}
  2519  	if len(ofields) == 0 {
  2520  		return
  2521  	}
  2522  
  2523  	// OneofFuncs
  2524  	g.P("// XXX_OneofWrappers is for the internal use of the proto package.")
  2525  	g.P("func (*", mc.goName, ") XXX_OneofWrappers() []interface{} {")
  2526  	g.P("return []interface{}{")
  2527  	for _, of := range ofields {
  2528  		for _, sf := range of.subFields {
  2529  			sf.typedNil(g)
  2530  		}
  2531  	}
  2532  	g.P("}")
  2533  	g.P("}")
  2534  	g.P()
  2535  }
  2536  
  2537  func (g *Generator) generateOneofDecls(mc *msgCtx, topLevelFields []topLevelField) {
  2538  	ofields := []*oneofField{}
  2539  	for _, f := range topLevelFields {
  2540  		if o, ok := f.(*oneofField); ok {
  2541  			ofields = append(ofields, o)
  2542  		}
  2543  	}
  2544  	if len(ofields) == 0 {
  2545  		return
  2546  	}
  2547  	// Oneof per-field types, discriminants and getters.
  2548  	// Generate unexported named types for the discriminant interfaces.
  2549  	// We shouldn't have to do this, but there was (~19 Aug 2015) a compiler/linker bug
  2550  	// that was triggered by using anonymous interfaces here.
  2551  	// TODO: Revisit this and consider reverting back to anonymous interfaces.
  2552  	// for oi := range message.OneofDecl {
  2553  	for _, of := range ofields {
  2554  		dname := of.goType
  2555  		g.P("type ", dname, " interface {")
  2556  		g.In()
  2557  		g.P(dname, "()")
  2558  		if gogoproto.HasEqual(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2559  			g.P(`Equal(interface{}) bool`)
  2560  		}
  2561  		if gogoproto.HasVerboseEqual(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2562  			g.P(`VerboseEqual(interface{}) error`)
  2563  		}
  2564  		if gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
  2565  			gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
  2566  			gogoproto.IsStableMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2567  			g.P(`MarshalTo([]byte) (int, error)`)
  2568  		}
  2569  		if gogoproto.IsSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2570  			g.P(`Size() int`)
  2571  		}
  2572  		if gogoproto.IsProtoSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2573  			g.P(`ProtoSize() int`)
  2574  		}
  2575  		if gogoproto.HasCompare(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2576  			g.P(`Compare(interface{}) int`)
  2577  		}
  2578  		g.Out()
  2579  		g.P("}")
  2580  	}
  2581  	g.P()
  2582  	for _, of := range ofields {
  2583  		for i, sf := range of.subFields {
  2584  			fieldFullPath := fmt.Sprintf("%s,%d,%d", mc.message.path, messageFieldPath, i)
  2585  			g.P("type ", Annotate(mc.message.file, fieldFullPath, sf.oneofTypeName), " struct{ ", Annotate(mc.message.file, fieldFullPath, sf.goName), " ", sf.goType, " `", sf.tags, "` }")
  2586  			if !gogoproto.IsStdType(sf.protoField) && !gogoproto.IsCustomType(sf.protoField) && !gogoproto.IsCastType(sf.protoField) {
  2587  				g.RecordTypeUse(sf.protoField.GetTypeName())
  2588  			}
  2589  		}
  2590  	}
  2591  	g.P()
  2592  	for _, of := range ofields {
  2593  		for _, sf := range of.subFields {
  2594  			g.P("func (*", sf.oneofTypeName, ") ", of.goType, "() {}")
  2595  		}
  2596  	}
  2597  	g.P()
  2598  	for _, of := range ofields {
  2599  		fname := of.goName
  2600  		g.P("func (m *", mc.goName, ") Get", fname, "() ", of.goType, " {")
  2601  		g.P("if m != nil { return m.", fname, " }")
  2602  		g.P("return nil")
  2603  		g.P("}")
  2604  	}
  2605  	g.P()
  2606  }
  2607  
  2608  // generateMessageStruct adds the actual struct with it's members (but not methods) to the output.
  2609  func (g *Generator) generateMessageStruct(mc *msgCtx, topLevelFields []topLevelField) {
  2610  	comments := g.PrintComments(mc.message.path)
  2611  
  2612  	// Guarantee deprecation comments appear after user-provided comments.
  2613  	if mc.message.GetOptions().GetDeprecated() {
  2614  		if comments {
  2615  			// Convention: Separate deprecation comments from original
  2616  			// comments with an empty line.
  2617  			g.P("//")
  2618  		}
  2619  		g.P(deprecationComment)
  2620  	}
  2621  	g.P("type ", Annotate(mc.message.file, mc.message.path, mc.goName), " struct {")
  2622  	for _, pf := range topLevelFields {
  2623  		pf.decl(g, mc)
  2624  	}
  2625  	g.generateInternalStructFields(mc, topLevelFields)
  2626  	g.P("}")
  2627  }
  2628  
  2629  // generateGetters adds getters for all fields, including oneofs and weak fields when applicable.
  2630  func (g *Generator) generateGetters(mc *msgCtx, topLevelFields []topLevelField) {
  2631  	for _, pf := range topLevelFields {
  2632  		pf.getter(g, mc)
  2633  
  2634  	}
  2635  }
  2636  
  2637  // generateSetters add setters for all fields, including oneofs and weak fields when applicable.
  2638  func (g *Generator) generateSetters(mc *msgCtx, topLevelFields []topLevelField) {
  2639  	for _, pf := range topLevelFields {
  2640  		pf.setter(g, mc)
  2641  	}
  2642  }
  2643  
  2644  // generateCommonMethods adds methods to the message that are not on a per field basis.
  2645  func (g *Generator) generateCommonMethods(mc *msgCtx) {
  2646  	// Reset, String and ProtoMessage methods.
  2647  	g.P("func (m *", mc.goName, ") Reset() { *m = ", mc.goName, "{} }")
  2648  	if gogoproto.EnabledGoStringer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2649  		g.P("func (m *", mc.goName, ") String() string { return ", g.Pkg["proto"], ".CompactTextString(m) }")
  2650  	}
  2651  	g.P("func (*", mc.goName, ") ProtoMessage() {}")
  2652  	var indexes []string
  2653  	for m := mc.message; m != nil; m = m.parent {
  2654  		indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
  2655  	}
  2656  	g.P("func (*", mc.goName, ") Descriptor() ([]byte, []int) {")
  2657  	g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}")
  2658  	g.P("}")
  2659  	// TODO: Revisit the decision to use a XXX_WellKnownType method
  2660  	// if we change proto.MessageName to work with multiple equivalents.
  2661  	if mc.message.file.GetPackage() == "google.protobuf" && wellKnownTypes[mc.message.GetName()] {
  2662  		g.P("func (*", mc.goName, `) XXX_WellKnownType() string { return "`, mc.message.GetName(), `" }`)
  2663  	}
  2664  
  2665  	// Extension support methods
  2666  	if len(mc.message.ExtensionRange) > 0 {
  2667  		g.P()
  2668  		g.P("var extRange_", mc.goName, " = []", g.Pkg["proto"], ".ExtensionRange{")
  2669  		g.In()
  2670  		for _, r := range mc.message.ExtensionRange {
  2671  			end := fmt.Sprint(*r.End - 1) // make range inclusive on both ends
  2672  			g.P("{Start: ", r.Start, ", End: ", end, "},")
  2673  		}
  2674  		g.Out()
  2675  		g.P("}")
  2676  		g.P("func (*", mc.goName, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange {")
  2677  		g.In()
  2678  		g.P("return extRange_", mc.goName)
  2679  		g.Out()
  2680  		g.P("}")
  2681  		g.P()
  2682  		if !gogoproto.HasExtensionsMap(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2683  			g.P("func (m *", mc.goName, ") GetExtensions() *[]byte {")
  2684  			g.In()
  2685  			g.P("if m.XXX_extensions == nil {")
  2686  			g.In()
  2687  			g.P("m.XXX_extensions = make([]byte, 0)")
  2688  			g.Out()
  2689  			g.P("}")
  2690  			g.P("return &m.XXX_extensions")
  2691  			g.Out()
  2692  			g.P("}")
  2693  		}
  2694  	}
  2695  
  2696  	// TODO: It does not scale to keep adding another method for every
  2697  	// operation on protos that we want to switch over to using the
  2698  	// table-driven approach. Instead, we should only add a single method
  2699  	// that allows getting access to the *InternalMessageInfo struct and then
  2700  	// calling Unmarshal, Marshal, Merge, Size, and Discard directly on that.
  2701  
  2702  	// Wrapper for table-driven marshaling and unmarshaling.
  2703  	g.P("func (m *", mc.goName, ") XXX_Unmarshal(b []byte) error {")
  2704  	g.In()
  2705  	if gogoproto.IsUnmarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2706  		g.P("return m.Unmarshal(b)")
  2707  	} else {
  2708  		g.P("return xxx_messageInfo_", mc.goName, ".Unmarshal(m, b)")
  2709  	}
  2710  	g.Out()
  2711  	g.P("}")
  2712  
  2713  	g.P("func (m *", mc.goName, ") XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {")
  2714  	g.In()
  2715  	if gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
  2716  		gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2717  		if gogoproto.IsStableMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2718  			g.P("b = b[:cap(b)]")
  2719  			g.P("n, err := m.MarshalToSizedBuffer(b)")
  2720  			g.P("if err != nil {")
  2721  			g.In()
  2722  			g.P("return nil, err")
  2723  			g.Out()
  2724  			g.P("}")
  2725  			g.P("return b[:n], nil")
  2726  		} else {
  2727  			g.P("if deterministic {")
  2728  			g.In()
  2729  			g.P("return xxx_messageInfo_", mc.goName, ".Marshal(b, m, deterministic)")
  2730  			g.P("} else {")
  2731  			g.In()
  2732  			g.P("b = b[:cap(b)]")
  2733  			g.P("n, err := m.MarshalToSizedBuffer(b)")
  2734  			g.P("if err != nil {")
  2735  			g.In()
  2736  			g.P("return nil, err")
  2737  			g.Out()
  2738  			g.P("}")
  2739  			g.Out()
  2740  			g.P("return b[:n], nil")
  2741  			g.Out()
  2742  			g.P("}")
  2743  		}
  2744  	} else {
  2745  		g.P("return xxx_messageInfo_", mc.goName, ".Marshal(b, m, deterministic)")
  2746  	}
  2747  	g.Out()
  2748  	g.P("}")
  2749  
  2750  	g.P("func (m *", mc.goName, ") XXX_Merge(src ", g.Pkg["proto"], ".Message) {")
  2751  	g.In()
  2752  	g.P("xxx_messageInfo_", mc.goName, ".Merge(m, src)")
  2753  	g.Out()
  2754  	g.P("}")
  2755  
  2756  	g.P("func (m *", mc.goName, ") XXX_Size() int {") // avoid name clash with "Size" field in some message
  2757  	g.In()
  2758  	if (gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
  2759  		gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto)) &&
  2760  		gogoproto.IsSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2761  		g.P("return m.Size()")
  2762  	} else if (gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
  2763  		gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto)) &&
  2764  		gogoproto.IsProtoSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
  2765  		g.P("return m.ProtoSize()")
  2766  	} else {
  2767  		g.P("return xxx_messageInfo_", mc.goName, ".Size(m)")
  2768  	}
  2769  	g.Out()
  2770  	g.P("}")
  2771  
  2772  	g.P("func (m *", mc.goName, ") XXX_DiscardUnknown() {")
  2773  	g.In()
  2774  	g.P("xxx_messageInfo_", mc.goName, ".DiscardUnknown(m)")
  2775  	g.Out()
  2776  	g.P("}")
  2777  
  2778  	g.P("var xxx_messageInfo_", mc.goName, " ", g.Pkg["proto"], ".InternalMessageInfo")
  2779  }
  2780  
  2781  // Generate the type and default constant definitions for this Descriptor.
  2782  func (g *Generator) generateMessage(message *Descriptor) {
  2783  	topLevelFields := []topLevelField{}
  2784  	oFields := make(map[int32]*oneofField)
  2785  	// The full type name
  2786  	typeName := message.TypeName()
  2787  	// The full type name, CamelCased.
  2788  	goTypeName := CamelCaseSlice(typeName)
  2789  
  2790  	usedNames := make(map[string]bool)
  2791  	for _, n := range methodNames {
  2792  		usedNames[n] = true
  2793  	}
  2794  	if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
  2795  		usedNames["Size"] = true
  2796  	}
  2797  
  2798  	// allocNames finds a conflict-free variation of the given strings,
  2799  	// consistently mutating their suffixes.
  2800  	// It returns the same number of strings.
  2801  	allocNames := func(ns ...string) []string {
  2802  	Loop:
  2803  		for {
  2804  			for _, n := range ns {
  2805  				if usedNames[n] {
  2806  					for i := range ns {
  2807  						ns[i] += "_"
  2808  					}
  2809  					continue Loop
  2810  				}
  2811  			}
  2812  			for _, n := range ns {
  2813  				usedNames[n] = true
  2814  			}
  2815  			return ns
  2816  		}
  2817  	}
  2818  
  2819  	mapFieldTypes := make(map[*descriptor.FieldDescriptorProto]string) // keep track of the map fields to be added later
  2820  
  2821  	for i, field := range message.Field {
  2822  		// Allocate the getter and the field at the same time so name
  2823  		// collisions create field/method consistent names.
  2824  		// TODO: This allocation occurs based on the order of the fields
  2825  		// in the proto file, meaning that a change in the field
  2826  		// ordering can change generated Method/Field names.
  2827  		base := CamelCase(*field.Name)
  2828  		if gogoproto.IsCustomName(field) {
  2829  			base = gogoproto.GetCustomName(field)
  2830  		}
  2831  		ns := allocNames(base, "Get"+base)
  2832  		fieldName, fieldGetterName := ns[0], ns[1]
  2833  
  2834  		typename, wiretype := g.GoType(message, field)
  2835  		jsonName := *field.Name
  2836  		jsonTag := jsonName + ",omitempty"
  2837  		repeatedNativeType := (!field.IsMessage() && !gogoproto.IsCustomType(field) && field.IsRepeated())
  2838  		if !gogoproto.IsNullable(field) && !repeatedNativeType {
  2839  			jsonTag = jsonName
  2840  		}
  2841  		gogoJsonTag := gogoproto.GetJsonTag(field)
  2842  		if gogoJsonTag != nil {
  2843  			jsonTag = *gogoJsonTag
  2844  		}
  2845  		gogoMoreTags := gogoproto.GetMoreTags(field)
  2846  		moreTags := ""
  2847  		if gogoMoreTags != nil {
  2848  			moreTags = " " + *gogoMoreTags
  2849  		}
  2850  		tag := fmt.Sprintf("protobuf:%s json:%q%s", g.goTag(message, field, wiretype), jsonTag, moreTags)
  2851  		if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE && gogoproto.IsEmbed(field) {
  2852  			fieldName = ""
  2853  		}
  2854  
  2855  		oneof := field.OneofIndex != nil && message.allowOneof()
  2856  		if oneof && oFields[*field.OneofIndex] == nil {
  2857  			odp := message.OneofDecl[int(*field.OneofIndex)]
  2858  			base := CamelCase(odp.GetName())
  2859  			names := allocNames(base, "Get"+base)
  2860  			fname, gname := names[0], names[1]
  2861  
  2862  			// This is the first field of a oneof we haven't seen before.
  2863  			// Generate the union field.
  2864  			oneofFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageOneofPath, *field.OneofIndex)
  2865  			c, ok := g.makeComments(oneofFullPath)
  2866  			if ok {
  2867  				c += "\n//\n"
  2868  			}
  2869  			c += "// Types that are valid to be assigned to " + fname + ":\n"
  2870  			// Generate the rest of this comment later,
  2871  			// when we've computed any disambiguation.
  2872  
  2873  			dname := "is" + goTypeName + "_" + fname
  2874  			oneOftag := `protobuf_oneof:"` + odp.GetName() + `"`
  2875  			of := oneofField{
  2876  				fieldCommon: fieldCommon{
  2877  					goName:     fname,
  2878  					getterName: gname,
  2879  					goType:     dname,
  2880  					tags:       oneOftag,
  2881  					protoName:  odp.GetName(),
  2882  					fullPath:   oneofFullPath,
  2883  					protoField: field,
  2884  				},
  2885  				comment: c,
  2886  			}
  2887  			topLevelFields = append(topLevelFields, &of)
  2888  			oFields[*field.OneofIndex] = &of
  2889  		}
  2890  
  2891  		if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE {
  2892  			desc := g.ObjectNamed(field.GetTypeName())
  2893  			if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() {
  2894  				m := g.GoMapType(d, field)
  2895  				typename = m.GoType
  2896  				mapFieldTypes[field] = typename // record for the getter generation
  2897  
  2898  				tag += fmt.Sprintf(" protobuf_key:%s protobuf_val:%s", m.KeyTag, m.ValueTag)
  2899  			}
  2900  		}
  2901  		goTyp, _ := g.GoType(message, field)
  2902  		fieldDeprecated := ""
  2903  		if field.GetOptions().GetDeprecated() {
  2904  			fieldDeprecated = deprecationComment
  2905  		}
  2906  		dvalue := g.getterDefault(field, goTypeName, GoTypeToName(goTyp))
  2907  		if oneof {
  2908  			tname := goTypeName + "_" + fieldName
  2909  			// It is possible for this to collide with a message or enum
  2910  			// nested in this message. Check for collisions.
  2911  			for {
  2912  				ok := true
  2913  				for _, desc := range message.nested {
  2914  					if CamelCaseSlice(desc.TypeName()) == tname {
  2915  						ok = false
  2916  						break
  2917  					}
  2918  				}
  2919  				for _, enum := range message.enums {
  2920  					if CamelCaseSlice(enum.TypeName()) == tname {
  2921  						ok = false
  2922  						break
  2923  					}
  2924  				}
  2925  				if !ok {
  2926  					tname += "_"
  2927  					continue
  2928  				}
  2929  				break
  2930  			}
  2931  
  2932  			oneofField := oFields[*field.OneofIndex]
  2933  			sf := oneofSubField{
  2934  				fieldCommon: fieldCommon{
  2935  					goName:     fieldName,
  2936  					getterName: fieldGetterName,
  2937  					goType:     typename,
  2938  					tags:       tag,
  2939  					protoName:  field.GetName(),
  2940  					fullPath:   fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i),
  2941  					protoField: field,
  2942  				},
  2943  				protoTypeName: field.GetTypeName(),
  2944  				fieldNumber:   int(*field.Number),
  2945  				protoType:     *field.Type,
  2946  				getterDef:     dvalue,
  2947  				protoDef:      field.GetDefaultValue(),
  2948  				oneofTypeName: tname,
  2949  				deprecated:    fieldDeprecated,
  2950  			}
  2951  
  2952  			oneofField.subFields = append(oneofField.subFields, &sf)
  2953  			if !gogoproto.IsStdType(field) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
  2954  				g.RecordTypeUse(field.GetTypeName())
  2955  			}
  2956  			continue
  2957  		}
  2958  
  2959  		fieldFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i)
  2960  		c, ok := g.makeComments(fieldFullPath)
  2961  		if ok {
  2962  			c += "\n"
  2963  		}
  2964  		rf := simpleField{
  2965  			fieldCommon: fieldCommon{
  2966  				goName:     fieldName,
  2967  				getterName: fieldGetterName,
  2968  				goType:     typename,
  2969  				tags:       tag,
  2970  				protoName:  field.GetName(),
  2971  				fullPath:   fieldFullPath,
  2972  				protoField: field,
  2973  			},
  2974  			protoTypeName: field.GetTypeName(),
  2975  			protoType:     *field.Type,
  2976  			deprecated:    fieldDeprecated,
  2977  			getterDef:     dvalue,
  2978  			protoDef:      field.GetDefaultValue(),
  2979  			comment:       c,
  2980  		}
  2981  		var pf topLevelField = &rf
  2982  
  2983  		topLevelFields = append(topLevelFields, pf)
  2984  
  2985  		if gogoproto.HasTypeDecl(message.file.FileDescriptorProto, message.DescriptorProto) {
  2986  			if !gogoproto.IsStdType(field) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
  2987  				g.RecordTypeUse(field.GetTypeName())
  2988  			}
  2989  		} else {
  2990  			// Even if the type does not need to be generated, we need to iterate
  2991  			// over all its fields to be able to mark as used any imported types
  2992  			// used by those fields.
  2993  			for _, mfield := range message.Field {
  2994  				if !gogoproto.IsStdType(mfield) && !gogoproto.IsCustomType(mfield) && !gogoproto.IsCastType(mfield) {
  2995  					g.RecordTypeUse(mfield.GetTypeName())
  2996  				}
  2997  			}
  2998  		}
  2999  	}
  3000  
  3001  	mc := &msgCtx{
  3002  		goName:  goTypeName,
  3003  		message: message,
  3004  	}
  3005  
  3006  	if gogoproto.HasTypeDecl(message.file.FileDescriptorProto, message.DescriptorProto) {
  3007  		g.generateMessageStruct(mc, topLevelFields)
  3008  		g.P()
  3009  	}
  3010  	g.generateCommonMethods(mc)
  3011  	g.P()
  3012  	g.generateDefaultConstants(mc, topLevelFields)
  3013  	g.P()
  3014  	g.generateOneofDecls(mc, topLevelFields)
  3015  	g.P()
  3016  	g.generateGetters(mc, topLevelFields)
  3017  	g.P()
  3018  	g.generateSetters(mc, topLevelFields)
  3019  	g.P()
  3020  	g.generateOneofFuncs(mc, topLevelFields)
  3021  	g.P()
  3022  
  3023  	var oneofTypes []string
  3024  	for _, f := range topLevelFields {
  3025  		if of, ok := f.(*oneofField); ok {
  3026  			for _, osf := range of.subFields {
  3027  				oneofTypes = append(oneofTypes, osf.oneofTypeName)
  3028  			}
  3029  		}
  3030  	}
  3031  
  3032  	opts := message.Options
  3033  	ms := &messageSymbol{
  3034  		sym:           goTypeName,
  3035  		hasExtensions: len(message.ExtensionRange) > 0,
  3036  		isMessageSet:  opts != nil && opts.GetMessageSetWireFormat(),
  3037  		oneofTypes:    oneofTypes,
  3038  	}
  3039  	g.file.addExport(message, ms)
  3040  
  3041  	for _, ext := range message.ext {
  3042  		g.generateExtension(ext)
  3043  	}
  3044  
  3045  	fullName := strings.Join(message.TypeName(), ".")
  3046  	if g.file.Package != nil {
  3047  		fullName = *g.file.Package + "." + fullName
  3048  	}
  3049  
  3050  	g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], goTypeName, fullName)
  3051  	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
  3052  		g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["golang_proto"], goTypeName, fullName)
  3053  	}
  3054  	if gogoproto.HasMessageName(g.file.FileDescriptorProto, message.DescriptorProto) {
  3055  		g.P("func (*", goTypeName, ") XXX_MessageName() string {")
  3056  		g.In()
  3057  		g.P("return ", strconv.Quote(fullName))
  3058  		g.Out()
  3059  		g.P("}")
  3060  	}
  3061  	// Register types for native map types.
  3062  	for _, k := range mapFieldKeys(mapFieldTypes) {
  3063  		fullName := strings.TrimPrefix(*k.TypeName, ".")
  3064  		g.addInitf("%s.RegisterMapType((%s)(nil), %q)", g.Pkg["proto"], mapFieldTypes[k], fullName)
  3065  		if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
  3066  			g.addInitf("%s.RegisterMapType((%s)(nil), %q)", g.Pkg["golang_proto"], mapFieldTypes[k], fullName)
  3067  		}
  3068  	}
  3069  }
  3070  
  3071  type byTypeName []*descriptor.FieldDescriptorProto
  3072  
  3073  func (a byTypeName) Len() int           { return len(a) }
  3074  func (a byTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
  3075  func (a byTypeName) Less(i, j int) bool { return *a[i].TypeName < *a[j].TypeName }
  3076  
  3077  // mapFieldKeys returns the keys of m in a consistent order.
  3078  func mapFieldKeys(m map[*descriptor.FieldDescriptorProto]string) []*descriptor.FieldDescriptorProto {
  3079  	keys := make([]*descriptor.FieldDescriptorProto, 0, len(m))
  3080  	for k := range m {
  3081  		keys = append(keys, k)
  3082  	}
  3083  	sort.Sort(byTypeName(keys))
  3084  	return keys
  3085  }
  3086  
  3087  var escapeChars = [256]byte{
  3088  	'a': '\a', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', 'v': '\v', '\\': '\\', '"': '"', '\'': '\'', '?': '?',
  3089  }
  3090  
  3091  // unescape reverses the "C" escaping that protoc does for default values of bytes fields.
  3092  // It is best effort in that it effectively ignores malformed input. Seemingly invalid escape
  3093  // sequences are conveyed, unmodified, into the decoded result.
  3094  func unescape(s string) string {
  3095  	// NB: Sadly, we can't use strconv.Unquote because protoc will escape both
  3096  	// single and double quotes, but strconv.Unquote only allows one or the
  3097  	// other (based on actual surrounding quotes of its input argument).
  3098  
  3099  	var out []byte
  3100  	for len(s) > 0 {
  3101  		// regular character, or too short to be valid escape
  3102  		if s[0] != '\\' || len(s) < 2 {
  3103  			out = append(out, s[0])
  3104  			s = s[1:]
  3105  		} else if c := escapeChars[s[1]]; c != 0 {
  3106  			// escape sequence
  3107  			out = append(out, c)
  3108  			s = s[2:]
  3109  		} else if s[1] == 'x' || s[1] == 'X' {
  3110  			// hex escape, e.g. "\x80
  3111  			if len(s) < 4 {
  3112  				// too short to be valid
  3113  				out = append(out, s[:2]...)
  3114  				s = s[2:]
  3115  				continue
  3116  			}
  3117  			v, err := strconv.ParseUint(s[2:4], 16, 8)
  3118  			if err != nil {
  3119  				out = append(out, s[:4]...)
  3120  			} else {
  3121  				out = append(out, byte(v))
  3122  			}
  3123  			s = s[4:]
  3124  		} else if '0' <= s[1] && s[1] <= '7' {
  3125  			// octal escape, can vary from 1 to 3 octal digits; e.g., "\0" "\40" or "\164"
  3126  			// so consume up to 2 more bytes or up to end-of-string
  3127  			n := len(s[1:]) - len(strings.TrimLeft(s[1:], "01234567"))
  3128  			if n > 3 {
  3129  				n = 3
  3130  			}
  3131  			v, err := strconv.ParseUint(s[1:1+n], 8, 8)
  3132  			if err != nil {
  3133  				out = append(out, s[:1+n]...)
  3134  			} else {
  3135  				out = append(out, byte(v))
  3136  			}
  3137  			s = s[1+n:]
  3138  		} else {
  3139  			// bad escape, just propagate the slash as-is
  3140  			out = append(out, s[0])
  3141  			s = s[1:]
  3142  		}
  3143  	}
  3144  
  3145  	return string(out)
  3146  }
  3147  
  3148  func (g *Generator) generateExtension(ext *ExtensionDescriptor) {
  3149  	ccTypeName := ext.DescName()
  3150  
  3151  	extObj := g.ObjectNamed(*ext.Extendee)
  3152  	var extDesc *Descriptor
  3153  	if id, ok := extObj.(*ImportedDescriptor); ok {
  3154  		// This is extending a publicly imported message.
  3155  		// We need the underlying type for goTag.
  3156  		extDesc = id.o.(*Descriptor)
  3157  	} else {
  3158  		extDesc = extObj.(*Descriptor)
  3159  	}
  3160  	extendedType := "*" + g.TypeName(extObj) // always use the original
  3161  	field := ext.FieldDescriptorProto
  3162  	fieldType, wireType := g.GoType(ext.parent, field)
  3163  	tag := g.goTag(extDesc, field, wireType)
  3164  	g.RecordTypeUse(*ext.Extendee)
  3165  	if n := ext.FieldDescriptorProto.TypeName; n != nil {
  3166  		// foreign extension type
  3167  		g.RecordTypeUse(*n)
  3168  	}
  3169  
  3170  	typeName := ext.TypeName()
  3171  
  3172  	// Special case for proto2 message sets: If this extension is extending
  3173  	// proto2.bridge.MessageSet, and its final name component is "message_set_extension",
  3174  	// then drop that last component.
  3175  	//
  3176  	// TODO: This should be implemented in the text formatter rather than the generator.
  3177  	// In addition, the situation for when to apply this special case is implemented
  3178  	// differently in other languages:
  3179  	// https://github.com/google/protobuf/blob/aff10976/src/google/protobuf/text_format.cc#L1560
  3180  	if extDesc.GetOptions().GetMessageSetWireFormat() && typeName[len(typeName)-1] == "message_set_extension" {
  3181  		typeName = typeName[:len(typeName)-1]
  3182  	}
  3183  
  3184  	// For text formatting, the package must be exactly what the .proto file declares,
  3185  	// ignoring overrides such as the go_package option, and with no dot/underscore mapping.
  3186  	extName := strings.Join(typeName, ".")
  3187  	if g.file.Package != nil {
  3188  		extName = *g.file.Package + "." + extName
  3189  	}
  3190  
  3191  	g.P("var ", ccTypeName, " = &", g.Pkg["proto"], ".ExtensionDesc{")
  3192  	g.In()
  3193  	g.P("ExtendedType: (", extendedType, ")(nil),")
  3194  	g.P("ExtensionType: (", fieldType, ")(nil),")
  3195  	g.P("Field: ", field.Number, ",")
  3196  	g.P(`Name: "`, extName, `",`)
  3197  	g.P("Tag: ", tag, ",")
  3198  	g.P(`Filename: "`, g.file.GetName(), `",`)
  3199  
  3200  	g.Out()
  3201  	g.P("}")
  3202  	g.P()
  3203  
  3204  	g.addInitf("%s.RegisterExtension(%s)", g.Pkg["proto"], ext.DescName())
  3205  
  3206  	g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var", ""})
  3207  }
  3208  
  3209  func (g *Generator) generateInitFunction() {
  3210  	if len(g.init) == 0 {
  3211  		return
  3212  	}
  3213  	g.P("func init() {")
  3214  	g.In()
  3215  	for _, l := range g.init {
  3216  		g.P(l)
  3217  	}
  3218  	g.Out()
  3219  	g.P("}")
  3220  	g.init = nil
  3221  }
  3222  
  3223  func (g *Generator) generateFileDescriptor(file *FileDescriptor) {
  3224  	// Make a copy and trim source_code_info data.
  3225  	// TODO: Trim this more when we know exactly what we need.
  3226  	pb := proto.Clone(file.FileDescriptorProto).(*descriptor.FileDescriptorProto)
  3227  	pb.SourceCodeInfo = nil
  3228  
  3229  	b, err := proto.Marshal(pb)
  3230  	if err != nil {
  3231  		g.Fail(err.Error())
  3232  	}
  3233  
  3234  	var buf bytes.Buffer
  3235  	w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
  3236  	w.Write(b)
  3237  	w.Close()
  3238  	b = buf.Bytes()
  3239  
  3240  	v := file.VarName()
  3241  	g.P()
  3242  	g.P("func init() { ", g.Pkg["proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ") }")
  3243  	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
  3244  		g.P("func init() { ", g.Pkg["golang_proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ") }")
  3245  	}
  3246  	g.P("var ", v, " = []byte{")
  3247  	g.In()
  3248  	g.P("// ", len(b), " bytes of a gzipped FileDescriptorProto")
  3249  	for len(b) > 0 {
  3250  		n := 16
  3251  		if n > len(b) {
  3252  			n = len(b)
  3253  		}
  3254  
  3255  		s := ""
  3256  		for _, c := range b[:n] {
  3257  			s += fmt.Sprintf("0x%02x,", c)
  3258  		}
  3259  		g.P(s)
  3260  
  3261  		b = b[n:]
  3262  	}
  3263  	g.Out()
  3264  	g.P("}")
  3265  }
  3266  
  3267  func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) {
  3268  	// // We always print the full (proto-world) package name here.
  3269  	pkg := enum.File().GetPackage()
  3270  	if pkg != "" {
  3271  		pkg += "."
  3272  	}
  3273  	// The full type name
  3274  	typeName := enum.TypeName()
  3275  	// The full type name, CamelCased.
  3276  	ccTypeName := CamelCaseSlice(typeName)
  3277  	g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["proto"], pkg+ccTypeName, ccTypeName)
  3278  	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
  3279  		g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["golang_proto"], pkg+ccTypeName, ccTypeName)
  3280  	}
  3281  }
  3282  
  3283  // And now lots of helper functions.
  3284  
  3285  // Is c an ASCII lower-case letter?
  3286  func isASCIILower(c byte) bool {
  3287  	return 'a' <= c && c <= 'z'
  3288  }
  3289  
  3290  // Is c an ASCII digit?
  3291  func isASCIIDigit(c byte) bool {
  3292  	return '0' <= c && c <= '9'
  3293  }
  3294  
  3295  // CamelCase returns the CamelCased name.
  3296  // If there is an interior underscore followed by a lower case letter,
  3297  // drop the underscore and convert the letter to upper case.
  3298  // There is a remote possibility of this rewrite causing a name collision,
  3299  // but it's so remote we're prepared to pretend it's nonexistent - since the
  3300  // C++ generator lowercases names, it's extremely unlikely to have two fields
  3301  // with different capitalizations.
  3302  // In short, _my_field_name_2 becomes XMyFieldName_2.
  3303  func CamelCase(s string) string {
  3304  	if s == "" {
  3305  		return ""
  3306  	}
  3307  	t := make([]byte, 0, 32)
  3308  	i := 0
  3309  	if s[0] == '_' {
  3310  		// Need a capital letter; drop the '_'.
  3311  		t = append(t, 'X')
  3312  		i++
  3313  	}
  3314  	// Invariant: if the next letter is lower case, it must be converted
  3315  	// to upper case.
  3316  	// That is, we process a word at a time, where words are marked by _ or
  3317  	// upper case letter. Digits are treated as words.
  3318  	for ; i < len(s); i++ {
  3319  		c := s[i]
  3320  		if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
  3321  			continue // Skip the underscore in s.
  3322  		}
  3323  		if isASCIIDigit(c) {
  3324  			t = append(t, c)
  3325  			continue
  3326  		}
  3327  		// Assume we have a letter now - if not, it's a bogus identifier.
  3328  		// The next word is a sequence of characters that must start upper case.
  3329  		if isASCIILower(c) {
  3330  			c ^= ' ' // Make it a capital letter.
  3331  		}
  3332  		t = append(t, c) // Guaranteed not lower case.
  3333  		// Accept lower case sequence that follows.
  3334  		for i+1 < len(s) && isASCIILower(s[i+1]) {
  3335  			i++
  3336  			t = append(t, s[i])
  3337  		}
  3338  	}
  3339  	return string(t)
  3340  }
  3341  
  3342  // CamelCaseSlice is like CamelCase, but the argument is a slice of strings to
  3343  // be joined with "_".
  3344  func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
  3345  
  3346  // dottedSlice turns a sliced name into a dotted name.
  3347  func dottedSlice(elem []string) string { return strings.Join(elem, ".") }
  3348  
  3349  // Is this field optional?
  3350  func isOptional(field *descriptor.FieldDescriptorProto) bool {
  3351  	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL
  3352  }
  3353  
  3354  // Is this field required?
  3355  func isRequired(field *descriptor.FieldDescriptorProto) bool {
  3356  	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED
  3357  }
  3358  
  3359  // Is this field repeated?
  3360  func isRepeated(field *descriptor.FieldDescriptorProto) bool {
  3361  	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
  3362  }
  3363  
  3364  // Is this field a scalar numeric type?
  3365  func IsScalar(field *descriptor.FieldDescriptorProto) bool {
  3366  	if field.Type == nil {
  3367  		return false
  3368  	}
  3369  	switch *field.Type {
  3370  	case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
  3371  		descriptor.FieldDescriptorProto_TYPE_FLOAT,
  3372  		descriptor.FieldDescriptorProto_TYPE_INT64,
  3373  		descriptor.FieldDescriptorProto_TYPE_UINT64,
  3374  		descriptor.FieldDescriptorProto_TYPE_INT32,
  3375  		descriptor.FieldDescriptorProto_TYPE_FIXED64,
  3376  		descriptor.FieldDescriptorProto_TYPE_FIXED32,
  3377  		descriptor.FieldDescriptorProto_TYPE_BOOL,
  3378  		descriptor.FieldDescriptorProto_TYPE_UINT32,
  3379  		descriptor.FieldDescriptorProto_TYPE_ENUM,
  3380  		descriptor.FieldDescriptorProto_TYPE_SFIXED32,
  3381  		descriptor.FieldDescriptorProto_TYPE_SFIXED64,
  3382  		descriptor.FieldDescriptorProto_TYPE_SINT32,
  3383  		descriptor.FieldDescriptorProto_TYPE_SINT64:
  3384  		return true
  3385  	default:
  3386  		return false
  3387  	}
  3388  }
  3389  
  3390  // badToUnderscore is the mapping function used to generate Go names from package names,
  3391  // which can be dotted in the input .proto file.  It replaces non-identifier characters such as
  3392  // dot or dash with underscore.
  3393  func badToUnderscore(r rune) rune {
  3394  	if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
  3395  		return r
  3396  	}
  3397  	return '_'
  3398  }
  3399  
  3400  // baseName returns the last path element of the name, with the last dotted suffix removed.
  3401  func baseName(name string) string {
  3402  	// First, find the last element
  3403  	if i := strings.LastIndex(name, "/"); i >= 0 {
  3404  		name = name[i+1:]
  3405  	}
  3406  	// Now drop the suffix
  3407  	if i := strings.LastIndex(name, "."); i >= 0 {
  3408  		name = name[0:i]
  3409  	}
  3410  	return name
  3411  }
  3412  
  3413  // The SourceCodeInfo message describes the location of elements of a parsed
  3414  // .proto file by way of a "path", which is a sequence of integers that
  3415  // describe the route from a FileDescriptorProto to the relevant submessage.
  3416  // The path alternates between a field number of a repeated field, and an index
  3417  // into that repeated field. The constants below define the field numbers that
  3418  // are used.
  3419  //
  3420  // See descriptor.proto for more information about this.
  3421  const (
  3422  	// tag numbers in FileDescriptorProto
  3423  	packagePath = 2 // package
  3424  	messagePath = 4 // message_type
  3425  	enumPath    = 5 // enum_type
  3426  	// tag numbers in DescriptorProto
  3427  	messageFieldPath   = 2 // field
  3428  	messageMessagePath = 3 // nested_type
  3429  	messageEnumPath    = 4 // enum_type
  3430  	messageOneofPath   = 8 // oneof_decl
  3431  	// tag numbers in EnumDescriptorProto
  3432  	enumValuePath = 2 // value
  3433  )
  3434  
  3435  var supportTypeAliases bool
  3436  
  3437  func init() {
  3438  	for _, tag := range build.Default.ReleaseTags {
  3439  		if tag == "go1.9" {
  3440  			supportTypeAliases = true
  3441  			return
  3442  		}
  3443  	}
  3444  }
  3445  

View as plain text