فهرست منبع

goprotobuf: Repeated field getters.

R=adg
CC=golang-dev
https://codereview.appspot.com/7225068
David Symonds 13 سال پیش
والد
کامیت
db7a687c29

+ 45 - 9
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)

+ 4 - 0
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;

+ 21 - 0
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"`

+ 21 - 0
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"`