aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Symonds <dsymonds@golang.org>2013-01-30 17:08:05 +1100
committerDavid Symonds <dsymonds@golang.org>2013-01-30 17:08:05 +1100
commitdb7a687c2924df3534aea8ec031e79d40f3a8ba0 (patch)
tree7774c1ab9011866209778ccbe17cf4ea4f0d2af7
parent6e8ab8784338b90a5e515346a6193852f33d397b (diff)
downloadprotobuf-db7a687c2924df3534aea8ec031e79d40f3a8ba0.tar.gz
goprotobuf: Repeated field getters.
R=adg CC=golang-dev https://codereview.appspot.com/7225068
-rw-r--r--protoc-gen-go/generator/generator.go54
-rw-r--r--protoc-gen-go/testdata/imp.proto4
-rw-r--r--protoc-gen-go/testdata/my_test/test.pb.go21
-rw-r--r--protoc-gen-go/testdata/my_test/test.pb.go.golden21
4 files changed, 91 insertions, 9 deletions
diff --git a/protoc-gen-go/generator/generator.go b/protoc-gen-go/generator/generator.go
index 58d42bf..ddefabe 100644
--- a/protoc-gen-go/generator/generator.go
+++ b/protoc-gen-go/generator/generator.go
@@ -298,24 +298,60 @@ func (ms *messageSymbol) GenerateAlias(g *Generator, pkg string) {
}
}
for _, get := range ms.getters {
+ if get.typeName != "" {
+ g.RecordTypeUse(get.typeName)
+ }
typ := get.typ
val := "(*" + remoteSym + ")(this)." + get.name + "()"
if get.genType {
// typ will be "*pkg.T" (message/group) or "pkg.T" (enum).
+ // Either of those might have a "[]" prefix if it is repeated.
// Drop the package qualifier since we have hoisted the type into this package.
+ rep := strings.HasPrefix(typ, "[]")
+ if rep {
+ typ = typ[2:]
+ }
star := typ[0] == '*'
typ = typ[strings.Index(typ, ".")+1:]
if star {
typ = "*" + typ
}
+ if rep {
+ // Go does not permit conversion between slice types where both
+ // element types are named. That means we need to generate a bit
+ // of code in this situation.
+ // typ is the element type.
+ // val is the expression to get the slice from the imported type.
+
+ ctyp := typ // conversion type expression; "Foo" or "(*Foo)"
+ if star {
+ ctyp = "(" + typ + ")"
+ }
+
+ g.P("func (this *", ms.sym, ") ", get.name, "() []", typ, " {")
+ g.In()
+ g.P("o := ", val)
+ g.P("if o == nil {")
+ g.In()
+ g.P("return nil")
+ g.Out()
+ g.P("}")
+ g.P("s := make([]", typ, ", len(o))")
+ g.P("for i, x := range o {")
+ g.In()
+ g.P("s[i] = ", ctyp, "(x)")
+ g.Out()
+ g.P("}")
+ g.P("return s")
+ g.Out()
+ g.P("}")
+ continue
+ }
// Convert imported type into the forwarding type.
val = "(" + typ + ")(" + val + ")"
}
g.P("func (this *", ms.sym, ") ", get.name, "() ", typ, " { return ", val, " }")
- if get.typeName != "" {
- g.RecordTypeUse(get.typeName)
- }
}
}
@@ -1011,8 +1047,8 @@ func (g *Generator) generateImports() {
}
g.P("// Reference proto, json, and math imports to suppress error if they are not otherwise used.")
g.P("var _ = ", g.Pkg["proto"], ".Marshal")
- g.P("var _ = &json.SyntaxError{}")
- g.P("var _ = math.Inf")
+ g.P("var _ = &", g.Pkg["json"], ".SyntaxError{}")
+ g.P("var _ = ", g.Pkg["math"], ".Inf")
g.P()
}
@@ -1452,9 +1488,6 @@ func (g *Generator) generateMessage(message *Descriptor) {
// Field getters
var getters []getterSymbol
for _, field := range message.Field {
- if isRepeated(field) {
- continue
- }
fname := fieldNames[field]
typename, _ := g.GoType(message, field)
mname := "Get" + fname
@@ -1504,9 +1537,12 @@ func (g *Generator) generateMessage(message *Descriptor) {
case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE:
typeDefaultIsNil = true
}
+ if isRepeated(field) {
+ typeDefaultIsNil = true
+ }
if typeDefaultIsNil {
// A bytes field with no explicit default needs less generated code,
- // as does a message or group field.
+ // as does a message or group field, or a repeated field.
g.P("if this != nil {")
g.In()
g.P("return this." + fname)
diff --git a/protoc-gen-go/testdata/imp.proto b/protoc-gen-go/testdata/imp.proto
index 9767a0d..52d34e2 100644
--- a/protoc-gen-go/testdata/imp.proto
+++ b/protoc-gen-go/testdata/imp.proto
@@ -42,6 +42,10 @@ message ImportedMessage {
optional ForeignImportedMessage foreign_msg = 3; // in imp3.proto
optional Owner enum_field = 4;
+ repeated string name = 5;
+ repeated Owner boss = 6;
+ repeated ImportedMessage2 memo = 7;
+
enum Owner {
DAVE = 1;
MIKE = 2;
diff --git a/protoc-gen-go/testdata/my_test/test.pb.go b/protoc-gen-go/testdata/my_test/test.pb.go
index 4a465f7..0e3f4c2 100644
--- a/protoc-gen-go/testdata/my_test/test.pb.go
+++ b/protoc-gen-go/testdata/my_test/test.pb.go
@@ -183,6 +183,13 @@ const Default_Request_Hat HatType = HatType_FEDORA
var Default_Request_Deadline float32 = float32(math.Inf(1))
+func (this *Request) GetKey() []int64 {
+ if this != nil {
+ return this.Key
+ }
+ return nil
+}
+
func (this *Request) GetHue() Request_Color {
if this != nil && this.Hue != nil {
return *this.Hue
@@ -256,6 +263,20 @@ func (this *Reply) ExtensionMap() map[int32]proto.Extension {
return this.XXX_extensions
}
+func (this *Reply) GetFound() []*Reply_Entry {
+ if this != nil {
+ return this.Found
+ }
+ return nil
+}
+
+func (this *Reply) GetCompactKeys() []int32 {
+ if this != nil {
+ return this.CompactKeys
+ }
+ return nil
+}
+
type Reply_Entry struct {
KeyThatNeeds_1234Camel_CasIng *int64 `protobuf:"varint,1,req,name=key_that_needs_1234camel_CasIng" json:"key_that_needs_1234camel_CasIng,omitempty"`
Value *int64 `protobuf:"varint,2,opt,name=value,def=7" json:"value,omitempty"`
diff --git a/protoc-gen-go/testdata/my_test/test.pb.go.golden b/protoc-gen-go/testdata/my_test/test.pb.go.golden
index 4a465f7..0e3f4c2 100644
--- a/protoc-gen-go/testdata/my_test/test.pb.go.golden
+++ b/protoc-gen-go/testdata/my_test/test.pb.go.golden
@@ -183,6 +183,13 @@ const Default_Request_Hat HatType = HatType_FEDORA
var Default_Request_Deadline float32 = float32(math.Inf(1))
+func (this *Request) GetKey() []int64 {
+ if this != nil {
+ return this.Key
+ }
+ return nil
+}
+
func (this *Request) GetHue() Request_Color {
if this != nil && this.Hue != nil {
return *this.Hue
@@ -256,6 +263,20 @@ func (this *Reply) ExtensionMap() map[int32]proto.Extension {
return this.XXX_extensions
}
+func (this *Reply) GetFound() []*Reply_Entry {
+ if this != nil {
+ return this.Found
+ }
+ return nil
+}
+
+func (this *Reply) GetCompactKeys() []int32 {
+ if this != nil {
+ return this.CompactKeys
+ }
+ return nil
+}
+
type Reply_Entry struct {
KeyThatNeeds_1234Camel_CasIng *int64 `protobuf:"varint,1,req,name=key_that_needs_1234camel_CasIng" json:"key_that_needs_1234camel_CasIng,omitempty"`
Value *int64 `protobuf:"varint,2,opt,name=value,def=7" json:"value,omitempty"`