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