cmd/protoc-gen-go: generate common message methods

Generate the standard Reset, String, ProtoMessage, and Descriptor
methods for each message struct.

Generate the table-driven support methods (XXX_Marshal, et al.).

Change-Id: I8a5ed8af1433b481e2458ad534456692d6f74c1f
Reviewed-on: https://go-review.googlesource.com/134996
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/cmd/protoc-gen-go/main.go b/cmd/protoc-gen-go/main.go
index dc4ded3..9213ea8 100644
--- a/cmd/protoc-gen-go/main.go
+++ b/cmd/protoc-gen-go/main.go
@@ -267,6 +267,62 @@
 	g.P("}")
 	g.P()
 
+	// Reset
+	g.P("func (m *", message.GoIdent, ") Reset() { *m = ", message.GoIdent, "{} }")
+	// String
+	g.P("func (m *", message.GoIdent, ") String() string { return ", protogen.GoIdent{
+		GoImportPath: protoPackage,
+		GoName:       "CompactTextString",
+	}, "(m) }")
+	// ProtoMessage
+	g.P("func (*", message.GoIdent, ") ProtoMessage() {}")
+	// Descriptor
+	var indexes []string
+	for i := 1; i < len(message.Path); i += 2 {
+		indexes = append(indexes, strconv.Itoa(int(message.Path[i])))
+	}
+	g.P("func (*", message.GoIdent, ") Descriptor() ([]byte, []int) {")
+	g.P("return ", f.descriptorVar, ", []int{", strings.Join(indexes, ","), "}")
+	g.P("}")
+	// TODO: extension support methods
+
+	// Table-driven proto support.
+	//
+	// TODO: It does not scale to keep adding another method for every
+	// operation on protos that we want to switch over to using the
+	// table-driven approach. Instead, we should only add a single method
+	// that allows getting access to the *InternalMessageInfo struct and then
+	// calling Unmarshal, Marshal, Merge, Size, and Discard directly on that.
+	messageInfoVar := "xxx_messageInfo_" + message.GoIdent.GoName
+	// XXX_Unmarshal
+	g.P("func (m *", message.GoIdent, ") XXX_Unmarshal(b []byte) error {")
+	g.P("return ", messageInfoVar, ".Unmarshal(m, b)")
+	g.P("}")
+	// XXX_Marshal
+	g.P("func (m *", message.GoIdent, ") XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {")
+	g.P("return ", messageInfoVar, ".Marshal(b, m, deterministic)")
+	g.P("}")
+	// XXX_Merge
+	g.P("func (m *", message.GoIdent, ") XXX_Merge(src proto.Message) {")
+	g.P(messageInfoVar, ".Merge(m, src)")
+	g.P("}")
+	// XXX_Size
+	g.P("func (m *", message.GoIdent, ") XXX_Size() int {")
+	g.P("return ", messageInfoVar, ".Size(m)")
+	g.P("}")
+	// XXX_DiscardUnknown
+	g.P("func (m *", message.GoIdent, ") XXX_DiscardUnknown() {")
+	g.P(messageInfoVar, ".DiscardUnknown(m)")
+	g.P("}")
+	g.P()
+	g.P("var ", messageInfoVar, " ", protogen.GoIdent{
+		GoImportPath: protoPackage,
+		GoName:       "InternalMessageInfo",
+	})
+	g.P()
+
+	// TODO: getters
+
 	for _, nested := range message.Messages {
 		genMessage(gen, g, f, nested)
 	}
diff --git a/cmd/protoc-gen-go/testdata/comments/comments.pb.go b/cmd/protoc-gen-go/testdata/comments/comments.pb.go
index fedfc9e..6a426fe 100644
--- a/cmd/protoc-gen-go/testdata/comments/comments.pb.go
+++ b/cmd/protoc-gen-go/testdata/comments/comments.pb.go
@@ -20,6 +20,30 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *Message1) Reset()         { *m = Message1{} }
+func (m *Message1) String() string { return proto.CompactTextString(m) }
+func (*Message1) ProtoMessage()    {}
+func (*Message1) Descriptor() ([]byte, []int) {
+	return fileDescriptor_885e8293f1fab554, []int{0}
+}
+func (m *Message1) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Message1.Unmarshal(m, b)
+}
+func (m *Message1) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Message1.Marshal(b, m, deterministic)
+}
+func (m *Message1) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Message1.Merge(m, src)
+}
+func (m *Message1) XXX_Size() int {
+	return xxx_messageInfo_Message1.Size(m)
+}
+func (m *Message1) XXX_DiscardUnknown() {
+	xxx_messageInfo_Message1.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Message1 proto.InternalMessageInfo
+
 // COMMENT: Message1A
 type Message1_Message1A struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -27,6 +51,30 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *Message1_Message1A) Reset()         { *m = Message1_Message1A{} }
+func (m *Message1_Message1A) String() string { return proto.CompactTextString(m) }
+func (*Message1_Message1A) ProtoMessage()    {}
+func (*Message1_Message1A) Descriptor() ([]byte, []int) {
+	return fileDescriptor_885e8293f1fab554, []int{0, 0}
+}
+func (m *Message1_Message1A) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Message1_Message1A.Unmarshal(m, b)
+}
+func (m *Message1_Message1A) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Message1_Message1A.Marshal(b, m, deterministic)
+}
+func (m *Message1_Message1A) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Message1_Message1A.Merge(m, src)
+}
+func (m *Message1_Message1A) XXX_Size() int {
+	return xxx_messageInfo_Message1_Message1A.Size(m)
+}
+func (m *Message1_Message1A) XXX_DiscardUnknown() {
+	xxx_messageInfo_Message1_Message1A.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Message1_Message1A proto.InternalMessageInfo
+
 // COMMENT: Message1B
 type Message1_Message1B struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -34,6 +82,30 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *Message1_Message1B) Reset()         { *m = Message1_Message1B{} }
+func (m *Message1_Message1B) String() string { return proto.CompactTextString(m) }
+func (*Message1_Message1B) ProtoMessage()    {}
+func (*Message1_Message1B) Descriptor() ([]byte, []int) {
+	return fileDescriptor_885e8293f1fab554, []int{0, 1}
+}
+func (m *Message1_Message1B) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Message1_Message1B.Unmarshal(m, b)
+}
+func (m *Message1_Message1B) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Message1_Message1B.Marshal(b, m, deterministic)
+}
+func (m *Message1_Message1B) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Message1_Message1B.Merge(m, src)
+}
+func (m *Message1_Message1B) XXX_Size() int {
+	return xxx_messageInfo_Message1_Message1B.Size(m)
+}
+func (m *Message1_Message1B) XXX_DiscardUnknown() {
+	xxx_messageInfo_Message1_Message1B.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Message1_Message1B proto.InternalMessageInfo
+
 // COMMENT: Message2
 type Message2 struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -41,6 +113,30 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *Message2) Reset()         { *m = Message2{} }
+func (m *Message2) String() string { return proto.CompactTextString(m) }
+func (*Message2) ProtoMessage()    {}
+func (*Message2) Descriptor() ([]byte, []int) {
+	return fileDescriptor_885e8293f1fab554, []int{1}
+}
+func (m *Message2) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Message2.Unmarshal(m, b)
+}
+func (m *Message2) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Message2.Marshal(b, m, deterministic)
+}
+func (m *Message2) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Message2.Merge(m, src)
+}
+func (m *Message2) XXX_Size() int {
+	return xxx_messageInfo_Message2.Size(m)
+}
+func (m *Message2) XXX_DiscardUnknown() {
+	xxx_messageInfo_Message2.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Message2 proto.InternalMessageInfo
+
 // COMMENT: Message2A
 type Message2_Message2A struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -48,6 +144,30 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *Message2_Message2A) Reset()         { *m = Message2_Message2A{} }
+func (m *Message2_Message2A) String() string { return proto.CompactTextString(m) }
+func (*Message2_Message2A) ProtoMessage()    {}
+func (*Message2_Message2A) Descriptor() ([]byte, []int) {
+	return fileDescriptor_885e8293f1fab554, []int{1, 0}
+}
+func (m *Message2_Message2A) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Message2_Message2A.Unmarshal(m, b)
+}
+func (m *Message2_Message2A) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Message2_Message2A.Marshal(b, m, deterministic)
+}
+func (m *Message2_Message2A) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Message2_Message2A.Merge(m, src)
+}
+func (m *Message2_Message2A) XXX_Size() int {
+	return xxx_messageInfo_Message2_Message2A.Size(m)
+}
+func (m *Message2_Message2A) XXX_DiscardUnknown() {
+	xxx_messageInfo_Message2_Message2A.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Message2_Message2A proto.InternalMessageInfo
+
 // COMMENT: Message2B
 type Message2_Message2B struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -55,6 +175,30 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *Message2_Message2B) Reset()         { *m = Message2_Message2B{} }
+func (m *Message2_Message2B) String() string { return proto.CompactTextString(m) }
+func (*Message2_Message2B) ProtoMessage()    {}
+func (*Message2_Message2B) Descriptor() ([]byte, []int) {
+	return fileDescriptor_885e8293f1fab554, []int{1, 1}
+}
+func (m *Message2_Message2B) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Message2_Message2B.Unmarshal(m, b)
+}
+func (m *Message2_Message2B) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Message2_Message2B.Marshal(b, m, deterministic)
+}
+func (m *Message2_Message2B) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Message2_Message2B.Merge(m, src)
+}
+func (m *Message2_Message2B) XXX_Size() int {
+	return xxx_messageInfo_Message2_Message2B.Size(m)
+}
+func (m *Message2_Message2B) XXX_DiscardUnknown() {
+	xxx_messageInfo_Message2_Message2B.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Message2_Message2B proto.InternalMessageInfo
+
 func init() { proto.RegisterFile("comments/comments.proto", fileDescriptor_885e8293f1fab554) }
 
 var fileDescriptor_885e8293f1fab554 = []byte{
diff --git a/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go b/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go
index c57f3c2..a12017f 100644
--- a/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go
+++ b/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go
@@ -40,6 +40,30 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *Message) Reset()         { *m = Message{} }
+func (m *Message) String() string { return proto.CompactTextString(m) }
+func (*Message) ProtoMessage()    {}
+func (*Message) Descriptor() ([]byte, []int) {
+	return fileDescriptor_6bbe3f70febb9403, []int{0}
+}
+func (m *Message) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Message.Unmarshal(m, b)
+}
+func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Message.Marshal(b, m, deterministic)
+}
+func (m *Message) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Message.Merge(m, src)
+}
+func (m *Message) XXX_Size() int {
+	return xxx_messageInfo_Message.Size(m)
+}
+func (m *Message) XXX_DiscardUnknown() {
+	xxx_messageInfo_Message.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Message proto.InternalMessageInfo
+
 func init() { proto.RegisterFile("fieldnames/fieldnames.proto", fileDescriptor_6bbe3f70febb9403) }
 
 var fileDescriptor_6bbe3f70febb9403 = []byte{
diff --git a/cmd/protoc-gen-go/testdata/proto2/enum.pb.go b/cmd/protoc-gen-go/testdata/proto2/enum.pb.go
index 8911ecd..5a32525 100644
--- a/cmd/protoc-gen-go/testdata/proto2/enum.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/enum.pb.go
@@ -176,6 +176,30 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *EnumContainerMessage1) Reset()         { *m = EnumContainerMessage1{} }
+func (m *EnumContainerMessage1) String() string { return proto.CompactTextString(m) }
+func (*EnumContainerMessage1) ProtoMessage()    {}
+func (*EnumContainerMessage1) Descriptor() ([]byte, []int) {
+	return fileDescriptor_de9f68860d540858, []int{0}
+}
+func (m *EnumContainerMessage1) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EnumContainerMessage1.Unmarshal(m, b)
+}
+func (m *EnumContainerMessage1) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EnumContainerMessage1.Marshal(b, m, deterministic)
+}
+func (m *EnumContainerMessage1) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EnumContainerMessage1.Merge(m, src)
+}
+func (m *EnumContainerMessage1) XXX_Size() int {
+	return xxx_messageInfo_EnumContainerMessage1.Size(m)
+}
+func (m *EnumContainerMessage1) XXX_DiscardUnknown() {
+	xxx_messageInfo_EnumContainerMessage1.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EnumContainerMessage1 proto.InternalMessageInfo
+
 // NestedEnumType2A comment.
 type EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2A int32
 
@@ -258,6 +282,34 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *EnumContainerMessage1_EnumContainerMessage2) Reset() {
+	*m = EnumContainerMessage1_EnumContainerMessage2{}
+}
+func (m *EnumContainerMessage1_EnumContainerMessage2) String() string {
+	return proto.CompactTextString(m)
+}
+func (*EnumContainerMessage1_EnumContainerMessage2) ProtoMessage() {}
+func (*EnumContainerMessage1_EnumContainerMessage2) Descriptor() ([]byte, []int) {
+	return fileDescriptor_de9f68860d540858, []int{0, 0}
+}
+func (m *EnumContainerMessage1_EnumContainerMessage2) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EnumContainerMessage1_EnumContainerMessage2.Unmarshal(m, b)
+}
+func (m *EnumContainerMessage1_EnumContainerMessage2) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EnumContainerMessage1_EnumContainerMessage2.Marshal(b, m, deterministic)
+}
+func (m *EnumContainerMessage1_EnumContainerMessage2) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EnumContainerMessage1_EnumContainerMessage2.Merge(m, src)
+}
+func (m *EnumContainerMessage1_EnumContainerMessage2) XXX_Size() int {
+	return xxx_messageInfo_EnumContainerMessage1_EnumContainerMessage2.Size(m)
+}
+func (m *EnumContainerMessage1_EnumContainerMessage2) XXX_DiscardUnknown() {
+	xxx_messageInfo_EnumContainerMessage1_EnumContainerMessage2.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EnumContainerMessage1_EnumContainerMessage2 proto.InternalMessageInfo
+
 func init() {
 	proto.RegisterEnum("goproto.protoc.proto2.EnumType1", EnumType1_name, EnumType1_value)
 	proto.RegisterEnum("goproto.protoc.proto2.EnumType2", EnumType2_name, EnumType2_value)
diff --git a/cmd/protoc-gen-go/testdata/proto2/fields.pb.go b/cmd/protoc-gen-go/testdata/proto2/fields.pb.go
index 1658e61..f3302a5 100644
--- a/cmd/protoc-gen-go/testdata/proto2/fields.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/fields.pb.go
@@ -108,6 +108,30 @@
 	XXX_sizecache        int32                             `json:"-"`
 }
 
+func (m *FieldTestMessage) Reset()         { *m = FieldTestMessage{} }
+func (m *FieldTestMessage) String() string { return proto.CompactTextString(m) }
+func (*FieldTestMessage) ProtoMessage()    {}
+func (*FieldTestMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fd8a9d72b841fd68, []int{0}
+}
+func (m *FieldTestMessage) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_FieldTestMessage.Unmarshal(m, b)
+}
+func (m *FieldTestMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_FieldTestMessage.Marshal(b, m, deterministic)
+}
+func (m *FieldTestMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FieldTestMessage.Merge(m, src)
+}
+func (m *FieldTestMessage) XXX_Size() int {
+	return xxx_messageInfo_FieldTestMessage.Size(m)
+}
+func (m *FieldTestMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_FieldTestMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FieldTestMessage proto.InternalMessageInfo
+
 type FieldTestMessage_OptionalGroup struct {
 	OptionalGroup        *string  `protobuf:"bytes,19,opt,name=optional_group,json=optionalGroup" json:"optional_group,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -115,6 +139,30 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *FieldTestMessage_OptionalGroup) Reset()         { *m = FieldTestMessage_OptionalGroup{} }
+func (m *FieldTestMessage_OptionalGroup) String() string { return proto.CompactTextString(m) }
+func (*FieldTestMessage_OptionalGroup) ProtoMessage()    {}
+func (*FieldTestMessage_OptionalGroup) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fd8a9d72b841fd68, []int{0, 0}
+}
+func (m *FieldTestMessage_OptionalGroup) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_FieldTestMessage_OptionalGroup.Unmarshal(m, b)
+}
+func (m *FieldTestMessage_OptionalGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_FieldTestMessage_OptionalGroup.Marshal(b, m, deterministic)
+}
+func (m *FieldTestMessage_OptionalGroup) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FieldTestMessage_OptionalGroup.Merge(m, src)
+}
+func (m *FieldTestMessage_OptionalGroup) XXX_Size() int {
+	return xxx_messageInfo_FieldTestMessage_OptionalGroup.Size(m)
+}
+func (m *FieldTestMessage_OptionalGroup) XXX_DiscardUnknown() {
+	xxx_messageInfo_FieldTestMessage_OptionalGroup.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FieldTestMessage_OptionalGroup proto.InternalMessageInfo
+
 type FieldTestMessage_RequiredGroup struct {
 	RequiredGroup        *string  `protobuf:"bytes,119,req,name=required_group,json=requiredGroup" json:"required_group,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -122,6 +170,30 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *FieldTestMessage_RequiredGroup) Reset()         { *m = FieldTestMessage_RequiredGroup{} }
+func (m *FieldTestMessage_RequiredGroup) String() string { return proto.CompactTextString(m) }
+func (*FieldTestMessage_RequiredGroup) ProtoMessage()    {}
+func (*FieldTestMessage_RequiredGroup) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fd8a9d72b841fd68, []int{0, 1}
+}
+func (m *FieldTestMessage_RequiredGroup) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_FieldTestMessage_RequiredGroup.Unmarshal(m, b)
+}
+func (m *FieldTestMessage_RequiredGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_FieldTestMessage_RequiredGroup.Marshal(b, m, deterministic)
+}
+func (m *FieldTestMessage_RequiredGroup) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FieldTestMessage_RequiredGroup.Merge(m, src)
+}
+func (m *FieldTestMessage_RequiredGroup) XXX_Size() int {
+	return xxx_messageInfo_FieldTestMessage_RequiredGroup.Size(m)
+}
+func (m *FieldTestMessage_RequiredGroup) XXX_DiscardUnknown() {
+	xxx_messageInfo_FieldTestMessage_RequiredGroup.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FieldTestMessage_RequiredGroup proto.InternalMessageInfo
+
 type FieldTestMessage_RepeatedGroup struct {
 	RepeatedGroup        []string `protobuf:"bytes,219,rep,name=repeated_group,json=repeatedGroup" json:"repeated_group,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -129,12 +201,60 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *FieldTestMessage_RepeatedGroup) Reset()         { *m = FieldTestMessage_RepeatedGroup{} }
+func (m *FieldTestMessage_RepeatedGroup) String() string { return proto.CompactTextString(m) }
+func (*FieldTestMessage_RepeatedGroup) ProtoMessage()    {}
+func (*FieldTestMessage_RepeatedGroup) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fd8a9d72b841fd68, []int{0, 2}
+}
+func (m *FieldTestMessage_RepeatedGroup) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_FieldTestMessage_RepeatedGroup.Unmarshal(m, b)
+}
+func (m *FieldTestMessage_RepeatedGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_FieldTestMessage_RepeatedGroup.Marshal(b, m, deterministic)
+}
+func (m *FieldTestMessage_RepeatedGroup) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FieldTestMessage_RepeatedGroup.Merge(m, src)
+}
+func (m *FieldTestMessage_RepeatedGroup) XXX_Size() int {
+	return xxx_messageInfo_FieldTestMessage_RepeatedGroup.Size(m)
+}
+func (m *FieldTestMessage_RepeatedGroup) XXX_DiscardUnknown() {
+	xxx_messageInfo_FieldTestMessage_RepeatedGroup.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FieldTestMessage_RepeatedGroup proto.InternalMessageInfo
+
 type FieldTestMessage_Message struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *FieldTestMessage_Message) Reset()         { *m = FieldTestMessage_Message{} }
+func (m *FieldTestMessage_Message) String() string { return proto.CompactTextString(m) }
+func (*FieldTestMessage_Message) ProtoMessage()    {}
+func (*FieldTestMessage_Message) Descriptor() ([]byte, []int) {
+	return fileDescriptor_fd8a9d72b841fd68, []int{0, 3}
+}
+func (m *FieldTestMessage_Message) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_FieldTestMessage_Message.Unmarshal(m, b)
+}
+func (m *FieldTestMessage_Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_FieldTestMessage_Message.Marshal(b, m, deterministic)
+}
+func (m *FieldTestMessage_Message) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FieldTestMessage_Message.Merge(m, src)
+}
+func (m *FieldTestMessage_Message) XXX_Size() int {
+	return xxx_messageInfo_FieldTestMessage_Message.Size(m)
+}
+func (m *FieldTestMessage_Message) XXX_DiscardUnknown() {
+	xxx_messageInfo_FieldTestMessage_Message.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FieldTestMessage_Message proto.InternalMessageInfo
+
 func init() {
 	proto.RegisterEnum("goproto.protoc.proto2.FieldTestMessage_Enum", FieldTestMessage_Enum_name, FieldTestMessage_Enum_value)
 }
diff --git a/cmd/protoc-gen-go/testdata/proto2/nested_messages.pb.go b/cmd/protoc-gen-go/testdata/proto2/nested_messages.pb.go
index 385351c..4f1470e 100644
--- a/cmd/protoc-gen-go/testdata/proto2/nested_messages.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/nested_messages.pb.go
@@ -19,6 +19,30 @@
 	XXX_sizecache        int32                 `json:"-"`
 }
 
+func (m *Layer1) Reset()         { *m = Layer1{} }
+func (m *Layer1) String() string { return proto.CompactTextString(m) }
+func (*Layer1) ProtoMessage()    {}
+func (*Layer1) Descriptor() ([]byte, []int) {
+	return fileDescriptor_7417ee157699d191, []int{0}
+}
+func (m *Layer1) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Layer1.Unmarshal(m, b)
+}
+func (m *Layer1) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Layer1.Marshal(b, m, deterministic)
+}
+func (m *Layer1) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Layer1.Merge(m, src)
+}
+func (m *Layer1) XXX_Size() int {
+	return xxx_messageInfo_Layer1.Size(m)
+}
+func (m *Layer1) XXX_DiscardUnknown() {
+	xxx_messageInfo_Layer1.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Layer1 proto.InternalMessageInfo
+
 type Layer1_Layer2 struct {
 	L3                   *Layer1_Layer2_Layer3 `protobuf:"bytes,1,opt,name=l3" json:"l3,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}              `json:"-"`
@@ -26,12 +50,60 @@
 	XXX_sizecache        int32                 `json:"-"`
 }
 
+func (m *Layer1_Layer2) Reset()         { *m = Layer1_Layer2{} }
+func (m *Layer1_Layer2) String() string { return proto.CompactTextString(m) }
+func (*Layer1_Layer2) ProtoMessage()    {}
+func (*Layer1_Layer2) Descriptor() ([]byte, []int) {
+	return fileDescriptor_7417ee157699d191, []int{0, 0}
+}
+func (m *Layer1_Layer2) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Layer1_Layer2.Unmarshal(m, b)
+}
+func (m *Layer1_Layer2) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Layer1_Layer2.Marshal(b, m, deterministic)
+}
+func (m *Layer1_Layer2) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Layer1_Layer2.Merge(m, src)
+}
+func (m *Layer1_Layer2) XXX_Size() int {
+	return xxx_messageInfo_Layer1_Layer2.Size(m)
+}
+func (m *Layer1_Layer2) XXX_DiscardUnknown() {
+	xxx_messageInfo_Layer1_Layer2.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Layer1_Layer2 proto.InternalMessageInfo
+
 type Layer1_Layer2_Layer3 struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *Layer1_Layer2_Layer3) Reset()         { *m = Layer1_Layer2_Layer3{} }
+func (m *Layer1_Layer2_Layer3) String() string { return proto.CompactTextString(m) }
+func (*Layer1_Layer2_Layer3) ProtoMessage()    {}
+func (*Layer1_Layer2_Layer3) Descriptor() ([]byte, []int) {
+	return fileDescriptor_7417ee157699d191, []int{0, 0, 0}
+}
+func (m *Layer1_Layer2_Layer3) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Layer1_Layer2_Layer3.Unmarshal(m, b)
+}
+func (m *Layer1_Layer2_Layer3) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Layer1_Layer2_Layer3.Marshal(b, m, deterministic)
+}
+func (m *Layer1_Layer2_Layer3) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Layer1_Layer2_Layer3.Merge(m, src)
+}
+func (m *Layer1_Layer2_Layer3) XXX_Size() int {
+	return xxx_messageInfo_Layer1_Layer2_Layer3.Size(m)
+}
+func (m *Layer1_Layer2_Layer3) XXX_DiscardUnknown() {
+	xxx_messageInfo_Layer1_Layer2_Layer3.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Layer1_Layer2_Layer3 proto.InternalMessageInfo
+
 func init() { proto.RegisterFile("proto2/nested_messages.proto", fileDescriptor_7417ee157699d191) }
 
 var fileDescriptor_7417ee157699d191 = []byte{
diff --git a/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go b/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go
index b2efe83..3c938bd 100644
--- a/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go
@@ -19,6 +19,30 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *Message) Reset()         { *m = Message{} }
+func (m *Message) String() string { return proto.CompactTextString(m) }
+func (*Message) ProtoMessage()    {}
+func (*Message) Descriptor() ([]byte, []int) {
+	return fileDescriptor_d756bbe8817c03c1, []int{0}
+}
+func (m *Message) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Message.Unmarshal(m, b)
+}
+func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Message.Marshal(b, m, deterministic)
+}
+func (m *Message) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Message.Merge(m, src)
+}
+func (m *Message) XXX_Size() int {
+	return xxx_messageInfo_Message.Size(m)
+}
+func (m *Message) XXX_DiscardUnknown() {
+	xxx_messageInfo_Message.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Message proto.InternalMessageInfo
+
 func init() { proto.RegisterFile("proto2/proto2.proto", fileDescriptor_d756bbe8817c03c1) }
 
 var fileDescriptor_d756bbe8817c03c1 = []byte{
diff --git a/cmd/protoc-gen-go/testdata/proto3/fields.pb.go b/cmd/protoc-gen-go/testdata/proto3/fields.pb.go
index 4d9f39c..9a2efbb 100644
--- a/cmd/protoc-gen-go/testdata/proto3/fields.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto3/fields.pb.go
@@ -56,12 +56,60 @@
 	XXX_sizecache        int32                     `json:"-"`
 }
 
+func (m *FieldTestMessage) Reset()         { *m = FieldTestMessage{} }
+func (m *FieldTestMessage) String() string { return proto.CompactTextString(m) }
+func (*FieldTestMessage) ProtoMessage()    {}
+func (*FieldTestMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1e3ea068187307c, []int{0}
+}
+func (m *FieldTestMessage) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_FieldTestMessage.Unmarshal(m, b)
+}
+func (m *FieldTestMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_FieldTestMessage.Marshal(b, m, deterministic)
+}
+func (m *FieldTestMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FieldTestMessage.Merge(m, src)
+}
+func (m *FieldTestMessage) XXX_Size() int {
+	return xxx_messageInfo_FieldTestMessage.Size(m)
+}
+func (m *FieldTestMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_FieldTestMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FieldTestMessage proto.InternalMessageInfo
+
 type FieldTestMessage_Message struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
 }
 
+func (m *FieldTestMessage_Message) Reset()         { *m = FieldTestMessage_Message{} }
+func (m *FieldTestMessage_Message) String() string { return proto.CompactTextString(m) }
+func (*FieldTestMessage_Message) ProtoMessage()    {}
+func (*FieldTestMessage_Message) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1e3ea068187307c, []int{0, 0}
+}
+func (m *FieldTestMessage_Message) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_FieldTestMessage_Message.Unmarshal(m, b)
+}
+func (m *FieldTestMessage_Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_FieldTestMessage_Message.Marshal(b, m, deterministic)
+}
+func (m *FieldTestMessage_Message) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FieldTestMessage_Message.Merge(m, src)
+}
+func (m *FieldTestMessage_Message) XXX_Size() int {
+	return xxx_messageInfo_FieldTestMessage_Message.Size(m)
+}
+func (m *FieldTestMessage_Message) XXX_DiscardUnknown() {
+	xxx_messageInfo_FieldTestMessage_Message.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FieldTestMessage_Message proto.InternalMessageInfo
+
 func init() {
 	proto.RegisterEnum("goproto.protoc.proto3.FieldTestMessage_Enum", FieldTestMessage_Enum_name, FieldTestMessage_Enum_value)
 }