PageRenderTime 59ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/protoc-gen-go/generator/generator.go

https://code.google.com/p/goprotobuf/
Go | 1478 lines | 1077 code | 129 blank | 272 comment | 234 complexity | 0332d03da0924c1a92cea59152499719 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Go support for Protocol Buffers - Google's data interchange format
  2. //
  3. // Copyright 2010 Google Inc. All rights reserved.
  4. // http://code.google.com/p/goprotobuf/
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions are
  8. // met:
  9. //
  10. // * Redistributions of source code must retain the above copyright
  11. // notice, this list of conditions and the following disclaimer.
  12. // * Redistributions in binary form must reproduce the above
  13. // copyright notice, this list of conditions and the following disclaimer
  14. // in the documentation and/or other materials provided with the
  15. // distribution.
  16. // * Neither the name of Google Inc. nor the names of its
  17. // contributors may be used to endorse or promote products derived from
  18. // this software without specific prior written permission.
  19. //
  20. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. /*
  32. The code generator for the plugin for the Google protocol buffer compiler.
  33. It generates Go code from the protocol buffer description files read by the
  34. main routine.
  35. */
  36. package generator
  37. import (
  38. "bytes"
  39. "fmt"
  40. "go/parser"
  41. "go/printer"
  42. "go/token"
  43. "log"
  44. "os"
  45. "path"
  46. "strconv"
  47. "strings"
  48. "code.google.com/p/goprotobuf/proto"
  49. descriptor "code.google.com/p/goprotobuf/protoc-gen-go/descriptor"
  50. plugin "code.google.com/p/goprotobuf/protoc-gen-go/plugin"
  51. )
  52. // A Plugin provides functionality to add to the output during Go code generation,
  53. // such as to produce RPC stubs.
  54. type Plugin interface {
  55. // Name identifies the plugin.
  56. Name() string
  57. // Init is called once after data structures are built but before
  58. // code generation begins.
  59. Init(g *Generator)
  60. // Generate produces the code generated by the plugin for this file,
  61. // except for the imports, by calling the generator's methods P, In, and Out.
  62. Generate(file *FileDescriptor)
  63. // GenerateImports produces the import declarations for this file.
  64. // It is called after Generate.
  65. GenerateImports(file *FileDescriptor)
  66. }
  67. var plugins []Plugin
  68. // RegisterPlugin installs a (second-order) plugin to be run when the Go output is generated.
  69. // It is typically called during initialization.
  70. func RegisterPlugin(p Plugin) {
  71. plugins = append(plugins, p)
  72. }
  73. // Each type we import as a protocol buffer (other than FileDescriptorProto) needs
  74. // a pointer to the FileDescriptorProto that represents it. These types achieve that
  75. // wrapping by placing each Proto inside a struct with the pointer to its File. The
  76. // structs have the same names as their contents, with "Proto" removed.
  77. // FileDescriptor is used to store the things that it points to.
  78. // The file and package name method are common to messages and enums.
  79. type common struct {
  80. file *descriptor.FileDescriptorProto // File this object comes from.
  81. }
  82. // PackageName is name in the package clause in the generated file.
  83. func (c *common) PackageName() string { return uniquePackageOf(c.file) }
  84. func (c *common) File() *descriptor.FileDescriptorProto { return c.file }
  85. // Descriptor represents a protocol buffer message.
  86. type Descriptor struct {
  87. common
  88. *descriptor.DescriptorProto
  89. parent *Descriptor // The containing message, if any.
  90. nested []*Descriptor // Inner messages, if any.
  91. ext []*ExtensionDescriptor // Extensions, if any.
  92. typename []string // Cached typename vector.
  93. }
  94. // TypeName returns the elements of the dotted type name.
  95. // The package name is not part of this name.
  96. func (d *Descriptor) TypeName() []string {
  97. if d.typename != nil {
  98. return d.typename
  99. }
  100. n := 0
  101. for parent := d; parent != nil; parent = parent.parent {
  102. n++
  103. }
  104. s := make([]string, n, n)
  105. for parent := d; parent != nil; parent = parent.parent {
  106. n--
  107. s[n] = proto.GetString(parent.Name)
  108. }
  109. d.typename = s
  110. return s
  111. }
  112. // EnumDescriptor describes an enum. If it's at top level, its parent will be nil.
  113. // Otherwise it will be the descriptor of the message in which it is defined.
  114. type EnumDescriptor struct {
  115. common
  116. *descriptor.EnumDescriptorProto
  117. parent *Descriptor // The containing message, if any.
  118. typename []string // Cached typename vector.
  119. }
  120. // TypeName returns the elements of the dotted type name.
  121. // The package name is not part of this name.
  122. func (e *EnumDescriptor) TypeName() (s []string) {
  123. if e.typename != nil {
  124. return e.typename
  125. }
  126. name := proto.GetString(e.Name)
  127. if e.parent == nil {
  128. s = make([]string, 1)
  129. } else {
  130. pname := e.parent.TypeName()
  131. s = make([]string, len(pname)+1)
  132. copy(s, pname)
  133. }
  134. s[len(s)-1] = name
  135. e.typename = s
  136. return s
  137. }
  138. // Everything but the last element of the full type name, CamelCased.
  139. // The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... .
  140. func (e *EnumDescriptor) prefix() string {
  141. typeName := e.TypeName()
  142. ccPrefix := CamelCaseSlice(typeName[0:len(typeName)-1]) + "_"
  143. if e.parent == nil {
  144. // If the enum is not part of a message, the prefix is just the type name.
  145. ccPrefix = CamelCase(*e.Name) + "_"
  146. }
  147. return ccPrefix
  148. }
  149. // The integer value of the named constant in this enumerated type.
  150. func (e *EnumDescriptor) integerValueAsString(name string) string {
  151. for _, c := range e.Value {
  152. if proto.GetString(c.Name) == name {
  153. return fmt.Sprint(proto.GetInt32(c.Number))
  154. }
  155. }
  156. log.Fatal("cannot find value for enum constant")
  157. return ""
  158. }
  159. // ExtensionDescriptor describes an extension. If it's at top level, its parent will be nil.
  160. // Otherwise it will be the descriptor of the message in which it is defined.
  161. type ExtensionDescriptor struct {
  162. common
  163. *descriptor.FieldDescriptorProto
  164. parent *Descriptor // The containing message, if any.
  165. }
  166. // TypeName returns the elements of the dotted type name.
  167. // The package name is not part of this name.
  168. func (e *ExtensionDescriptor) TypeName() (s []string) {
  169. name := proto.GetString(e.Name)
  170. if e.parent == nil {
  171. // top-level extension
  172. s = make([]string, 1)
  173. } else {
  174. pname := e.parent.TypeName()
  175. s = make([]string, len(pname)+1)
  176. copy(s, pname)
  177. }
  178. s[len(s)-1] = name
  179. return s
  180. }
  181. // DescName returns the variable name used for the generated descriptor.
  182. func (e *ExtensionDescriptor) DescName() string {
  183. // The full type name.
  184. typeName := e.TypeName()
  185. // Each scope of the extension is individually CamelCased, and all are joined with "_" with an "E_" prefix.
  186. for i, s := range typeName {
  187. typeName[i] = CamelCase(s)
  188. }
  189. return "E_" + strings.Join(typeName, "_")
  190. }
  191. // ImportedDescriptor describes a type that has been publicly imported from another file.
  192. type ImportedDescriptor struct {
  193. common
  194. o Object
  195. }
  196. func (id *ImportedDescriptor) TypeName() []string { return id.o.TypeName() }
  197. // FileDescriptor describes an protocol buffer descriptor file (.proto).
  198. // It includes slices of all the messages and enums defined within it.
  199. // Those slices are constructed by WrapTypes.
  200. type FileDescriptor struct {
  201. *descriptor.FileDescriptorProto
  202. desc []*Descriptor // All the messages defined in this file.
  203. enum []*EnumDescriptor // All the enums defined in this file.
  204. ext []*ExtensionDescriptor // All the top-level extensions defined in this file.
  205. imp []*ImportedDescriptor // All types defined in files publicly imported by this file.
  206. // The full list of symbols that are exported,
  207. // as a map from the exported object to its symbols.
  208. // This is used for supporting public imports.
  209. exported map[Object][]Symbol
  210. }
  211. // PackageName is the package name we'll use in the generated code to refer to this file.
  212. func (d *FileDescriptor) PackageName() string { return uniquePackageOf(d.FileDescriptorProto) }
  213. // The package named defined in the input for this file, possibly dotted.
  214. // If the file does not define a package, use the base of the file name.
  215. func (d *FileDescriptor) originalPackageName() string {
  216. // Does the file have a package clause?
  217. if pkg := proto.GetString(d.Package); pkg != "" {
  218. return pkg
  219. }
  220. // Use the file base name.
  221. return BaseName(proto.GetString(d.Name))
  222. }
  223. func (d *FileDescriptor) addExport(obj Object, symbol Symbol) {
  224. d.exported[obj] = append(d.exported[obj], symbol)
  225. }
  226. // Symbol is an interface representing an exported Go symbol.
  227. type Symbol interface {
  228. // GenerateAlias should generate an appropriate alias
  229. // for the symbol from the named package.
  230. GenerateAlias(g *Generator, pkg string)
  231. }
  232. type messageSymbol struct {
  233. sym string
  234. hasExtensions, isMessageSet bool
  235. }
  236. func (ms messageSymbol) GenerateAlias(g *Generator, pkg string) {
  237. remoteSym := pkg + "." + ms.sym
  238. g.P("type ", ms.sym, " ", remoteSym)
  239. g.P("func (this *", ms.sym, ") Reset() { (*", remoteSym, ")(this).Reset() }")
  240. g.P("func (this *", ms.sym, ") String() string { return (*", remoteSym, ")(this).String() }")
  241. if ms.hasExtensions {
  242. g.P("func (*", ms.sym, ") ExtensionRangeArray() []", g.ProtoPkg, ".ExtensionRange ",
  243. "{ return (*", remoteSym, ")(nil).ExtensionRangeArray() }")
  244. g.P("func (this *", ms.sym, ") ExtensionMap() map[int32]", g.ProtoPkg, ".Extension ",
  245. "{ return (*", remoteSym, ")(this).ExtensionMap() }")
  246. if ms.isMessageSet {
  247. g.P("func (this *", ms.sym, ") Marshal() ([]byte, error) ",
  248. "{ return (*", remoteSym, ")(this).Marshal() }")
  249. g.P("func (this *", ms.sym, ") Unmarshal(buf []byte) error ",
  250. "{ return (*", remoteSym, ")(this).Unmarshal(buf) }")
  251. }
  252. }
  253. }
  254. type enumSymbol string
  255. func (es enumSymbol) GenerateAlias(g *Generator, pkg string) {
  256. s := string(es)
  257. g.P("type ", s, " ", pkg, ".", s)
  258. g.P("var ", s, "_name = ", pkg, ".", s, "_name")
  259. g.P("var ", s, "_value = ", pkg, ".", s, "_value")
  260. g.P("func New", s, "(x ", s, ") *", s, " { e := ", s, "(x); return &e }")
  261. }
  262. type constOrVarSymbol struct {
  263. sym string
  264. typ string // either "const" or "var"
  265. }
  266. func (cs constOrVarSymbol) GenerateAlias(g *Generator, pkg string) {
  267. g.P(cs.typ, " ", cs.sym, " = ", pkg, ".", cs.sym)
  268. }
  269. // Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects.
  270. type Object interface {
  271. PackageName() string // The name we use in our output (a_b_c), possibly renamed for uniqueness.
  272. TypeName() []string
  273. File() *descriptor.FileDescriptorProto
  274. }
  275. // Each package name we generate must be unique. The package we're generating
  276. // gets its own name but every other package must have a unique name that does
  277. // not conflict in the code we generate. These names are chosen globally (although
  278. // they don't have to be, it simplifies things to do them globally).
  279. func uniquePackageOf(fd *descriptor.FileDescriptorProto) string {
  280. s, ok := uniquePackageName[fd]
  281. if !ok {
  282. log.Fatal("internal error: no package name defined for", proto.GetString(fd.Name))
  283. }
  284. return s
  285. }
  286. // Generator is the type whose methods generate the output, stored in the associated response structure.
  287. type Generator struct {
  288. *bytes.Buffer
  289. Request *plugin.CodeGeneratorRequest // The input.
  290. Response *plugin.CodeGeneratorResponse // The output.
  291. Param map[string]string // Command-line parameters.
  292. ImportPrefix string // String to prefix to imported package file names.
  293. ImportMap map[string]string // Mapping from import name to generated name
  294. ProtoPkg string // The name under which we import the library's package proto.
  295. packageName string // What we're calling ourselves.
  296. allFiles []*FileDescriptor // All files in the tree
  297. genFiles []*FileDescriptor // Those files we will generate output for.
  298. file *FileDescriptor // The file we are compiling now.
  299. usedPackages map[string]bool // Names of packages used in current file.
  300. typeNameToObject map[string]Object // Key is a fully-qualified name in input syntax.
  301. indent string
  302. }
  303. // New creates a new generator and allocates the request and response protobufs.
  304. func New() *Generator {
  305. g := new(Generator)
  306. g.Buffer = new(bytes.Buffer)
  307. g.Request = new(plugin.CodeGeneratorRequest)
  308. g.Response = new(plugin.CodeGeneratorResponse)
  309. return g
  310. }
  311. // Error reports a problem, including an error, and exits the program.
  312. func (g *Generator) Error(err error, msgs ...string) {
  313. s := strings.Join(msgs, " ") + ":" + err.Error()
  314. log.Println("protoc-gen-go: error:", s)
  315. g.Response.Error = proto.String(s)
  316. os.Exit(1)
  317. }
  318. // Fail reports a problem and exits the program.
  319. func (g *Generator) Fail(msgs ...string) {
  320. s := strings.Join(msgs, " ")
  321. log.Println("protoc-gen-go: error:", s)
  322. g.Response.Error = proto.String(s)
  323. os.Exit(1)
  324. }
  325. // CommandLineParameters breaks the comma-separated list of key=value pairs
  326. // in the parameter (a member of the request protobuf) into a key/value map.
  327. // It then sets file name mappings defined by those entries.
  328. func (g *Generator) CommandLineParameters(parameter string) {
  329. g.Param = make(map[string]string)
  330. for _, p := range strings.Split(parameter, ",") {
  331. if i := strings.Index(p, "="); i < 0 {
  332. g.Param[p] = ""
  333. } else {
  334. g.Param[p[0:i]] = p[i+1:]
  335. }
  336. }
  337. g.ImportMap = make(map[string]string)
  338. for k, v := range g.Param {
  339. if k == "import_prefix" {
  340. g.ImportPrefix = v
  341. } else if len(k) > 0 && k[0] == 'M' {
  342. g.ImportMap[k[1:]] = v
  343. }
  344. }
  345. }
  346. // DefaultPackageName returns the package name printed for the object.
  347. // If its file is in a different package, it returns the package name we're using for this file, plus ".".
  348. // Otherwise it returns the empty string.
  349. func (g *Generator) DefaultPackageName(obj Object) string {
  350. pkg := obj.PackageName()
  351. if pkg == g.packageName {
  352. return ""
  353. }
  354. return pkg + "."
  355. }
  356. // For each input file, the unique package name to use, underscored.
  357. var uniquePackageName = make(map[*descriptor.FileDescriptorProto]string)
  358. // Package names already registered. Key is the name from the .proto file;
  359. // value is the name that appears in the generated code.
  360. var pkgNamesInUse = make(map[string]bool)
  361. // Create and remember a guaranteed unique package name for this file descriptor.
  362. // Pkg is the candidate name. If f is nil, it's a builtin package like "proto" and
  363. // has no file descriptor.
  364. func RegisterUniquePackageName(pkg string, f *FileDescriptor) string {
  365. // Convert dots to underscores before finding a unique alias.
  366. pkg = strings.Map(DotToUnderscore, pkg)
  367. for i, orig := 1, pkg; pkgNamesInUse[pkg]; i++ {
  368. // It's a duplicate; must rename.
  369. pkg = orig + strconv.Itoa(i)
  370. }
  371. // Install it.
  372. pkgNamesInUse[pkg] = true
  373. if f != nil {
  374. uniquePackageName[f.FileDescriptorProto] = pkg
  375. }
  376. return pkg
  377. }
  378. // SetPackageNames sets the package name for this run.
  379. // The package name must agree across all files being generated.
  380. // It also defines unique package names for all imported files.
  381. func (g *Generator) SetPackageNames() {
  382. // Register the name for this package. It will be the first name
  383. // registered so is guaranteed to be unmodified.
  384. pkg := g.genFiles[0].originalPackageName()
  385. g.packageName = RegisterUniquePackageName(pkg, g.genFiles[0])
  386. // Register the proto package name. It might collide with the
  387. // name of a package we import.
  388. g.ProtoPkg = RegisterUniquePackageName("proto", nil)
  389. // Verify that we are generating output for a single package.
  390. for _, f := range g.genFiles {
  391. thisPkg := f.originalPackageName()
  392. if thisPkg != pkg {
  393. g.Fail("inconsistent package names:", thisPkg, pkg)
  394. }
  395. }
  396. AllFiles:
  397. for _, f := range g.allFiles {
  398. for _, genf := range g.genFiles {
  399. if f == genf {
  400. // In this package already.
  401. uniquePackageName[f.FileDescriptorProto] = g.packageName
  402. continue AllFiles
  403. }
  404. }
  405. // The file is a dependency, so we want to ignore its go_package option
  406. // because that is only relevant for its specific generated output.
  407. pkg := proto.GetString(f.Package)
  408. if pkg == "" {
  409. pkg = BaseName(*f.Name)
  410. }
  411. RegisterUniquePackageName(pkg, f)
  412. }
  413. }
  414. // WrapTypes walks the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos
  415. // and FileDescriptorProtos into file-referenced objects within the Generator.
  416. // It also creates the list of files to generate and so should be called before GenerateAllFiles.
  417. func (g *Generator) WrapTypes() {
  418. g.allFiles = make([]*FileDescriptor, len(g.Request.ProtoFile))
  419. for i, f := range g.Request.ProtoFile {
  420. // We must wrap the descriptors before we wrap the enums
  421. descs := wrapDescriptors(f)
  422. g.buildNestedDescriptors(descs)
  423. enums := wrapEnumDescriptors(f, descs)
  424. exts := wrapExtensions(f)
  425. imps := wrapImported(f, g)
  426. g.allFiles[i] = &FileDescriptor{
  427. FileDescriptorProto: f,
  428. desc: descs,
  429. enum: enums,
  430. ext: exts,
  431. imp: imps,
  432. exported: make(map[Object][]Symbol),
  433. }
  434. }
  435. g.genFiles = make([]*FileDescriptor, len(g.Request.FileToGenerate))
  436. FindFiles:
  437. for i, fileName := range g.Request.FileToGenerate {
  438. // Search the list. This algorithm is n^2 but n is tiny.
  439. for _, file := range g.allFiles {
  440. if fileName == proto.GetString(file.Name) {
  441. g.genFiles[i] = file
  442. continue FindFiles
  443. }
  444. }
  445. g.Fail("could not find file named", fileName)
  446. }
  447. g.Response.File = make([]*plugin.CodeGeneratorResponse_File, len(g.genFiles))
  448. }
  449. // Scan the descriptors in this file. For each one, build the slice of nested descriptors
  450. func (g *Generator) buildNestedDescriptors(descs []*Descriptor) {
  451. for _, desc := range descs {
  452. if len(desc.NestedType) != 0 {
  453. desc.nested = make([]*Descriptor, len(desc.NestedType))
  454. n := 0
  455. for _, nest := range descs {
  456. if nest.parent == desc {
  457. desc.nested[n] = nest
  458. n++
  459. }
  460. }
  461. if n != len(desc.NestedType) {
  462. g.Fail("internal error: nesting failure for", proto.GetString(desc.Name))
  463. }
  464. }
  465. }
  466. }
  467. // Construct the Descriptor and add it to the slice
  468. func addDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*Descriptor {
  469. d := &Descriptor{common{file}, desc, parent, nil, nil, nil}
  470. d.ext = make([]*ExtensionDescriptor, len(desc.Extension))
  471. for i, field := range desc.Extension {
  472. d.ext[i] = &ExtensionDescriptor{common{file}, field, d}
  473. }
  474. return append(sl, d)
  475. }
  476. // Return a slice of all the Descriptors defined within this file
  477. func wrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor {
  478. sl := make([]*Descriptor, 0, len(file.MessageType)+10)
  479. for _, desc := range file.MessageType {
  480. sl = wrapThisDescriptor(sl, desc, nil, file)
  481. }
  482. return sl
  483. }
  484. // Wrap this Descriptor, recursively
  485. func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*Descriptor {
  486. sl = addDescriptor(sl, desc, parent, file)
  487. me := sl[len(sl)-1]
  488. for _, nested := range desc.NestedType {
  489. sl = wrapThisDescriptor(sl, nested, me, file)
  490. }
  491. return sl
  492. }
  493. // Construct the EnumDescriptor and add it to the slice
  494. func addEnumDescriptor(sl []*EnumDescriptor, desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*EnumDescriptor {
  495. return append(sl, &EnumDescriptor{common{file}, desc, parent, nil})
  496. }
  497. // Return a slice of all the EnumDescriptors defined within this file
  498. func wrapEnumDescriptors(file *descriptor.FileDescriptorProto, descs []*Descriptor) []*EnumDescriptor {
  499. sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
  500. // Top-level enums.
  501. for _, enum := range file.EnumType {
  502. sl = addEnumDescriptor(sl, enum, nil, file)
  503. }
  504. // Enums within messages. Enums within embedded messages appear in the outer-most message.
  505. for _, nested := range descs {
  506. for _, enum := range nested.EnumType {
  507. sl = addEnumDescriptor(sl, enum, nested, file)
  508. }
  509. }
  510. return sl
  511. }
  512. // Return a slice of all the top-level ExtensionDescriptors defined within this file.
  513. func wrapExtensions(file *descriptor.FileDescriptorProto) []*ExtensionDescriptor {
  514. sl := make([]*ExtensionDescriptor, len(file.Extension))
  515. for i, field := range file.Extension {
  516. sl[i] = &ExtensionDescriptor{common{file}, field, nil}
  517. }
  518. return sl
  519. }
  520. // Return a slice of all the types that are publicly imported into this file.
  521. func wrapImported(file *descriptor.FileDescriptorProto, g *Generator) (sl []*ImportedDescriptor) {
  522. for _, index := range file.PublicDependency {
  523. df := g.fileByName(file.Dependency[index])
  524. for _, d := range df.desc {
  525. sl = append(sl, &ImportedDescriptor{common{file}, d})
  526. }
  527. for _, e := range df.enum {
  528. sl = append(sl, &ImportedDescriptor{common{file}, e})
  529. }
  530. for _, ext := range df.ext {
  531. sl = append(sl, &ImportedDescriptor{common{file}, ext})
  532. }
  533. }
  534. return
  535. }
  536. // BuildTypeNameMap builds the map from fully qualified type names to objects.
  537. // The key names for the map come from the input data, which puts a period at the beginning.
  538. // It should be called after SetPackageNames and before GenerateAllFiles.
  539. func (g *Generator) BuildTypeNameMap() {
  540. g.typeNameToObject = make(map[string]Object)
  541. for _, f := range g.allFiles {
  542. // The names in this loop are defined by the proto world, not us, so the
  543. // package name may be empty. If so, the dotted package name of X will
  544. // be ".X"; otherwise it will be ".pkg.X".
  545. dottedPkg := "." + proto.GetString(f.Package)
  546. if dottedPkg != "." {
  547. dottedPkg += "."
  548. }
  549. for _, enum := range f.enum {
  550. name := dottedPkg + dottedSlice(enum.TypeName())
  551. g.typeNameToObject[name] = enum
  552. }
  553. for _, desc := range f.desc {
  554. name := dottedPkg + dottedSlice(desc.TypeName())
  555. g.typeNameToObject[name] = desc
  556. }
  557. }
  558. }
  559. // ObjectNamed, given a fully-qualified input type name as it appears in the input data,
  560. // returns the descriptor for the message or enum with that name.
  561. func (g *Generator) ObjectNamed(typeName string) Object {
  562. o, ok := g.typeNameToObject[typeName]
  563. if !ok {
  564. g.Fail("can't find object with type", typeName)
  565. }
  566. // If the file of this object isn't a direct dependency of the current file,
  567. // or in the current file, then this object has been publicly imported into
  568. // a dependency of the current file.
  569. // We should return the ImportedDescriptor object for it instead.
  570. direct := *o.File().Name == *g.file.Name
  571. if !direct {
  572. for _, dep := range g.file.Dependency {
  573. if *g.fileByName(dep).Name == *o.File().Name {
  574. direct = true
  575. break
  576. }
  577. }
  578. }
  579. if !direct {
  580. found := false
  581. Loop:
  582. for _, dep := range g.file.Dependency {
  583. df := g.fileByName(*g.fileByName(dep).Name)
  584. for _, td := range df.imp {
  585. if td.o == o {
  586. // Found it!
  587. o = td
  588. found = true
  589. break Loop
  590. }
  591. }
  592. }
  593. if !found {
  594. log.Printf("protoc-gen-go: WARNING: failed finding publicly imported dependency for %v, used in %v", typeName, *g.file.Name)
  595. }
  596. }
  597. return o
  598. }
  599. // P prints the arguments to the generated output. It handles strings and int32s, plus
  600. // handling indirections because they may be *string, etc.
  601. func (g *Generator) P(str ...interface{}) {
  602. g.WriteString(g.indent)
  603. for _, v := range str {
  604. switch s := v.(type) {
  605. case string:
  606. g.WriteString(s)
  607. case *string:
  608. g.WriteString(*s)
  609. case bool:
  610. g.WriteString(fmt.Sprintf("%t", s))
  611. case *bool:
  612. g.WriteString(fmt.Sprintf("%t", *s))
  613. case *int32:
  614. g.WriteString(fmt.Sprintf("%d", *s))
  615. case float64:
  616. g.WriteString(fmt.Sprintf("%g", s))
  617. case *float64:
  618. g.WriteString(fmt.Sprintf("%g", *s))
  619. default:
  620. g.Fail(fmt.Sprintf("unknown type in printer: %T", v))
  621. }
  622. }
  623. g.WriteByte('\n')
  624. }
  625. // In Indents the output one tab stop.
  626. func (g *Generator) In() { g.indent += "\t" }
  627. // Out unindents the output one tab stop.
  628. func (g *Generator) Out() {
  629. if len(g.indent) > 0 {
  630. g.indent = g.indent[1:]
  631. }
  632. }
  633. // GenerateAllFiles generates the output for all the files we're outputting.
  634. func (g *Generator) GenerateAllFiles() {
  635. // Initialize the plugins
  636. for _, p := range plugins {
  637. p.Init(g)
  638. }
  639. // Generate the output. The generator runs for every file, even the files
  640. // that we don't generate output for, so that we can collate the full list
  641. // of exported symbols to support public imports.
  642. genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles))
  643. for _, file := range g.genFiles {
  644. genFileMap[file] = true
  645. }
  646. i := 0
  647. for _, file := range g.allFiles {
  648. g.Reset()
  649. g.generate(file)
  650. if _, ok := genFileMap[file]; !ok {
  651. continue
  652. }
  653. g.Response.File[i] = new(plugin.CodeGeneratorResponse_File)
  654. g.Response.File[i].Name = proto.String(goFileName(*file.Name))
  655. g.Response.File[i].Content = proto.String(g.String())
  656. i++
  657. }
  658. }
  659. // Run all the plugins associated with the file.
  660. func (g *Generator) runPlugins(file *FileDescriptor) {
  661. for _, p := range plugins {
  662. p.Generate(file)
  663. }
  664. }
  665. // FileOf return the FileDescriptor for this FileDescriptorProto.
  666. func (g *Generator) FileOf(fd *descriptor.FileDescriptorProto) *FileDescriptor {
  667. for _, file := range g.allFiles {
  668. if file.FileDescriptorProto == fd {
  669. return file
  670. }
  671. }
  672. g.Fail("could not find file in table:", proto.GetString(fd.Name))
  673. return nil
  674. }
  675. // Fill the response protocol buffer with the generated output for all the files we're
  676. // supposed to generate.
  677. func (g *Generator) generate(file *FileDescriptor) {
  678. g.file = g.FileOf(file.FileDescriptorProto)
  679. g.usedPackages = make(map[string]bool)
  680. for _, td := range g.file.imp {
  681. g.generateImported(td)
  682. }
  683. for _, enum := range g.file.enum {
  684. g.generateEnum(enum)
  685. }
  686. for _, desc := range g.file.desc {
  687. g.generateMessage(desc)
  688. }
  689. for _, ext := range g.file.ext {
  690. g.generateExtension(ext)
  691. }
  692. g.generateInitFunction()
  693. // Run the plugins before the imports so we know which imports are necessary.
  694. g.runPlugins(file)
  695. // Generate header and imports last, though they appear first in the output.
  696. rem := g.Buffer
  697. g.Buffer = new(bytes.Buffer)
  698. g.generateHeader()
  699. g.generateImports()
  700. g.Write(rem.Bytes())
  701. // Reformat generated code.
  702. fset := token.NewFileSet()
  703. ast, err := parser.ParseFile(fset, "", g, parser.ParseComments)
  704. if err != nil {
  705. g.Fail("bad Go source code was generated:", err.Error())
  706. return
  707. }
  708. g.Reset()
  709. err = (&printer.Config{printer.TabIndent | printer.UseSpaces, 8}).Fprint(g, fset, ast)
  710. if err != nil {
  711. g.Fail("generated Go source code could not be reformatted:", err.Error())
  712. }
  713. }
  714. // Generate the header, including package definition and imports
  715. func (g *Generator) generateHeader() {
  716. g.P("// Code generated by protoc-gen-go from ", Quote(*g.file.Name))
  717. g.P("// DO NOT EDIT!")
  718. g.P()
  719. g.P("package ", g.file.PackageName())
  720. g.P()
  721. }
  722. func (g *Generator) fileByName(filename string) *FileDescriptor {
  723. for _, fd := range g.allFiles {
  724. if proto.GetString(fd.Name) == filename {
  725. return fd
  726. }
  727. }
  728. return nil
  729. }
  730. // weak returns whether the ith import of the current file is a weak import.
  731. func (g *Generator) weak(i int32) bool {
  732. for _, j := range g.file.WeakDependency {
  733. if j == i {
  734. return true
  735. }
  736. }
  737. return false
  738. }
  739. // Generate the header, including package definition and imports
  740. func (g *Generator) generateImports() {
  741. // We almost always need a proto import. Rather than computing when we
  742. // do, which is tricky when there's a plugin, just import it and
  743. // reference it later. The same argument applies to the math package,
  744. // for handling bit patterns for floating-point numbers.
  745. g.P("import " + g.ProtoPkg + " " + Quote(g.ImportPrefix+"code.google.com/p/goprotobuf/proto"))
  746. g.P(`import "math"`)
  747. for i, s := range g.file.Dependency {
  748. fd := g.fileByName(s)
  749. // Do not import our own package.
  750. if fd.PackageName() == g.packageName {
  751. continue
  752. }
  753. filename := goFileName(s)
  754. if substitution, ok := g.ImportMap[s]; ok {
  755. filename = substitution
  756. }
  757. filename = g.ImportPrefix + filename
  758. if strings.HasSuffix(filename, ".go") {
  759. filename = filename[0 : len(filename)-3]
  760. }
  761. // Skip weak imports.
  762. if g.weak(int32(i)) {
  763. g.P("// skipping weak import ", fd.PackageName(), " ", Quote(filename))
  764. continue
  765. }
  766. if _, ok := g.usedPackages[fd.PackageName()]; ok {
  767. g.P("import ", fd.PackageName(), " ", Quote(filename))
  768. } else {
  769. // TODO: Re-enable this when we are more feature-complete.
  770. // For instance, some protos use foreign field extensions, which we don't support.
  771. // Until then, this is just annoying spam.
  772. //log.Printf("protoc-gen-go: discarding unused import from %v: %v", *g.file.Name, s)
  773. g.P("// discarding unused import ", fd.PackageName(), " ", Quote(filename))
  774. }
  775. }
  776. g.P()
  777. // TODO: may need to worry about uniqueness across plugins
  778. for _, p := range plugins {
  779. p.GenerateImports(g.file)
  780. g.P()
  781. }
  782. g.P("// Reference proto and math imports to suppress error if they are not otherwise used.")
  783. g.P("var _ = ", g.ProtoPkg, ".GetString")
  784. g.P("var _ = math.Inf")
  785. g.P()
  786. }
  787. func (g *Generator) generateImported(id *ImportedDescriptor) {
  788. // Don't generate public import symbols for files that we are generating
  789. // code for, since those symbols will already be in this package.
  790. // We can't simply avoid creating the ImportedDescriptor objects,
  791. // because g.genFiles isn't populated at that stage.
  792. tn := id.TypeName()
  793. sn := tn[len(tn)-1]
  794. df := g.FileOf(id.o.File())
  795. filename := *df.Name
  796. for _, fd := range g.genFiles {
  797. if *fd.Name == filename {
  798. g.P("// Ignoring public import of ", sn, " from ", filename)
  799. g.P()
  800. return
  801. }
  802. }
  803. g.P("// ", sn, " from public import ", filename)
  804. g.usedPackages[df.PackageName()] = true
  805. for _, sym := range df.exported[id.o] {
  806. sym.GenerateAlias(g, df.PackageName())
  807. }
  808. g.P()
  809. }
  810. // Generate the enum definitions for this EnumDescriptor.
  811. func (g *Generator) generateEnum(enum *EnumDescriptor) {
  812. // The full type name
  813. typeName := enum.TypeName()
  814. // The full type name, CamelCased.
  815. ccTypeName := CamelCaseSlice(typeName)
  816. ccPrefix := enum.prefix()
  817. g.P("type ", ccTypeName, " int32")
  818. g.file.addExport(enum, enumSymbol(ccTypeName))
  819. g.P("const (")
  820. g.In()
  821. for _, e := range enum.Value {
  822. name := ccPrefix + *e.Name
  823. g.P(name, " ", ccTypeName, " = ", e.Number)
  824. g.file.addExport(enum, constOrVarSymbol{name, "const"})
  825. }
  826. g.Out()
  827. g.P(")")
  828. g.P("var ", ccTypeName, "_name = map[int32]string{")
  829. g.In()
  830. generated := make(map[int32]bool) // avoid duplicate values
  831. for _, e := range enum.Value {
  832. duplicate := ""
  833. if _, present := generated[*e.Number]; present {
  834. duplicate = "// Duplicate value: "
  835. }
  836. g.P(duplicate, e.Number, ": ", Quote(*e.Name), ",")
  837. generated[*e.Number] = true
  838. }
  839. g.Out()
  840. g.P("}")
  841. g.P("var ", ccTypeName, "_value = map[string]int32{")
  842. g.In()
  843. for _, e := range enum.Value {
  844. g.P(Quote(*e.Name), ": ", e.Number, ",")
  845. }
  846. g.Out()
  847. g.P("}")
  848. g.P("func New", ccTypeName, "(x ", ccTypeName, ") *", ccTypeName, " {")
  849. g.In()
  850. g.P("e := ", ccTypeName, "(x)")
  851. g.P("return &e")
  852. g.Out()
  853. g.P("}")
  854. g.P("func (x ", ccTypeName, ") String() string {")
  855. g.In()
  856. g.P("return ", g.ProtoPkg, ".EnumName(", ccTypeName, "_name, int32(x))")
  857. g.Out()
  858. g.P("}")
  859. g.P()
  860. }
  861. // The tag is a string like "varint,2,opt,name=fieldname,def=7" that
  862. // identifies details of the field for the protocol buffer marshaling and unmarshaling
  863. // code. The fields are:
  864. // wire encoding
  865. // protocol tag number
  866. // opt,req,rep for optional, required, or repeated
  867. // packed whether the encoding is "packed" (optional; repeated primitives only)
  868. // name= the original declared name
  869. // enum= the name of the enum type if it is an enum-typed field.
  870. // def= string representation of the default value, if any.
  871. // The default value must be in a representation that can be used at run-time
  872. // to generate the default value. Thus bools become 0 and 1, for instance.
  873. func (g *Generator) goTag(field *descriptor.FieldDescriptorProto, wiretype string) string {
  874. optrepreq := ""
  875. switch {
  876. case isOptional(field):
  877. optrepreq = "opt"
  878. case isRequired(field):
  879. optrepreq = "req"
  880. case isRepeated(field):
  881. optrepreq = "rep"
  882. }
  883. defaultValue := proto.GetString(field.DefaultValue)
  884. if defaultValue != "" {
  885. switch *field.Type {
  886. case descriptor.FieldDescriptorProto_TYPE_BOOL:
  887. if defaultValue == "true" {
  888. defaultValue = "1"
  889. } else {
  890. defaultValue = "0"
  891. }
  892. case descriptor.FieldDescriptorProto_TYPE_STRING,
  893. descriptor.FieldDescriptorProto_TYPE_BYTES:
  894. // Nothing to do. Quoting is done for the whole tag.
  895. case descriptor.FieldDescriptorProto_TYPE_ENUM:
  896. // For enums we need to provide the integer constant.
  897. obj := g.ObjectNamed(proto.GetString(field.TypeName))
  898. enum, ok := obj.(*EnumDescriptor)
  899. if !ok {
  900. g.Fail("enum type inconsistent for", CamelCaseSlice(obj.TypeName()))
  901. }
  902. defaultValue = enum.integerValueAsString(defaultValue)
  903. }
  904. defaultValue = ",def=" + defaultValue
  905. }
  906. enum := ""
  907. if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
  908. // We avoid using obj.PackageName(), because we want to use the
  909. // original (proto-world) package name.
  910. obj := g.ObjectNamed(proto.GetString(field.TypeName))
  911. enum = ",enum="
  912. if pkg := proto.GetString(obj.File().Package); pkg != "" {
  913. enum += pkg + "."
  914. }
  915. enum += CamelCaseSlice(obj.TypeName())
  916. }
  917. packed := ""
  918. if field.Options != nil && proto.GetBool(field.Options.Packed) {
  919. packed = ",packed"
  920. }
  921. fieldName := proto.GetString(field.Name)
  922. name := fieldName
  923. if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
  924. // We must use the type name for groups instead of
  925. // the field name to preserve capitalization.
  926. // type_name in FieldDescriptorProto is fully-qualified,
  927. // but we only want the local part.
  928. name = *field.TypeName
  929. if i := strings.LastIndex(name, "."); i >= 0 {
  930. name = name[i+1:]
  931. }
  932. }
  933. if name == CamelCase(fieldName) {
  934. name = ""
  935. } else {
  936. name = ",name=" + name
  937. }
  938. return Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s",
  939. wiretype,
  940. proto.GetInt32(field.Number),
  941. optrepreq,
  942. packed,
  943. name,
  944. enum,
  945. defaultValue))
  946. }
  947. func needsStar(typ descriptor.FieldDescriptorProto_Type) bool {
  948. switch typ {
  949. case descriptor.FieldDescriptorProto_TYPE_GROUP:
  950. return false
  951. case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
  952. return false
  953. case descriptor.FieldDescriptorProto_TYPE_BYTES:
  954. return false
  955. }
  956. return true
  957. }
  958. // TypeName is the printed name appropriate for an item. If the object is in the current file,
  959. // TypeName drops the package name and underscores the rest.
  960. // Otherwise the object is from another package; and the result is the underscored
  961. // package name followed by the item name.
  962. // The result always has an initial capital.
  963. func (g *Generator) TypeName(obj Object) string {
  964. return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName())
  965. }
  966. // TypeNameWithPackage is like TypeName, but always includes the package
  967. // name even if the object is in our own package.
  968. func (g *Generator) TypeNameWithPackage(obj Object) string {
  969. return obj.PackageName() + CamelCaseSlice(obj.TypeName())
  970. }
  971. // GoType returns a string representing the type name, and the wire type
  972. func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
  973. // TODO: Options.
  974. switch *field.Type {
  975. case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
  976. typ, wire = "float64", "fixed64"
  977. case descriptor.FieldDescriptorProto_TYPE_FLOAT:
  978. typ, wire = "float32", "fixed32"
  979. case descriptor.FieldDescriptorProto_TYPE_INT64:
  980. typ, wire = "int64", "varint"
  981. case descriptor.FieldDescriptorProto_TYPE_UINT64:
  982. typ, wire = "uint64", "varint"
  983. case descriptor.FieldDescriptorProto_TYPE_INT32:
  984. typ, wire = "int32", "varint"
  985. case descriptor.FieldDescriptorProto_TYPE_UINT32:
  986. typ, wire = "uint32", "varint"
  987. case descriptor.FieldDescriptorProto_TYPE_FIXED64:
  988. typ, wire = "uint64", "fixed64"
  989. case descriptor.FieldDescriptorProto_TYPE_FIXED32:
  990. typ, wire = "uint32", "fixed32"
  991. case descriptor.FieldDescriptorProto_TYPE_BOOL:
  992. typ, wire = "bool", "varint"
  993. case descriptor.FieldDescriptorProto_TYPE_STRING:
  994. typ, wire = "string", "bytes"
  995. case descriptor.FieldDescriptorProto_TYPE_GROUP:
  996. desc := g.ObjectNamed(proto.GetString(field.TypeName))
  997. typ, wire = "*"+g.TypeName(desc), "group"
  998. case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
  999. desc := g.ObjectNamed(proto.GetString(field.TypeName))
  1000. typ, wire = "*"+g.TypeName(desc), "bytes"
  1001. case descriptor.FieldDescriptorProto_TYPE_BYTES:
  1002. typ, wire = "[]byte", "bytes"
  1003. case descriptor.FieldDescriptorProto_TYPE_ENUM:
  1004. desc := g.ObjectNamed(proto.GetString(field.TypeName))
  1005. typ, wire = g.TypeName(desc), "varint"
  1006. case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
  1007. typ, wire = "int32", "fixed32"
  1008. case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
  1009. typ, wire = "int64", "fixed64"
  1010. case descriptor.FieldDescriptorProto_TYPE_SINT32:
  1011. typ, wire = "int32", "zigzag32"
  1012. case descriptor.FieldDescriptorProto_TYPE_SINT64:
  1013. typ, wire = "int64", "zigzag64"
  1014. default:
  1015. g.Fail("unknown type for", proto.GetString(field.Name))
  1016. }
  1017. if isRepeated(field) {
  1018. typ = "[]" + typ
  1019. } else if needsStar(*field.Type) {
  1020. typ = "*" + typ
  1021. }
  1022. return
  1023. }
  1024. func (g *Generator) RecordTypeUse(t string) {
  1025. if obj, ok := g.typeNameToObject[t]; ok {
  1026. // Call ObjectNamed to get the true object to record the use.
  1027. obj = g.ObjectNamed(t)
  1028. g.usedPackages[obj.PackageName()] = true
  1029. }
  1030. }
  1031. // Method names that may be generated. Fields with these names get an
  1032. // underscore appended.
  1033. var methodNames = [...]string{
  1034. "Reset",
  1035. "String",
  1036. "Marshal",
  1037. "Unmarshal",
  1038. "ExtensionRangeArray",
  1039. "ExtensionMap",
  1040. }
  1041. // Generate the type and default constant definitions for this Descriptor.
  1042. func (g *Generator) generateMessage(message *Descriptor) {
  1043. // The full type name
  1044. typeName := message.TypeName()
  1045. // The full type name, CamelCased.
  1046. ccTypeName := CamelCaseSlice(typeName)
  1047. usedNames := make(map[string]bool)
  1048. for _, n := range methodNames {
  1049. usedNames[n] = true
  1050. }
  1051. g.P("type ", ccTypeName, " struct {")
  1052. g.In()
  1053. for _, field := range message.Field {
  1054. fieldname := CamelCase(*field.Name)
  1055. for usedNames[fieldname] {
  1056. fieldname += "_"
  1057. }
  1058. usedNames[fieldname] = true
  1059. typename, wiretype := g.GoType(message, field)
  1060. jsonName := *field.Name
  1061. // This is a hack that is going away. TODO: remove this.
  1062. if field.Options != nil && proto.GetBool(field.Options.Weak) {
  1063. typename = "[]byte"
  1064. }
  1065. tag := fmt.Sprintf("`protobuf:%s json:%q`", g.goTag(field, wiretype), jsonName+",omitempty")
  1066. g.P(fieldname, "\t", typename, "\t", tag)
  1067. g.RecordTypeUse(proto.GetString(field.TypeName))
  1068. }
  1069. if len(message.ExtensionRange) > 0 {
  1070. g.P("XXX_extensions\t\tmap[int32]", g.ProtoPkg, ".Extension `json:\"-\"`")
  1071. }
  1072. g.P("XXX_unrecognized\t[]byte `json:\"-\"`")
  1073. g.Out()
  1074. g.P("}")
  1075. // Reset and String functions
  1076. g.P("func (this *", ccTypeName, ") Reset() { *this = ", ccTypeName, "{} }")
  1077. g.P("func (this *", ccTypeName, ") String() string { return ", g.ProtoPkg, ".CompactTextString(this) }")
  1078. // Extension support methods
  1079. var hasExtensions, isMessageSet bool
  1080. if len(message.ExtensionRange) > 0 {
  1081. hasExtensions = true
  1082. // message_set_wire_format only makes sense when extensions are defined.
  1083. if opts := message.Options; opts != nil && proto.GetBool(opts.MessageSetWireFormat) {
  1084. isMessageSet = true
  1085. g.P()
  1086. g.P("func (this *", ccTypeName, ") Marshal() ([]byte, error) {")
  1087. g.In()
  1088. g.P("return ", g.ProtoPkg, ".MarshalMessageSet(this.ExtensionMap())")
  1089. g.Out()
  1090. g.P("}")
  1091. g.P("func (this *", ccTypeName, ") Unmarshal(buf []byte) error {")
  1092. g.In()
  1093. g.P("return ", g.ProtoPkg, ".UnmarshalMessageSet(buf, this.ExtensionMap())")
  1094. g.Out()
  1095. g.P("}")
  1096. g.P("// ensure ", ccTypeName, " satisfies proto.Marshaler and proto.Unmarshaler")
  1097. g.P("var _ ", g.ProtoPkg, ".Marshaler = (*", ccTypeName, ")(nil)")
  1098. g.P("var _ ", g.ProtoPkg, ".Unmarshaler = (*", ccTypeName, ")(nil)")
  1099. }
  1100. g.P()
  1101. g.P("var extRange_", ccTypeName, " = []", g.ProtoPkg, ".ExtensionRange{")
  1102. g.In()
  1103. for _, r := range message.ExtensionRange {
  1104. end := fmt.Sprint(*r.End - 1) // make range inclusive on both ends
  1105. g.P("{", r.Start, ", ", end, "},")
  1106. }
  1107. g.Out()
  1108. g.P("}")
  1109. g.P("func (*", ccTypeName, ") ExtensionRangeArray() []", g.ProtoPkg, ".ExtensionRange {")
  1110. g.In()
  1111. g.P("return extRange_", ccTypeName)
  1112. g.Out()
  1113. g.P("}")
  1114. g.P("func (this *", ccTypeName, ") ExtensionMap() map[int32]", g.ProtoPkg, ".Extension {")
  1115. g.In()
  1116. g.P("if this.XXX_extensions == nil {")
  1117. g.In()
  1118. g.P("this.XXX_extensions = make(map[int32]", g.ProtoPkg, ".Extension)")
  1119. g.Out()
  1120. g.P("}")
  1121. g.P("return this.XXX_extensions")
  1122. g.Out()
  1123. g.P("}")
  1124. }
  1125. g.file.addExport(message, messageSymbol{ccTypeName, hasExtensions, isMessageSet})
  1126. // Default constants
  1127. for _, field := range message.Field {
  1128. def := proto.GetString(field.DefaultValue)
  1129. if def == "" {
  1130. continue
  1131. }
  1132. fieldname := "Default_" + ccTypeName + "_" + CamelCase(*field.Name)
  1133. typename, _ := g.GoType(message, field)
  1134. if typename[0] == '*' {
  1135. typename = typename[1:]
  1136. }
  1137. kind := "const "
  1138. switch {
  1139. case typename == "bool":
  1140. case typename == "string":
  1141. def = Quote(def)
  1142. case typename == "[]byte":
  1143. def = "[]byte(" + Quote(def) + ")"
  1144. kind = "var "
  1145. case def == "inf", def == "-inf", def == "nan":
  1146. // These names are known to, and defined by, the protocol language.
  1147. switch def {
  1148. case "inf":
  1149. def = "math.Inf(1)"
  1150. case "-inf":
  1151. def = "math.Inf(-1)"
  1152. case "nan":
  1153. def = "math.NaN()"
  1154. }
  1155. if *field.Type == descriptor.FieldDescriptorProto_TYPE_FLOAT {
  1156. def = "float32(" + def + ")"
  1157. }
  1158. kind = "var "
  1159. case *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM:
  1160. // Must be an enum. Need to construct the prefixed name.
  1161. obj := g.ObjectNamed(proto.GetString(field.TypeName))
  1162. enum, ok := obj.(*EnumDescriptor)
  1163. if !ok {
  1164. log.Println("don't know how to generate constant for", fieldname)
  1165. continue
  1166. }
  1167. def = g.DefaultPackageName(enum) + enum.prefix() + def
  1168. }
  1169. g.P(kind, fieldname, " ", typename, " = ", def)
  1170. g.file.addExport(message, constOrVarSymbol{fieldname, kind})
  1171. }
  1172. g.P()
  1173. for _, ext := range message.ext {
  1174. g.generateExtension(ext)
  1175. }
  1176. }
  1177. func (g *Generator) generateExtension(ext *ExtensionDescriptor) {
  1178. ccTypeName := ext.DescName()
  1179. extendedType := "*" + g.TypeName(g.ObjectNamed(*ext.Extendee))
  1180. field := ext.FieldDescriptorProto
  1181. fieldType, wireType := g.GoType(ext.parent, field)
  1182. tag := g.goTag(field, wireType)
  1183. g.RecordTypeUse(*ext.Extendee)
  1184. if n := ext.FieldDescriptorProto.TypeName; n != nil {
  1185. // foreign extension type
  1186. g.RecordTypeUse(*n)
  1187. }
  1188. typeName := ext.TypeName()
  1189. // Special case for proto2 message sets: If this extension is extending
  1190. // proto2_bridge.MessageSet, and its final name component is "message_set_extension",
  1191. // then drop that last component.
  1192. if extendedType == "*proto2_bridge.MessageSet" && typeName[len(typeName)-1] == "message_set_extension" {
  1193. typeName = typeName[:len(typeName)-1]
  1194. }
  1195. // For text formatting, the package must be exactly what the .proto file declares,
  1196. // ignoring overrides such as the go_package option, and with no dot/underscore mapping.
  1197. extName := strings.Join(typeName, ".")
  1198. if g.file.Package != nil {
  1199. extName = *g.file.Package + "." + extName
  1200. }
  1201. g.P("var ", ccTypeName, " = &", g.ProtoPkg, ".ExtensionDesc{")
  1202. g.In()
  1203. g.P("ExtendedType: (", extendedType, ")(nil),")
  1204. g.P("ExtensionType: (", fieldType, ")(nil),")
  1205. g.P("Field: ", field.Number, ",")
  1206. g.P(`Name: "`, extName, `",`)
  1207. g.P("Tag: ", tag, ",")
  1208. g.Out()
  1209. g.P("}")
  1210. g.P()
  1211. g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var"})
  1212. }
  1213. func (g *Generator) generateInitFunction() {
  1214. g.P("func init() {")
  1215. g.In()
  1216. for _, enum := range g.file.enum {
  1217. g.generateEnumRegistration(enum)
  1218. }
  1219. for _, d := range g.file.desc {
  1220. for _, ext := range d.ext {
  1221. g.generateExtensionRegistration(ext)
  1222. }
  1223. }
  1224. for _, ext := range g.file.ext {
  1225. g.generateExtensionRegistration(ext)
  1226. }
  1227. g.Out()
  1228. g.P("}")
  1229. }
  1230. func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) {
  1231. // // We always print the full (proto-world) package name here.
  1232. pkg := proto.GetString(enum.File().Package)
  1233. if pkg != "" {
  1234. pkg += "."
  1235. }
  1236. // The full type name
  1237. typeName := enum.TypeName()
  1238. // The full type name, CamelCased.
  1239. ccTypeName := CamelCaseSlice(typeName)
  1240. g.P(g.ProtoPkg+".RegisterEnum(", Quote(pkg+ccTypeName), ", ", ccTypeName+"_name, ", ccTypeName+"_value)")
  1241. }
  1242. func (g *Generator) generateExtensionRegistration(ext *ExtensionDescriptor) {
  1243. g.P(g.ProtoPkg+".RegisterExtension(", ext.DescName(), ")")
  1244. }
  1245. // And now lots of helper functions.
  1246. // Is c an ASCII lower-case letter?
  1247. func isASCIILower(c byte) bool {
  1248. return 'a' <= c && c <= 'z'
  1249. }
  1250. // Is c an ASCII digit?
  1251. func isASCIIDigit(c byte) bool {
  1252. return '0' <= c && c <= '9'
  1253. }
  1254. // CamelCase returns the CamelCased name.
  1255. // If there is an interior underscore followed by a lower case letter,
  1256. // drop the underscore and convert the letter to upper case.
  1257. // There is a remote possibility of this rewrite causing a name collision,
  1258. // but it's so remote we're prepared to pretend it's nonexistent - since the
  1259. // C++ generator lowercases names, it's extremely unlikely to have two fields
  1260. // with different capitalizations.
  1261. // In short, _my_field_name_2 becomes XMyFieldName2.
  1262. func CamelCase(s string) string {
  1263. if s == "" {
  1264. return ""
  1265. }
  1266. t := make([]byte, 0, 32)
  1267. i := 0
  1268. if s[0] == '_' {
  1269. // Need a capital letter; drop the '_'.
  1270. t = append(t, 'X')
  1271. i++
  1272. }
  1273. // Invariant: if the next letter is lower case, it must be converted
  1274. // to upper case.
  1275. // That is, we process a word at a time, where words are marked by _ or
  1276. // upper case letter. Digits are treated as words.
  1277. for ; i < len(s); i++ {
  1278. c := s[i]
  1279. if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
  1280. continue // Skip the underscore in s.
  1281. }
  1282. if isASCIIDigit(c) {
  1283. t = append(t, c)
  1284. continue
  1285. }
  1286. // Assume we have a letter now - if not, it's a bogus identifier.
  1287. // The next word is a sequence of characters that must start upper case.
  1288. if isASCIILower(c) {
  1289. c ^= ' ' // Make it a capital letter.
  1290. }
  1291. t = append(t, c) // Guaranteed not lower case.
  1292. // Accept lower case sequence that follows.
  1293. for i+1 < len(s) && isASCIILower(s[i+1]) {
  1294. i++
  1295. t = append(t, s[i])
  1296. }
  1297. }
  1298. return string(t)
  1299. }
  1300. // CamelCaseSlice is like CamelCase, but the argument is a slice of strings to
  1301. // be joined with "_".
  1302. func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
  1303. // dottedSlice turns a sliced name into a dotted name.
  1304. func dottedSlice(elem []string) string { return strings.Join(elem, ".") }
  1305. // Quote returns a Go-source quoted string representation of s.
  1306. func Quote(s string) string { return fmt.Sprintf("%q", s) }
  1307. // Given a .proto file name, return the output name for the generated Go program.
  1308. func goFileName(name string) string {
  1309. ext := path.Ext(name)
  1310. if ext == ".proto" || ext == ".protodevel" {
  1311. name = name[0 : len(name)-len(ext)]
  1312. }
  1313. return name + ".pb.go"
  1314. }
  1315. // Is this field optional?
  1316. func isOptional(field *descriptor.FieldDescriptorProto) bool {
  1317. return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL
  1318. }
  1319. // Is this field required?
  1320. func isRequired(field *descriptor.FieldDescriptorProto) bool {
  1321. return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED
  1322. }
  1323. // Is this field repeated?
  1324. func isRepeated(field *descriptor.FieldDescriptorProto) bool {
  1325. return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
  1326. }
  1327. // DotToUnderscore is the mapping function used to generate Go names from package names,
  1328. // which can be dotted in the input .proto file. It maps dots to underscores.
  1329. // Because we also get here from package names generated from file names, it also maps
  1330. // minus signs to underscores.
  1331. func DotToUnderscore(r rune) rune {
  1332. switch r {
  1333. case '.', '-':
  1334. return '_'
  1335. }
  1336. return r
  1337. }
  1338. // BaseName returns the last path element of the name, with the last dotted suffix removed.
  1339. func BaseName(name string) string {
  1340. // First, find the last element
  1341. if i := strings.LastIndex(name, "/"); i >= 0 {
  1342. name = name[i+1:]
  1343. }
  1344. // Now drop the suffix
  1345. if i := strings.LastIndex(name, "."); i >= 0 {
  1346. name = name[0:i]
  1347. }
  1348. return name
  1349. }