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*/
42package generator
43
44import (
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).
76const generatedCodeVersion = 3
77
78// A Plugin provides functionality to add to the output during Go code generation,
79// such as to produce RPC stubs.
80type 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
94type pluginSlice []Plugin
95
96func (ps pluginSlice) Len() int {
97	return len(ps)
98}
99
100func (ps pluginSlice) Less(i, j int) bool {
101	return ps[i].Name() < ps[j].Name()
102}
103
104func (ps pluginSlice) Swap(i, j int) {
105	ps[i], ps[j] = ps[j], ps[i]
106}
107
108var 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.
112func 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".
117type GoImportPath string
118
119func (p GoImportPath) String() string { return strconv.Quote(string(p)) }
120
121// A GoPackageName is the name of a Go package. e.g., "protobuf".
122type 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.
131type 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.
136func (c *common) GoImportPath() GoImportPath {
137	return c.file.importPath
138}
139
140func (c *common) File() *FileDescriptor { return c.file }
141
142func fileIsProto3(file *descriptor.FileDescriptorProto) bool {
143	return file.GetSyntax() == "proto3"
144}
145
146func (c *common) proto3() bool { return fileIsProto3(c.file.FileDescriptorProto) }
147
148// Descriptor represents a protocol buffer message.
149type 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.
164func (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
181func (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.
187type 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.
198func (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.
218func (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... .
229func (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.
239func (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.
251type 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.
259func (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.
274func (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.
285type ImportedDescriptor struct {
286	common
287	o Object
288}
289
290func (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.
295type 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.
319func (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).
328func (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.
347func (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
370func (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.
375type 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
381type messageSymbol struct {
382	sym                         string
383	hasExtensions, isMessageSet bool
384	oneofTypes                  []string
385}
386
387type 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
394func (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
402type enumSymbol struct {
403	name   string
404	proto3 bool // Whether this came from a proto3 file.
405}
406
407func (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
415type 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
421func (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.
430type 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.
437type 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
471type pathType int
472
473const (
474	pathTypeImport pathType = iota
475	pathTypeSourceRelative
476)
477
478// New creates a new generator and allocates the request and response protobufs.
479func 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.
490func (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.
497func (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.
506func (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.
573func (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.
582func (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.
603func (g *Generator) AddImport(importPath GoImportPath) GoPackageName {
604	g.addedImports[importPath] = true
605	return g.GoPackageName(importPath)
606}
607
608var 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.
616func 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
625var 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
653var 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
695func 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.
710func (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.
721func (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.
779func (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
840func (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
855func (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
871func 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
908func 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
917func 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
927func 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
943func 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.
959func 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.
968func 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
987func 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.
1004func (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.
1027func (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.
1036type 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.
1044func 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.
1049func (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).
1082func (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.
1120func (g *Generator) addInitf(stmt string, a ...interface{}) {
1121	g.init = append(g.init, fmt.Sprintf(stmt, a...))
1122}
1123
1124func (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.
1134func (g *Generator) In() { g.indent += "\t" }
1135
1136// Out unindents the output one tab stop.
1137func (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.
1144func (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.
1181func (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.
1189func (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
1298func (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.
1314var 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.
1320func (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
1332func (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.
1349func (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
1358func (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.
1363func (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
1373func (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
1448func (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.
1467func (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.
1610func (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
1778func 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.
1809func (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
1814func (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.
1917type 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
1929func (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
1998func (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.
2014var 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.
2032var 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"
2054func (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"
2128func (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.
2145type 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.
2151type 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".
2162func (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".
2167func (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.
2172type 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).
2183func (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.
2188func (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.
2203func (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".
2208func (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".
2213func (f *simpleField) getProtoTypeName() string {
2214	return f.protoTypeName
2215}
2216
2217// getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64.
2218func (f *simpleField) getProtoType() descriptor.FieldDescriptorProto_Type {
2219	return f.protoType
2220}
2221
2222func (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.
2227type 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
2240func (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".
2245func (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".
2250func (f *oneofSubField) getProtoTypeName() string {
2251	return f.protoTypeName
2252}
2253
2254// getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64.
2255func (f *oneofSubField) getProtoType() descriptor.FieldDescriptorProto_Type {
2256	return f.protoType
2257}
2258
2259func (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.
2265type 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).
2272func (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.
2282func (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.
2300func (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).
2305type 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).
2312type 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.
2323func (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.
2424func (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.
2488func (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.
2512func (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
2537func (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.
2609func (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.
2630func (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.
2638func (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.
2645func (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.
2782func (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
3071type byTypeName []*descriptor.FieldDescriptorProto
3072
3073func (a byTypeName) Len() int           { return len(a) }
3074func (a byTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
3075func (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.
3078func 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
3087var 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.
3094func 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
3148func (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
3209func (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
3223func (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
3267func (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?
3286func isASCIILower(c byte) bool {
3287	return 'a' <= c && c <= 'z'
3288}
3289
3290// Is c an ASCII digit?
3291func 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.
3303func 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 "_".
3344func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
3345
3346// dottedSlice turns a sliced name into a dotted name.
3347func dottedSlice(elem []string) string { return strings.Join(elem, ".") }
3348
3349// Is this field optional?
3350func isOptional(field *descriptor.FieldDescriptorProto) bool {
3351	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL
3352}
3353
3354// Is this field required?
3355func isRequired(field *descriptor.FieldDescriptorProto) bool {
3356	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED
3357}
3358
3359// Is this field repeated?
3360func 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?
3365func 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.
3393func 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.
3401func 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.
3421const (
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
3435var supportTypeAliases bool
3436
3437func init() {
3438	for _, tag := range build.Default.ReleaseTags {
3439		if tag == "go1.9" {
3440			supportTypeAliases = true
3441			return
3442		}
3443	}
3444}
3445