cmd/protoc-gen-go: generate extensions

Generate everything related to extensions: extension descriptors,
XXX_InternalExtensions fields, etc.

Tweak the order in which we generate code for descriptors to ensure
consistent output with the previous protoc-gen-go.

Change Field.ContainingType to Field.ParentMessage, since we need to get
at the parent of both message fields and extensions (and the "containing
type" of an extension field is the extended message, under existing
terminology).

Change-Id: I5d045ca80536436e7c987bca3d8fb8c1e1521e55
Reviewed-on: https://go-review.googlesource.com/136155
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/cmd/protoc-gen-go/main.go b/cmd/protoc-gen-go/main.go
index a03ae36..0c1b119 100644
--- a/cmd/protoc-gen-go/main.go
+++ b/cmd/protoc-gen-go/main.go
@@ -56,6 +56,7 @@
 	descriptorVar string // var containing the gzipped FileDescriptorProto
 	allEnums      []*protogen.Enum
 	allMessages   []*protogen.Message
+	allExtensions []*protogen.Extension
 }
 
 func genFile(gen *protogen.Plugin, file *protogen.File) {
@@ -68,11 +69,19 @@
 		f.locationMap[key] = append(f.locationMap[key], loc)
 	}
 
+	// The different order for enums and extensions is to match the output
+	// of the previous implementation.
+	//
+	// TODO: Eventually make this consistent.
 	f.allEnums = append(f.allEnums, f.File.Enums...)
-	f.allMessages = append(f.allMessages, f.File.Messages...)
 	for _, message := range f.Messages {
-		f.initMessage(message)
+		walkMessage(message, func(message *protogen.Message) {
+			f.allMessages = append(f.allMessages, message)
+			f.allEnums = append(f.allEnums, message.Enums...)
+			f.allExtensions = append(f.allExtensions, message.Extensions...)
+		})
 	}
+	f.allExtensions = append(f.allExtensions, f.File.Extensions...)
 
 	// Determine the name of the var holding the file descriptor:
 	//
@@ -120,17 +129,20 @@
 	for _, message := range f.allMessages {
 		genMessage(gen, g, f, message)
 	}
+	for _, extension := range f.Extensions {
+		genExtension(gen, g, f, extension)
+	}
 
 	genInitFunction(gen, g, f)
 
 	genFileDescriptor(gen, g, f)
 }
 
-func (f *File) initMessage(message *protogen.Message) {
-	f.allEnums = append(f.allEnums, message.Enums...)
-	f.allMessages = append(f.allMessages, message.Messages...)
+// walkMessage calls f on message and all of its descendants.
+func walkMessage(message *protogen.Message, f func(*protogen.Message)) {
+	f(message)
 	for _, m := range message.Messages {
-		f.initMessage(m)
+		walkMessage(m, f)
 	}
 }
 
@@ -300,6 +312,18 @@
 		g.P(field.GoName, " ", goType, " `", strings.Join(tags, " "), "`")
 	}
 	g.P("XXX_NoUnkeyedLiteral struct{} `json:\"-\"`")
+
+	if message.Desc.ExtensionRanges().Len() > 0 {
+		var tags []string
+		if messageOptions(gen, message).GetMessageSetWireFormat() {
+			tags = append(tags, `protobuf_messageset:"1"`)
+		}
+		tags = append(tags, `json:"-"`)
+		g.P(protogen.GoIdent{
+			GoImportPath: protoPackage,
+			GoName:       "XXX_InternalExtensions",
+		}, " `", strings.Join(tags, " "), "`")
+	}
 	// TODO XXX_InternalExtensions
 	g.P("XXX_unrecognized []byte `json:\"-\"`")
 	g.P("XXX_sizecache int32 `json:\"-\"`")
@@ -323,7 +347,43 @@
 	g.P("func (*", message.GoIdent, ") Descriptor() ([]byte, []int) {")
 	g.P("return ", f.descriptorVar, ", []int{", strings.Join(indexes, ","), "}")
 	g.P("}")
-	// TODO: extension support methods
+	g.P()
+
+	// ExtensionRangeArray
+	if extranges := message.Desc.ExtensionRanges(); extranges.Len() > 0 {
+		if messageOptions(gen, message).GetMessageSetWireFormat() {
+			g.P("func (m *", message.GoIdent, ") MarshalJSON() ([]byte, error) {")
+			g.P("return ", protogen.GoIdent{
+				GoImportPath: protoPackage,
+				GoName:       "MarshalMessageSetJSON",
+			}, "(&m.XXX_InternalExtensions)")
+			g.P("}")
+			g.P("func (m *", message.GoIdent, ") UnmarshalJSON(buf []byte) error {")
+			g.P("return ", protogen.GoIdent{
+				GoImportPath: protoPackage,
+				GoName:       "UnmarshalMessageSetJSON",
+			}, "(buf, &m.XXX_InternalExtensions)")
+			g.P("}")
+			g.P()
+		}
+
+		protoExtRange := protogen.GoIdent{
+			GoImportPath: protoPackage,
+			GoName:       "ExtensionRange",
+		}
+		extRangeVar := "extRange_" + message.GoIdent.GoName
+		g.P("var ", extRangeVar, " = []", protoExtRange, " {")
+		for i := 0; i < extranges.Len(); i++ {
+			r := extranges.Get(i)
+			g.P("{Start:", r[0], ", End:", r[1]-1 /* inclusive */, "},")
+		}
+		g.P("}")
+		g.P()
+		g.P("func (*", message.GoIdent, ") ExtensionRangeArray() []", protoExtRange, " {")
+		g.P("return ", extRangeVar)
+		g.P("}")
+		g.P()
+	}
 
 	// Table-driven proto support.
 	//
@@ -449,6 +509,9 @@
 	if len(message.Oneofs) > 0 {
 		genOneofFuncs(gen, g, f, message)
 	}
+	for _, extension := range message.Extensions {
+		genExtension(gen, g, f, extension)
+	}
 }
 
 // fieldGoType returns the Go type used for a field.
@@ -621,10 +684,42 @@
 	return string(field.Desc.Name()) + ",omitempty"
 }
 
+func genExtension(gen *protogen.Plugin, g *protogen.GeneratedFile, f *File, extension *protogen.Extension) {
+	g.P("var ", extensionVar(f, extension), " = &", protogen.GoIdent{
+		GoImportPath: protoPackage,
+		GoName:       "ExtensionDesc",
+	}, "{")
+	g.P("ExtendedType: (*", extension.ExtendedType.GoIdent, ")(nil),")
+	goType, pointer := fieldGoType(g, extension)
+	if pointer {
+		goType = "*" + goType
+	}
+	g.P("ExtensionType: (", goType, ")(nil),")
+	g.P("Field: ", extension.Desc.Number(), ",")
+	g.P("Name: ", strconv.Quote(string(extension.Desc.FullName())), ",")
+	g.P("Tag: ", strconv.Quote(fieldProtobufTag(extension)), ",")
+	g.P("Filename: ", strconv.Quote(f.Desc.Path()), ",")
+	g.P("}")
+	g.P()
+}
+
+// extensionVar returns the var holding the ExtensionDesc for an extension.
+func extensionVar(f *File, extension *protogen.Extension) protogen.GoIdent {
+	name := "E_"
+	if extension.ParentMessage != nil {
+		name += extension.ParentMessage.GoIdent.GoName + "_"
+	}
+	name += extension.GoName
+	return protogen.GoIdent{
+		GoImportPath: f.GoImportPath,
+		GoName:       name,
+	}
+}
+
 // genInitFunction generates an init function that registers the types in the
 // generated file with the proto package.
 func genInitFunction(gen *protogen.Plugin, g *protogen.GeneratedFile, f *File) {
-	if len(f.allMessages) == 0 && len(f.allEnums) == 0 {
+	if len(f.allMessages) == 0 && len(f.allEnums) == 0 && len(f.allExtensions) == 0 {
 		return
 	}
 
@@ -668,6 +763,12 @@
 			GoName:       "RegisterEnum",
 		}, fmt.Sprintf("(%q, %s_name, %s_value)", enumRegistryName(enum), name, name))
 	}
+	for _, extension := range f.allExtensions {
+		g.P(protogen.GoIdent{
+			GoImportPath: protoPackage,
+			GoName:       "RegisterExtension",
+		}, "(", extensionVar(f, extension), ")")
+	}
 	g.P("}")
 	g.P()
 }
diff --git a/cmd/protoc-gen-go/oneof.go b/cmd/protoc-gen-go/oneof.go
index fa90b1a..98880ec 100644
--- a/cmd/protoc-gen-go/oneof.go
+++ b/cmd/protoc-gen-go/oneof.go
@@ -340,7 +340,7 @@
 // fieldOneofType returns the wrapper type used to represent a field in a oneof.
 func fieldOneofType(field *protogen.Field) protogen.GoIdent {
 	return protogen.GoIdent{
-		GoImportPath: field.ContainingType.GoIdent.GoImportPath,
-		GoName:       field.ContainingType.GoIdent.GoName + "_" + field.GoName,
+		GoImportPath: field.ParentMessage.GoIdent.GoImportPath,
+		GoName:       field.ParentMessage.GoIdent.GoName + "_" + field.GoName,
 	}
 }
diff --git a/cmd/protoc-gen-go/options.go b/cmd/protoc-gen-go/options.go
new file mode 100644
index 0000000..a3828ea
--- /dev/null
+++ b/cmd/protoc-gen-go/options.go
@@ -0,0 +1,41 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains functions for fetching the options for a protoreflect descriptor.
+//
+// TODO: Replace this with the appropriate protoreflect API, once it exists.
+
+package main
+
+import (
+	descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+	"google.golang.org/proto/protogen"
+	"google.golang.org/proto/reflect/protoreflect"
+)
+
+// messageOptions returns the MessageOptions for a message.
+func messageOptions(gen *protogen.Plugin, message *protogen.Message) *descpb.MessageOptions {
+	file, ok := descriptorFile(gen, message.Desc)
+	if !ok {
+		return nil
+	}
+	desc := file.Proto.MessageType[message.Path[1]]
+	for i := 3; i < len(message.Path); i += 2 {
+		desc = desc.NestedType[message.Path[1]]
+	}
+	return desc.GetOptions()
+}
+
+func descriptorFile(gen *protogen.Plugin, desc protoreflect.Descriptor) (*protogen.File, bool) {
+	for {
+		if fdesc, ok := desc.(protoreflect.FileDescriptor); ok {
+			return gen.FileByName(fdesc.Path())
+		}
+		var ok bool
+		desc, ok = desc.Parent()
+		if !ok {
+			return nil, false
+		}
+	}
+}
diff --git a/cmd/protoc-gen-go/testdata/comments/comments.pb.go b/cmd/protoc-gen-go/testdata/comments/comments.pb.go
index 22046f4..682a960 100644
--- a/cmd/protoc-gen-go/testdata/comments/comments.pb.go
+++ b/cmd/protoc-gen-go/testdata/comments/comments.pb.go
@@ -35,6 +35,7 @@
 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)
 }
@@ -53,37 +54,6 @@
 
 var xxx_messageInfo_Message1 proto.InternalMessageInfo
 
-// COMMENT: Message2
-type Message2 struct {
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	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: Message1A
 type Message1_Message1A struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -97,6 +67,7 @@
 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)
 }
@@ -128,6 +99,7 @@
 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)
 }
@@ -146,6 +118,38 @@
 
 var xxx_messageInfo_Message1_Message1B proto.InternalMessageInfo
 
+// COMMENT: Message2
+type Message2 struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	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:"-"`
@@ -159,6 +163,7 @@
 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)
 }
@@ -190,6 +195,7 @@
 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)
 }
@@ -210,9 +216,9 @@
 
 func init() {
 	proto.RegisterType((*Message1)(nil), "goproto.protoc.proto2.Message1")
-	proto.RegisterType((*Message2)(nil), "goproto.protoc.proto2.Message2")
 	proto.RegisterType((*Message1_Message1A)(nil), "goproto.protoc.proto2.Message1.Message1A")
 	proto.RegisterType((*Message1_Message1B)(nil), "goproto.protoc.proto2.Message1.Message1B")
+	proto.RegisterType((*Message2)(nil), "goproto.protoc.proto2.Message2")
 	proto.RegisterType((*Message2_Message2A)(nil), "goproto.protoc.proto2.Message2.Message2A")
 	proto.RegisterType((*Message2_Message2B)(nil), "goproto.protoc.proto2.Message2.Message2B")
 }
diff --git a/cmd/protoc-gen-go/testdata/extensions/base/base.pb.go b/cmd/protoc-gen-go/testdata/extensions/base/base.pb.go
new file mode 100644
index 0000000..8bbe3f2
--- /dev/null
+++ b/cmd/protoc-gen-go/testdata/extensions/base/base.pb.go
@@ -0,0 +1,141 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: extensions/base/base.proto
+
+package base
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type BaseMessage struct {
+	Field                        *string  `protobuf:"bytes,1,opt,name=field" json:"field,omitempty"`
+	XXX_NoUnkeyedLiteral         struct{} `json:"-"`
+	proto.XXX_InternalExtensions `json:"-"`
+	XXX_unrecognized             []byte `json:"-"`
+	XXX_sizecache                int32  `json:"-"`
+}
+
+func (m *BaseMessage) Reset()         { *m = BaseMessage{} }
+func (m *BaseMessage) String() string { return proto.CompactTextString(m) }
+func (*BaseMessage) ProtoMessage()    {}
+func (*BaseMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aebb28f8d5a04466, []int{0}
+}
+
+var extRange_BaseMessage = []proto.ExtensionRange{
+	{Start: 4, End: 9},
+	{Start: 16, End: 536870911},
+}
+
+func (*BaseMessage) ExtensionRangeArray() []proto.ExtensionRange {
+	return extRange_BaseMessage
+}
+
+func (m *BaseMessage) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_BaseMessage.Unmarshal(m, b)
+}
+func (m *BaseMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_BaseMessage.Marshal(b, m, deterministic)
+}
+func (m *BaseMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_BaseMessage.Merge(m, src)
+}
+func (m *BaseMessage) XXX_Size() int {
+	return xxx_messageInfo_BaseMessage.Size(m)
+}
+func (m *BaseMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_BaseMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_BaseMessage proto.InternalMessageInfo
+
+func (m *BaseMessage) GetField() string {
+	if m != nil && m.Field != nil {
+		return *m.Field
+	}
+	return ""
+}
+
+type MessageSetWireFormatMessage struct {
+	XXX_NoUnkeyedLiteral         struct{} `json:"-"`
+	proto.XXX_InternalExtensions `protobuf_messageset:"1" json:"-"`
+	XXX_unrecognized             []byte `json:"-"`
+	XXX_sizecache                int32  `json:"-"`
+}
+
+func (m *MessageSetWireFormatMessage) Reset()         { *m = MessageSetWireFormatMessage{} }
+func (m *MessageSetWireFormatMessage) String() string { return proto.CompactTextString(m) }
+func (*MessageSetWireFormatMessage) ProtoMessage()    {}
+func (*MessageSetWireFormatMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aebb28f8d5a04466, []int{1}
+}
+
+func (m *MessageSetWireFormatMessage) MarshalJSON() ([]byte, error) {
+	return proto.MarshalMessageSetJSON(&m.XXX_InternalExtensions)
+}
+func (m *MessageSetWireFormatMessage) UnmarshalJSON(buf []byte) error {
+	return proto.UnmarshalMessageSetJSON(buf, &m.XXX_InternalExtensions)
+}
+
+var extRange_MessageSetWireFormatMessage = []proto.ExtensionRange{
+	{Start: 100, End: 2147483646},
+}
+
+func (*MessageSetWireFormatMessage) ExtensionRangeArray() []proto.ExtensionRange {
+	return extRange_MessageSetWireFormatMessage
+}
+
+func (m *MessageSetWireFormatMessage) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_MessageSetWireFormatMessage.Unmarshal(m, b)
+}
+func (m *MessageSetWireFormatMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_MessageSetWireFormatMessage.Marshal(b, m, deterministic)
+}
+func (m *MessageSetWireFormatMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MessageSetWireFormatMessage.Merge(m, src)
+}
+func (m *MessageSetWireFormatMessage) XXX_Size() int {
+	return xxx_messageInfo_MessageSetWireFormatMessage.Size(m)
+}
+func (m *MessageSetWireFormatMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_MessageSetWireFormatMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MessageSetWireFormatMessage proto.InternalMessageInfo
+
+func init() {
+	proto.RegisterType((*BaseMessage)(nil), "goproto.protoc.extension.base.BaseMessage")
+	proto.RegisterType((*MessageSetWireFormatMessage)(nil), "goproto.protoc.extension.base.MessageSetWireFormatMessage")
+}
+
+func init() { proto.RegisterFile("extensions/base/base.proto", fileDescriptor_aebb28f8d5a04466) }
+
+var fileDescriptor_aebb28f8d5a04466 = []byte{
+	// 198 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4a, 0xad, 0x28, 0x49,
+	0xcd, 0x2b, 0xce, 0xcc, 0xcf, 0x2b, 0xd6, 0x4f, 0x4a, 0x2c, 0x4e, 0x05, 0x13, 0x7a, 0x05, 0x45,
+	0xf9, 0x25, 0xf9, 0x42, 0xb2, 0xe9, 0xf9, 0x60, 0x06, 0x84, 0x9b, 0xac, 0x07, 0x57, 0xaa, 0x07,
+	0x52, 0xa4, 0x64, 0xcc, 0xc5, 0xed, 0x94, 0x58, 0x9c, 0xea, 0x9b, 0x5a, 0x5c, 0x9c, 0x98, 0x9e,
+	0x2a, 0x24, 0xc2, 0xc5, 0x9a, 0x96, 0x99, 0x9a, 0x93, 0x22, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x19,
+	0x04, 0xe1, 0x68, 0xb1, 0x70, 0xb0, 0x08, 0x70, 0x69, 0x71, 0x70, 0x08, 0x08, 0x34, 0x34, 0x34,
+	0x34, 0x30, 0x29, 0x69, 0x73, 0x49, 0x43, 0x35, 0x04, 0xa7, 0x96, 0x84, 0x67, 0x16, 0xa5, 0xba,
+	0xe5, 0x17, 0xe5, 0x26, 0x96, 0x40, 0xc5, 0xb4, 0x38, 0x38, 0x52, 0x04, 0xfe, 0xff, 0xff, 0xff,
+	0x9f, 0xdd, 0x8a, 0x89, 0x83, 0xd1, 0xc9, 0x25, 0xca, 0x29, 0x3d, 0x3f, 0x3f, 0x3d, 0x27, 0x55,
+	0x2f, 0x3d, 0x3f, 0x27, 0x31, 0x2f, 0x5d, 0x2f, 0xbf, 0x28, 0x5d, 0x1f, 0xec, 0x18, 0xfd, 0xe4,
+	0xdc, 0x14, 0x08, 0x2b, 0x59, 0x37, 0x3d, 0x35, 0x4f, 0x37, 0x3d, 0x5f, 0xbf, 0x24, 0xb5, 0xb8,
+	0x24, 0x25, 0xb1, 0x24, 0x51, 0x1f, 0xcd, 0x47, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5f, 0x09,
+	0xf0, 0xbd, 0xe3, 0x00, 0x00, 0x00,
+}
diff --git a/cmd/protoc-gen-go/testdata/extensions/base/base.proto b/cmd/protoc-gen-go/testdata/extensions/base/base.proto
new file mode 100644
index 0000000..3c16d25
--- /dev/null
+++ b/cmd/protoc-gen-go/testdata/extensions/base/base.proto
@@ -0,0 +1,20 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+syntax = "proto2";
+
+package goproto.protoc.extension.base;
+
+option go_package = "google.golang.org/proto/cmd/protoc-gen-go/testdata/extensions/base";
+
+message BaseMessage {
+  optional string field = 1;
+  extensions 4 to 9;
+  extensions 16 to max;
+}
+
+message MessageSetWireFormatMessage {
+  option message_set_wire_format = true;
+  extensions 100 to max;
+}
diff --git a/cmd/protoc-gen-go/testdata/extensions/ext/ext.pb.go b/cmd/protoc-gen-go/testdata/extensions/ext/ext.pb.go
new file mode 100644
index 0000000..b419842
--- /dev/null
+++ b/cmd/protoc-gen-go/testdata/extensions/ext/ext.pb.go
@@ -0,0 +1,866 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: extensions/ext/ext.proto
+
+package ext
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	base "google.golang.org/proto/cmd/protoc-gen-go/testdata/extensions/base"
+	extra "google.golang.org/proto/cmd/protoc-gen-go/testdata/extensions/extra"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type Enum int32
+
+const (
+	Enum_ZERO Enum = 0
+)
+
+var Enum_name = map[int32]string{
+	0: "ZERO",
+}
+
+var Enum_value = map[string]int32{
+	"ZERO": 0,
+}
+
+func (x Enum) Enum() *Enum {
+	p := new(Enum)
+	*p = x
+	return p
+}
+
+func (x Enum) String() string {
+	return proto.EnumName(Enum_name, int32(x))
+}
+
+func (x *Enum) UnmarshalJSON(data []byte) error {
+	value, err := proto.UnmarshalJSONEnum(Enum_value, data, "Enum")
+	if err != nil {
+		return err
+	}
+	*x = Enum(value)
+	return nil
+}
+
+func (Enum) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_bf470ef4907b23cb, []int{0}
+}
+
+type Message struct {
+	Data                 []byte   `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	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_bf470ef4907b23cb, []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 (m *Message) GetData() []byte {
+	if m != nil {
+		return m.Data
+	}
+	return nil
+}
+
+type Message_M struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Message_M) Reset()         { *m = Message_M{} }
+func (m *Message_M) String() string { return proto.CompactTextString(m) }
+func (*Message_M) ProtoMessage()    {}
+func (*Message_M) Descriptor() ([]byte, []int) {
+	return fileDescriptor_bf470ef4907b23cb, []int{0, 0}
+}
+
+func (m *Message_M) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Message_M.Unmarshal(m, b)
+}
+func (m *Message_M) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Message_M.Marshal(b, m, deterministic)
+}
+func (m *Message_M) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Message_M.Merge(m, src)
+}
+func (m *Message_M) XXX_Size() int {
+	return xxx_messageInfo_Message_M.Size(m)
+}
+func (m *Message_M) XXX_DiscardUnknown() {
+	xxx_messageInfo_Message_M.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Message_M proto.InternalMessageInfo
+
+type ExtensionGroup struct {
+	ExtensionGroup       *string  `protobuf:"bytes,120,opt,name=extension_group,json=extensionGroup" json:"extension_group,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ExtensionGroup) Reset()         { *m = ExtensionGroup{} }
+func (m *ExtensionGroup) String() string { return proto.CompactTextString(m) }
+func (*ExtensionGroup) ProtoMessage()    {}
+func (*ExtensionGroup) Descriptor() ([]byte, []int) {
+	return fileDescriptor_bf470ef4907b23cb, []int{1}
+}
+
+func (m *ExtensionGroup) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ExtensionGroup.Unmarshal(m, b)
+}
+func (m *ExtensionGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ExtensionGroup.Marshal(b, m, deterministic)
+}
+func (m *ExtensionGroup) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ExtensionGroup.Merge(m, src)
+}
+func (m *ExtensionGroup) XXX_Size() int {
+	return xxx_messageInfo_ExtensionGroup.Size(m)
+}
+func (m *ExtensionGroup) XXX_DiscardUnknown() {
+	xxx_messageInfo_ExtensionGroup.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ExtensionGroup proto.InternalMessageInfo
+
+func (m *ExtensionGroup) GetExtensionGroup() string {
+	if m != nil && m.ExtensionGroup != nil {
+		return *m.ExtensionGroup
+	}
+	return ""
+}
+
+// Extend in the scope of another type.
+type ExtendingMessage struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ExtendingMessage) Reset()         { *m = ExtendingMessage{} }
+func (m *ExtendingMessage) String() string { return proto.CompactTextString(m) }
+func (*ExtendingMessage) ProtoMessage()    {}
+func (*ExtendingMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_bf470ef4907b23cb, []int{2}
+}
+
+func (m *ExtendingMessage) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ExtendingMessage.Unmarshal(m, b)
+}
+func (m *ExtendingMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ExtendingMessage.Marshal(b, m, deterministic)
+}
+func (m *ExtendingMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ExtendingMessage.Merge(m, src)
+}
+func (m *ExtendingMessage) XXX_Size() int {
+	return xxx_messageInfo_ExtendingMessage.Size(m)
+}
+func (m *ExtendingMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_ExtendingMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ExtendingMessage proto.InternalMessageInfo
+
+var E_ExtendingMessage_ExtendingMessageString = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         200,
+	Name:          "goproto.protoc.extension.ext.ExtendingMessage.extending_message_string",
+	Tag:           "bytes,200,opt,name=extending_message_string",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtendingMessage_ExtendingMessageSubmessage = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*ExtendingMessage_ExtendingMessageSubmessage)(nil),
+	Field:         201,
+	Name:          "goproto.protoc.extension.ext.ExtendingMessage.extending_message_submessage",
+	Tag:           "bytes,201,opt,name=extending_message_submessage",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+type ExtendingMessage_ExtendingMessageSubmessage struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ExtendingMessage_ExtendingMessageSubmessage) Reset() {
+	*m = ExtendingMessage_ExtendingMessageSubmessage{}
+}
+func (m *ExtendingMessage_ExtendingMessageSubmessage) String() string {
+	return proto.CompactTextString(m)
+}
+func (*ExtendingMessage_ExtendingMessageSubmessage) ProtoMessage() {}
+func (*ExtendingMessage_ExtendingMessageSubmessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_bf470ef4907b23cb, []int{2, 0}
+}
+
+func (m *ExtendingMessage_ExtendingMessageSubmessage) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ExtendingMessage_ExtendingMessageSubmessage.Unmarshal(m, b)
+}
+func (m *ExtendingMessage_ExtendingMessageSubmessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ExtendingMessage_ExtendingMessageSubmessage.Marshal(b, m, deterministic)
+}
+func (m *ExtendingMessage_ExtendingMessageSubmessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ExtendingMessage_ExtendingMessageSubmessage.Merge(m, src)
+}
+func (m *ExtendingMessage_ExtendingMessageSubmessage) XXX_Size() int {
+	return xxx_messageInfo_ExtendingMessage_ExtendingMessageSubmessage.Size(m)
+}
+func (m *ExtendingMessage_ExtendingMessageSubmessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_ExtendingMessage_ExtendingMessageSubmessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ExtendingMessage_ExtendingMessageSubmessage proto.InternalMessageInfo
+
+type RepeatedGroup struct {
+	RepeatedXGroup       []string `protobuf:"bytes,319,rep,name=repeated_x_group,json=repeatedXGroup" json:"repeated_x_group,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *RepeatedGroup) Reset()         { *m = RepeatedGroup{} }
+func (m *RepeatedGroup) String() string { return proto.CompactTextString(m) }
+func (*RepeatedGroup) ProtoMessage()    {}
+func (*RepeatedGroup) Descriptor() ([]byte, []int) {
+	return fileDescriptor_bf470ef4907b23cb, []int{3}
+}
+
+func (m *RepeatedGroup) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_RepeatedGroup.Unmarshal(m, b)
+}
+func (m *RepeatedGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_RepeatedGroup.Marshal(b, m, deterministic)
+}
+func (m *RepeatedGroup) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RepeatedGroup.Merge(m, src)
+}
+func (m *RepeatedGroup) XXX_Size() int {
+	return xxx_messageInfo_RepeatedGroup.Size(m)
+}
+func (m *RepeatedGroup) XXX_DiscardUnknown() {
+	xxx_messageInfo_RepeatedGroup.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_RepeatedGroup proto.InternalMessageInfo
+
+func (m *RepeatedGroup) GetRepeatedXGroup() []string {
+	if m != nil {
+		return m.RepeatedXGroup
+	}
+	return nil
+}
+
+// An extension of an extension.
+type Extendable struct {
+	XXX_NoUnkeyedLiteral         struct{} `json:"-"`
+	proto.XXX_InternalExtensions `json:"-"`
+	XXX_unrecognized             []byte `json:"-"`
+	XXX_sizecache                int32  `json:"-"`
+}
+
+func (m *Extendable) Reset()         { *m = Extendable{} }
+func (m *Extendable) String() string { return proto.CompactTextString(m) }
+func (*Extendable) ProtoMessage()    {}
+func (*Extendable) Descriptor() ([]byte, []int) {
+	return fileDescriptor_bf470ef4907b23cb, []int{4}
+}
+
+var extRange_Extendable = []proto.ExtensionRange{
+	{Start: 1, End: 536870911},
+}
+
+func (*Extendable) ExtensionRangeArray() []proto.ExtensionRange {
+	return extRange_Extendable
+}
+
+func (m *Extendable) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Extendable.Unmarshal(m, b)
+}
+func (m *Extendable) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Extendable.Marshal(b, m, deterministic)
+}
+func (m *Extendable) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Extendable.Merge(m, src)
+}
+func (m *Extendable) XXX_Size() int {
+	return xxx_messageInfo_Extendable.Size(m)
+}
+func (m *Extendable) XXX_DiscardUnknown() {
+	xxx_messageInfo_Extendable.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Extendable proto.InternalMessageInfo
+
+// Message set wire format.
+type MessageSetWireFormatExtension struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *MessageSetWireFormatExtension) Reset()         { *m = MessageSetWireFormatExtension{} }
+func (m *MessageSetWireFormatExtension) String() string { return proto.CompactTextString(m) }
+func (*MessageSetWireFormatExtension) ProtoMessage()    {}
+func (*MessageSetWireFormatExtension) Descriptor() ([]byte, []int) {
+	return fileDescriptor_bf470ef4907b23cb, []int{5}
+}
+
+func (m *MessageSetWireFormatExtension) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_MessageSetWireFormatExtension.Unmarshal(m, b)
+}
+func (m *MessageSetWireFormatExtension) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_MessageSetWireFormatExtension.Marshal(b, m, deterministic)
+}
+func (m *MessageSetWireFormatExtension) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MessageSetWireFormatExtension.Merge(m, src)
+}
+func (m *MessageSetWireFormatExtension) XXX_Size() int {
+	return xxx_messageInfo_MessageSetWireFormatExtension.Size(m)
+}
+func (m *MessageSetWireFormatExtension) XXX_DiscardUnknown() {
+	xxx_messageInfo_MessageSetWireFormatExtension.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MessageSetWireFormatExtension proto.InternalMessageInfo
+
+var E_MessageSetWireFormatExtension_MessageSetField = &proto.ExtensionDesc{
+	ExtendedType:  (*base.MessageSetWireFormatMessage)(nil),
+	ExtensionType: (*MessageSetWireFormatExtension)(nil),
+	Field:         100,
+	Name:          "goproto.protoc.extension.ext.MessageSetWireFormatExtension.message_set_field",
+	Tag:           "bytes,100,opt,name=message_set_field",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionBool = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         101,
+	Name:          "goproto.protoc.extension.ext.extension_bool",
+	Tag:           "varint,101,opt,name=extension_bool",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionEnum = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*Enum)(nil),
+	Field:         102,
+	Name:          "goproto.protoc.extension.ext.extension_enum",
+	Tag:           "varint,102,opt,name=extension_enum,enum=goproto.protoc.extension.ext.Enum",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionInt32 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         103,
+	Name:          "goproto.protoc.extension.ext.extension_int32",
+	Tag:           "varint,103,opt,name=extension_int32",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionSint32 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         104,
+	Name:          "goproto.protoc.extension.ext.extension_sint32",
+	Tag:           "zigzag32,104,opt,name=extension_sint32",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionUint32 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*uint32)(nil),
+	Field:         105,
+	Name:          "goproto.protoc.extension.ext.extension_uint32",
+	Tag:           "varint,105,opt,name=extension_uint32",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionInt64 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         106,
+	Name:          "goproto.protoc.extension.ext.extension_int64",
+	Tag:           "varint,106,opt,name=extension_int64",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionSint64 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         107,
+	Name:          "goproto.protoc.extension.ext.extension_sint64",
+	Tag:           "zigzag64,107,opt,name=extension_sint64",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionUint64 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*uint64)(nil),
+	Field:         108,
+	Name:          "goproto.protoc.extension.ext.extension_uint64",
+	Tag:           "varint,108,opt,name=extension_uint64",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionSfixed32 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*int32)(nil),
+	Field:         109,
+	Name:          "goproto.protoc.extension.ext.extension_sfixed32",
+	Tag:           "fixed32,109,opt,name=extension_sfixed32",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionFixed32 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*uint32)(nil),
+	Field:         110,
+	Name:          "goproto.protoc.extension.ext.extension_fixed32",
+	Tag:           "fixed32,110,opt,name=extension_fixed32",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionFloat = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*float32)(nil),
+	Field:         111,
+	Name:          "goproto.protoc.extension.ext.extension_float",
+	Tag:           "fixed32,111,opt,name=extension_float",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionSfixed64 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*int64)(nil),
+	Field:         112,
+	Name:          "goproto.protoc.extension.ext.extension_sfixed64",
+	Tag:           "fixed64,112,opt,name=extension_sfixed64",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionFixed64 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*uint64)(nil),
+	Field:         113,
+	Name:          "goproto.protoc.extension.ext.extension_fixed64",
+	Tag:           "fixed64,113,opt,name=extension_fixed64",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionDouble = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*float64)(nil),
+	Field:         114,
+	Name:          "goproto.protoc.extension.ext.extension_double",
+	Tag:           "fixed64,114,opt,name=extension_double",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionString = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         115,
+	Name:          "goproto.protoc.extension.ext.extension_string",
+	Tag:           "bytes,115,opt,name=extension_string",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtensionBytes = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]byte)(nil),
+	Field:         116,
+	Name:          "goproto.protoc.extension.ext.extension_bytes",
+	Tag:           "bytes,116,opt,name=extension_bytes",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_Extension_Message = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*Message)(nil),
+	Field:         117,
+	Name:          "goproto.protoc.extension.ext.extension_Message",
+	Tag:           "bytes,117,opt,name=extension_Message",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_Extension_MessageM = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*Message_M)(nil),
+	Field:         118,
+	Name:          "goproto.protoc.extension.ext.extension_MessageM",
+	Tag:           "bytes,118,opt,name=extension_MessageM",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_Extensiongroup = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*ExtensionGroup)(nil),
+	Field:         119,
+	Name:          "goproto.protoc.extension.ext.extensiongroup",
+	Tag:           "group,119,opt,name=ExtensionGroup",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtraMessage = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*extra.ExtraMessage)(nil),
+	Field:         9,
+	Name:          "goproto.protoc.extension.ext.extra_message",
+	Tag:           "bytes,9,opt,name=extra_message",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXBool = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]bool)(nil),
+	Field:         301,
+	Name:          "goproto.protoc.extension.ext.repeated_x_bool",
+	Tag:           "varint,301,rep,name=repeated_x_bool",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXEnum = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]Enum)(nil),
+	Field:         302,
+	Name:          "goproto.protoc.extension.ext.repeated_x_enum",
+	Tag:           "varint,302,rep,name=repeated_x_enum,enum=goproto.protoc.extension.ext.Enum",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXInt32 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]int32)(nil),
+	Field:         303,
+	Name:          "goproto.protoc.extension.ext.repeated_x_int32",
+	Tag:           "varint,303,rep,name=repeated_x_int32",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXSint32 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]int32)(nil),
+	Field:         304,
+	Name:          "goproto.protoc.extension.ext.repeated_x_sint32",
+	Tag:           "zigzag32,304,rep,name=repeated_x_sint32",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXUint32 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]uint32)(nil),
+	Field:         305,
+	Name:          "goproto.protoc.extension.ext.repeated_x_uint32",
+	Tag:           "varint,305,rep,name=repeated_x_uint32",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXInt64 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]int64)(nil),
+	Field:         306,
+	Name:          "goproto.protoc.extension.ext.repeated_x_int64",
+	Tag:           "varint,306,rep,name=repeated_x_int64",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXSint64 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]int64)(nil),
+	Field:         307,
+	Name:          "goproto.protoc.extension.ext.repeated_x_sint64",
+	Tag:           "zigzag64,307,rep,name=repeated_x_sint64",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXUint64 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]uint64)(nil),
+	Field:         308,
+	Name:          "goproto.protoc.extension.ext.repeated_x_uint64",
+	Tag:           "varint,308,rep,name=repeated_x_uint64",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXSfixed32 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]int32)(nil),
+	Field:         309,
+	Name:          "goproto.protoc.extension.ext.repeated_x_sfixed32",
+	Tag:           "fixed32,309,rep,name=repeated_x_sfixed32",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXFixed32 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]uint32)(nil),
+	Field:         310,
+	Name:          "goproto.protoc.extension.ext.repeated_x_fixed32",
+	Tag:           "fixed32,310,rep,name=repeated_x_fixed32",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXFloat = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]float32)(nil),
+	Field:         311,
+	Name:          "goproto.protoc.extension.ext.repeated_x_float",
+	Tag:           "fixed32,311,rep,name=repeated_x_float",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXSfixed64 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]int64)(nil),
+	Field:         312,
+	Name:          "goproto.protoc.extension.ext.repeated_x_sfixed64",
+	Tag:           "fixed64,312,rep,name=repeated_x_sfixed64",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXFixed64 = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]uint64)(nil),
+	Field:         313,
+	Name:          "goproto.protoc.extension.ext.repeated_x_fixed64",
+	Tag:           "fixed64,313,rep,name=repeated_x_fixed64",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXDouble = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]float64)(nil),
+	Field:         314,
+	Name:          "goproto.protoc.extension.ext.repeated_x_double",
+	Tag:           "fixed64,314,rep,name=repeated_x_double",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXString = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]string)(nil),
+	Field:         315,
+	Name:          "goproto.protoc.extension.ext.repeated_x_string",
+	Tag:           "bytes,315,rep,name=repeated_x_string",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedXBytes = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([][]byte)(nil),
+	Field:         316,
+	Name:          "goproto.protoc.extension.ext.repeated_x_bytes",
+	Tag:           "bytes,316,rep,name=repeated_x_bytes",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_RepeatedX_Message = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]*Message)(nil),
+	Field:         317,
+	Name:          "goproto.protoc.extension.ext.repeated_x_Message",
+	Tag:           "bytes,317,rep,name=repeated_x_Message",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_Repeatedgroup = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: ([]*RepeatedGroup)(nil),
+	Field:         318,
+	Name:          "goproto.protoc.extension.ext.repeatedgroup",
+	Tag:           "group,318,rep,name=RepeatedGroup",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtendableField = &proto.ExtensionDesc{
+	ExtendedType:  (*base.BaseMessage)(nil),
+	ExtensionType: (*Extendable)(nil),
+	Field:         400,
+	Name:          "goproto.protoc.extension.ext.extendable_field",
+	Tag:           "bytes,400,opt,name=extendable_field",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+var E_ExtendableStringField = &proto.ExtensionDesc{
+	ExtendedType:  (*Extendable)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         1,
+	Name:          "goproto.protoc.extension.ext.extendable_string_field",
+	Tag:           "bytes,1,opt,name=extendable_string_field",
+	Filename:      "extensions/ext/ext.proto",
+}
+
+func init() {
+	proto.RegisterType((*Message)(nil), "goproto.protoc.extension.ext.Message")
+	proto.RegisterType((*Message_M)(nil), "goproto.protoc.extension.ext.Message.M")
+	proto.RegisterType((*ExtensionGroup)(nil), "goproto.protoc.extension.ext.ExtensionGroup")
+	proto.RegisterType((*ExtendingMessage)(nil), "goproto.protoc.extension.ext.ExtendingMessage")
+	proto.RegisterType((*ExtendingMessage_ExtendingMessageSubmessage)(nil), "goproto.protoc.extension.ext.ExtendingMessage.ExtendingMessageSubmessage")
+	proto.RegisterType((*RepeatedGroup)(nil), "goproto.protoc.extension.ext.RepeatedGroup")
+	proto.RegisterType((*Extendable)(nil), "goproto.protoc.extension.ext.Extendable")
+	proto.RegisterType((*MessageSetWireFormatExtension)(nil), "goproto.protoc.extension.ext.MessageSetWireFormatExtension")
+	proto.RegisterEnum("goproto.protoc.extension.ext.Enum", Enum_name, Enum_value)
+	proto.RegisterExtension(E_ExtendingMessage_ExtendingMessageString)
+	proto.RegisterExtension(E_ExtendingMessage_ExtendingMessageSubmessage)
+	proto.RegisterExtension(E_MessageSetWireFormatExtension_MessageSetField)
+	proto.RegisterExtension(E_ExtensionBool)
+	proto.RegisterExtension(E_ExtensionEnum)
+	proto.RegisterExtension(E_ExtensionInt32)
+	proto.RegisterExtension(E_ExtensionSint32)
+	proto.RegisterExtension(E_ExtensionUint32)
+	proto.RegisterExtension(E_ExtensionInt64)
+	proto.RegisterExtension(E_ExtensionSint64)
+	proto.RegisterExtension(E_ExtensionUint64)
+	proto.RegisterExtension(E_ExtensionSfixed32)
+	proto.RegisterExtension(E_ExtensionFixed32)
+	proto.RegisterExtension(E_ExtensionFloat)
+	proto.RegisterExtension(E_ExtensionSfixed64)
+	proto.RegisterExtension(E_ExtensionFixed64)
+	proto.RegisterExtension(E_ExtensionDouble)
+	proto.RegisterExtension(E_ExtensionString)
+	proto.RegisterExtension(E_ExtensionBytes)
+	proto.RegisterExtension(E_Extension_Message)
+	proto.RegisterExtension(E_Extension_MessageM)
+	proto.RegisterExtension(E_Extensiongroup)
+	proto.RegisterExtension(E_ExtraMessage)
+	proto.RegisterExtension(E_RepeatedXBool)
+	proto.RegisterExtension(E_RepeatedXEnum)
+	proto.RegisterExtension(E_RepeatedXInt32)
+	proto.RegisterExtension(E_RepeatedXSint32)
+	proto.RegisterExtension(E_RepeatedXUint32)
+	proto.RegisterExtension(E_RepeatedXInt64)
+	proto.RegisterExtension(E_RepeatedXSint64)
+	proto.RegisterExtension(E_RepeatedXUint64)
+	proto.RegisterExtension(E_RepeatedXSfixed32)
+	proto.RegisterExtension(E_RepeatedXFixed32)
+	proto.RegisterExtension(E_RepeatedXFloat)
+	proto.RegisterExtension(E_RepeatedXSfixed64)
+	proto.RegisterExtension(E_RepeatedXFixed64)
+	proto.RegisterExtension(E_RepeatedXDouble)
+	proto.RegisterExtension(E_RepeatedXString)
+	proto.RegisterExtension(E_RepeatedXBytes)
+	proto.RegisterExtension(E_RepeatedX_Message)
+	proto.RegisterExtension(E_Repeatedgroup)
+	proto.RegisterExtension(E_ExtendableField)
+	proto.RegisterExtension(E_ExtendableStringField)
+}
+
+func init() { proto.RegisterFile("extensions/ext/ext.proto", fileDescriptor_bf470ef4907b23cb) }
+
+var fileDescriptor_bf470ef4907b23cb = []byte{
+	// 1105 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x98, 0x5b, 0x6f, 0xe3, 0x44,
+	0x14, 0xc7, 0x99, 0x24, 0xbb, 0xcd, 0x0e, 0x4d, 0x9b, 0x18, 0xb1, 0x44, 0x51, 0x91, 0x46, 0x91,
+	0xd0, 0x0e, 0x85, 0x75, 0xa5, 0x10, 0x45, 0xc2, 0x3c, 0x51, 0x68, 0xd1, 0x3e, 0x44, 0x08, 0x57,
+	0x55, 0xbb, 0xcb, 0x43, 0x70, 0xea, 0xa9, 0x31, 0x38, 0x9e, 0xe2, 0x0b, 0x1b, 0x1e, 0x58, 0x45,
+	0x7c, 0x02, 0xbe, 0x03, 0xcf, 0xdc, 0x6f, 0xcb, 0xfd, 0x09, 0x09, 0x5e, 0xf9, 0x44, 0x68, 0x66,
+	0x7c, 0x19, 0x3b, 0x69, 0x36, 0xe3, 0x87, 0x56, 0x93, 0xb1, 0xf3, 0x3b, 0xc7, 0xff, 0x73, 0xe2,
+	0xff, 0xb1, 0x61, 0x97, 0xcc, 0x23, 0xe2, 0x87, 0x2e, 0xf5, 0xc3, 0x03, 0x32, 0x8f, 0xd8, 0x9f,
+	0x7e, 0x15, 0xd0, 0x88, 0x6a, 0x7b, 0x0e, 0xe5, 0x0b, 0xf1, 0xf1, 0x42, 0xcf, 0x4e, 0x64, 0xab,
+	0x5e, 0x4f, 0xfa, 0xde, 0xd4, 0x0a, 0x09, 0xff, 0x27, 0x4e, 0xed, 0xed, 0x15, 0x99, 0x81, 0x25,
+	0xfe, 0x8b, 0xa3, 0xfd, 0x3e, 0xdc, 0x1a, 0x93, 0x30, 0xb4, 0x1c, 0xa2, 0x69, 0xb0, 0x61, 0x5b,
+	0x91, 0xd5, 0x05, 0x08, 0xe0, 0x6d, 0x93, 0xaf, 0x7b, 0x75, 0x08, 0xc6, 0xfd, 0x57, 0xe1, 0xce,
+	0x51, 0xca, 0x78, 0x2b, 0xa0, 0xf1, 0x95, 0x76, 0x07, 0xee, 0x66, 0xd4, 0x89, 0xc3, 0xb6, 0xba,
+	0x73, 0x04, 0xf0, 0x2d, 0x73, 0x87, 0x14, 0x4e, 0xec, 0xff, 0x57, 0x83, 0x6d, 0xfe, 0x5d, 0xdb,
+	0xf5, 0x9d, 0x24, 0x50, 0x6f, 0x0f, 0xf6, 0xca, 0x7b, 0x27, 0xf1, 0x74, 0x26, 0x56, 0x03, 0x92,
+	0xa8, 0xc0, 0x8e, 0x4e, 0x92, 0xcd, 0x49, 0x18, 0x05, 0xae, 0xef, 0x68, 0xfb, 0xfa, 0xb5, 0x32,
+	0xf0, 0x2b, 0x3e, 0xb4, 0x42, 0x92, 0x10, 0xbb, 0xff, 0x00, 0x9e, 0xd1, 0x6d, 0x52, 0x0e, 0xc5,
+	0x51, 0x83, 0xc7, 0x00, 0xee, 0xad, 0x88, 0x93, 0xe5, 0xa1, 0x14, 0xeb, 0x5f, 0x16, 0xeb, 0xe9,
+	0xc1, 0x3d, 0x7d, 0x5d, 0x95, 0xf4, 0xf2, 0x45, 0xeb, 0xd7, 0xab, 0x60, 0xf6, 0xc8, 0xb5, 0xc7,
+	0xfa, 0x06, 0x6c, 0x99, 0xe4, 0x8a, 0x58, 0x11, 0xb1, 0x45, 0x39, 0x5e, 0x84, 0xed, 0x20, 0xd9,
+	0x98, 0xcc, 0x93, 0x7a, 0xfc, 0x55, 0x43, 0x75, 0x56, 0x90, 0xf4, 0xc0, 0xb9, 0x28, 0xc8, 0x6d,
+	0x08, 0x45, 0x54, 0x6b, 0xea, 0x91, 0xfd, 0x66, 0x13, 0xb4, 0x17, 0x8b, 0xc5, 0xa2, 0xd6, 0xff,
+	0x1b, 0xc0, 0xe7, 0xd3, 0x48, 0x24, 0x3a, 0x73, 0x03, 0x72, 0x4c, 0x83, 0x99, 0x15, 0x65, 0x85,
+	0x1f, 0x7c, 0x01, 0x60, 0x27, 0x93, 0x89, 0x44, 0x93, 0x4b, 0x97, 0x78, 0xb6, 0x66, 0x3c, 0x41,
+	0xa5, 0x55, 0xcc, 0x54, 0x35, 0x9b, 0x8b, 0xf6, 0xda, 0x7a, 0xd1, 0xd6, 0x26, 0x65, 0xee, 0xce,
+	0xb2, 0xc3, 0xc7, 0x2c, 0x9f, 0xfd, 0x36, 0x6c, 0x1c, 0xf9, 0xf1, 0x4c, 0x6b, 0xc2, 0xc6, 0x83,
+	0x23, 0xf3, 0xed, 0xf6, 0x53, 0xc6, 0x3b, 0x30, 0x6f, 0xca, 0xc9, 0x94, 0x52, 0x4f, 0xa9, 0xb2,
+	0x04, 0x01, 0xdc, 0x34, 0x5b, 0xd9, 0x19, 0x87, 0x94, 0x7a, 0x46, 0x2c, 0x23, 0x09, 0x0b, 0xa7,
+	0x82, 0xbc, 0x44, 0x00, 0xef, 0x0c, 0xfa, 0x4f, 0xe8, 0x15, 0x3f, 0x9e, 0x49, 0x61, 0xd9, 0x47,
+	0xe3, 0x44, 0xfe, 0xd5, 0xb9, 0x7e, 0xf4, 0xca, 0x40, 0x29, 0xae, 0x83, 0x00, 0xbe, 0x21, 0xfd,
+	0x42, 0xef, 0x31, 0x82, 0x71, 0x0a, 0xdb, 0x39, 0x34, 0x54, 0xa7, 0xbe, 0x8f, 0x00, 0xee, 0x98,
+	0x79, 0x62, 0x27, 0xee, 0x32, 0x36, 0x56, 0xc7, 0xba, 0x08, 0xe0, 0x96, 0x84, 0x3d, 0x15, 0xd8,
+	0xb2, 0x04, 0xa3, 0xa1, 0x12, 0xf5, 0x03, 0x04, 0x70, 0xbd, 0x28, 0xc1, 0x68, 0xb8, 0x2c, 0x81,
+	0x22, 0xf5, 0x43, 0x04, 0xb0, 0x56, 0x92, 0xa0, 0x8c, 0x8d, 0xd5, 0xb1, 0x1e, 0x02, 0xb8, 0x51,
+	0x92, 0x60, 0x34, 0x34, 0xee, 0x43, 0x4d, 0xca, 0xf6, 0xd2, 0x9d, 0x13, 0x5b, 0x51, 0xdb, 0x19,
+	0x02, 0x78, 0xd7, 0xec, 0xe4, 0xf9, 0x26, 0x10, 0xe3, 0x0c, 0xe6, 0x9b, 0x93, 0x2a, 0x64, 0x1f,
+	0x01, 0xbc, 0x65, 0xe6, 0x97, 0x7d, 0x9c, 0x80, 0x0b, 0x65, 0xbb, 0xf4, 0xa8, 0x15, 0x29, 0x61,
+	0x29, 0x02, 0xb8, 0x26, 0x95, 0xed, 0x98, 0x11, 0x56, 0x09, 0xa1, 0xa8, 0xf0, 0x15, 0x02, 0xb8,
+	0xbd, 0x24, 0xc4, 0x68, 0xb8, 0x42, 0x08, 0x45, 0xf2, 0x47, 0x08, 0xe0, 0x9b, 0x65, 0x21, 0xca,
+	0x3d, 0x61, 0xd3, 0x78, 0xea, 0xa9, 0x19, 0x4d, 0x80, 0x00, 0x06, 0x52, 0x4f, 0xbc, 0xc9, 0x11,
+	0xa5, 0x0e, 0x56, 0xf7, 0xca, 0x90, 0x5b, 0xa5, 0xd4, 0xc1, 0x1c, 0x51, 0x2c, 0xdb, 0xf4, 0x93,
+	0x88, 0x84, 0x4a, 0xd4, 0x88, 0x0f, 0x12, 0x79, 0xd9, 0x0e, 0x19, 0xc1, 0x78, 0x24, 0x6b, 0x3b,
+	0xae, 0x60, 0xb6, 0x31, 0xb7, 0x8d, 0x17, 0x36, 0xb2, 0x0d, 0xa9, 0x04, 0xc9, 0x8e, 0xf1, 0x19,
+	0x90, 0xfb, 0x26, 0xd9, 0x1d, 0x2b, 0x65, 0xf0, 0x31, 0xcf, 0xe0, 0xce, 0x46, 0x19, 0xe8, 0x63,
+	0xa9, 0xc1, 0xd2, 0x68, 0xc6, 0x02, 0x48, 0x16, 0xc2, 0x0d, 0x5b, 0x29, 0x81, 0x87, 0x08, 0x60,
+	0x38, 0x78, 0x79, 0x83, 0x71, 0x23, 0x1b, 0xc5, 0xcc, 0x52, 0x3c, 0xe3, 0x53, 0xd8, 0xe2, 0x83,
+	0xe0, 0xa4, 0xca, 0xc0, 0x73, 0x8b, 0x2b, 0xb0, 0x3e, 0x81, 0xc0, 0x62, 0x29, 0x04, 0x56, 0x5a,
+	0x8a, 0x6d, 0x22, 0x7d, 0x62, 0xbd, 0x25, 0xcd, 0x2c, 0xca, 0xbe, 0xfc, 0x25, 0x1b, 0x6f, 0x9a,
+	0x66, 0x2b, 0x1b, 0x6f, 0xb8, 0x31, 0x3f, 0x2c, 0x40, 0x95, 0x9d, 0xf9, 0x2b, 0x06, 0xdd, 0xd0,
+	0x9a, 0xb3, 0xc0, 0xdc, 0x9a, 0x4f, 0x0b, 0x13, 0x98, 0xba, 0xdd, 0x7d, 0xcd, 0x22, 0xdf, 0x90,
+	0xa6, 0x35, 0x61, 0xce, 0x67, 0xb0, 0x23, 0x61, 0x2b, 0xb8, 0xf3, 0x37, 0x8c, 0xdb, 0x31, 0x33,
+	0x55, 0xce, 0x13, 0x7b, 0x2e, 0x82, 0x2b, 0xf8, 0xf3, 0xb7, 0x0c, 0xdc, 0x92, 0xc0, 0xa7, 0x99,
+	0xef, 0x17, 0x85, 0x50, 0xbc, 0x71, 0x7e, 0xc7, 0xb8, 0xf5, 0xa2, 0x10, 0xe2, 0x86, 0x5c, 0x12,
+	0x42, 0x91, 0xfb, 0x3d, 0xe3, 0x6a, 0x25, 0x21, 0x96, 0xc0, 0x15, 0x5c, 0xfa, 0x07, 0x06, 0x6e,
+	0x94, 0x84, 0x18, 0x0d, 0x8d, 0x77, 0xe1, 0x33, 0x72, 0xc6, 0x55, 0xdc, 0xf4, 0x47, 0x86, 0xde,
+	0x35, 0x3b, 0x79, 0xce, 0xa9, 0x51, 0xdf, 0x87, 0x9a, 0x04, 0xaf, 0xc2, 0xfe, 0x89, 0xb1, 0xb7,
+	0xcc, 0xac, 0x58, 0xe7, 0xa9, 0x55, 0x17, 0x0b, 0xa8, 0xee, 0xd5, 0x3f, 0x33, 0x70, 0x4d, 0x2a,
+	0xa0, 0x30, 0xeb, 0x55, 0x72, 0x28, 0x2a, 0xfd, 0x98, 0x91, 0xdb, 0x4b, 0x72, 0x88, 0x91, 0xa8,
+	0x2c, 0x87, 0x22, 0xfb, 0x17, 0xc6, 0xbe, 0x59, 0x96, 0x63, 0xa9, 0x3f, 0x2a, 0x38, 0xf6, 0xaf,
+	0x8c, 0x0c, 0xa4, 0xfe, 0x48, 0x2c, 0xbb, 0xd4, 0xd1, 0xea, 0x9e, 0xfd, 0x9b, 0x78, 0xc0, 0x93,
+	0x3a, 0x5a, 0x98, 0x76, 0xb1, 0x80, 0xea, 0xae, 0xfd, 0x3b, 0xe3, 0x6e, 0x4b, 0x05, 0x14, 0xb6,
+	0xbd, 0x00, 0x05, 0x91, 0xab, 0x18, 0xf7, 0x1f, 0x8c, 0xbc, 0xb9, 0x73, 0x67, 0x09, 0xa4, 0x96,
+	0xf1, 0x08, 0x66, 0x77, 0x5d, 0x75, 0xcb, 0xfc, 0x93, 0x05, 0x87, 0x83, 0x97, 0xd6, 0x07, 0x2f,
+	0x3c, 0x57, 0x9b, 0xc5, 0x70, 0x4c, 0x02, 0x31, 0x4e, 0xf0, 0x87, 0xe7, 0xe4, 0x01, 0x58, 0x25,
+	0x87, 0xcf, 0xeb, 0xdc, 0x36, 0xf1, 0x26, 0xaf, 0x09, 0x58, 0x88, 0x64, 0x22, 0xe3, 0x6b, 0xfe,
+	0x78, 0x6b, 0xbc, 0x07, 0x9f, 0x93, 0x32, 0x10, 0x5d, 0x93, 0x24, 0xb2, 0x31, 0xb5, 0x2b, 0x5e,
+	0x8c, 0x3c, 0x9b, 0x83, 0x44, 0xe7, 0xf0, 0x08, 0x87, 0x6f, 0x3c, 0x78, 0xdd, 0xa1, 0xd4, 0xf1,
+	0x88, 0xee, 0x50, 0xcf, 0xf2, 0x1d, 0x9d, 0x06, 0xce, 0x01, 0x27, 0x1e, 0x5c, 0xcc, 0x6c, 0xb1,
+	0xba, 0xb8, 0xeb, 0x10, 0xff, 0xae, 0x43, 0x0f, 0x22, 0x12, 0x46, 0xb6, 0x15, 0xf1, 0x57, 0x4a,
+	0xd2, 0x3b, 0xa6, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa5, 0xa0, 0x8e, 0xb5, 0xc8, 0x12, 0x00,
+	0x00,
+}
diff --git a/cmd/protoc-gen-go/testdata/extensions/ext/ext.proto b/cmd/protoc-gen-go/testdata/extensions/ext/ext.proto
new file mode 100644
index 0000000..3767b1e
--- /dev/null
+++ b/cmd/protoc-gen-go/testdata/extensions/ext/ext.proto
@@ -0,0 +1,103 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+syntax = "proto2";
+
+import "extensions/base/base.proto";
+import "extensions/extra/extra.proto";
+
+package goproto.protoc.extension.ext;
+
+option go_package = "google.golang.org/proto/cmd/protoc-gen-go/testdata/extensions/ext";
+
+message Message {
+  optional bytes data = 1;
+
+  message M {}
+}
+
+enum Enum {
+  ZERO = 0;
+}
+
+// Extend with various types.
+extend goproto.protoc.extension.base.BaseMessage {
+  optional bool      extension_bool     = 101;
+  optional Enum      extension_enum     = 102;
+  optional int32     extension_int32    = 103;
+  optional sint32    extension_sint32   = 104;
+  optional uint32    extension_uint32   = 105;
+  optional int64     extension_int64    = 106;
+  optional sint64    extension_sint64   = 107;
+  optional uint64    extension_uint64   = 108;
+  optional sfixed32  extension_sfixed32 = 109;
+  optional fixed32   extension_fixed32  = 110;
+  optional float     extension_float    = 111;
+  optional sfixed64  extension_sfixed64 = 112;
+  optional fixed64   extension_fixed64  = 113;
+  optional double    extension_double   = 114;
+  optional string    extension_string   = 115;
+  optional bytes     extension_bytes    = 116;
+  optional Message   extension_Message  = 117;
+  optional Message.M extension_MessageM = 118;
+  optional group ExtensionGroup = 119 {
+    optional string extension_group = 120;
+  }
+}
+
+// Extend with a foreign message.
+extend goproto.protoc.extension.base.BaseMessage {
+  optional goproto.protoc.extension.extra.ExtraMessage extra_message = 9;
+}
+
+// Extend in the scope of another type.
+message ExtendingMessage {
+  extend goproto.protoc.extension.base.BaseMessage {
+    optional string extending_message_string = 200;
+    optional ExtendingMessageSubmessage extending_message_submessage = 201;
+  }
+  message ExtendingMessageSubmessage {}
+}
+
+// Extend with repeated fields.
+extend goproto.protoc.extension.base.BaseMessage {
+  repeated bool     repeated_x_bool     = 301;
+  repeated Enum     repeated_x_enum     = 302;
+  repeated int32    repeated_x_int32    = 303;
+  repeated sint32   repeated_x_sint32   = 304;
+  repeated uint32   repeated_x_uint32   = 305;
+  repeated int64    repeated_x_int64    = 306;
+  repeated sint64   repeated_x_sint64   = 307;
+  repeated uint64   repeated_x_uint64   = 308;
+  repeated sfixed32 repeated_x_sfixed32 = 309;
+  repeated fixed32  repeated_x_fixed32  = 310;
+  repeated float    repeated_x_float    = 311;
+  repeated sfixed64 repeated_x_sfixed64 = 312;
+  repeated fixed64  repeated_x_fixed64  = 313;
+  repeated double   repeated_x_double   = 314;
+  repeated string   repeated_x_string   = 315;
+  repeated bytes    repeated_x_bytes    = 316;
+  repeated Message  repeated_x_Message  = 317;
+  repeated group RepeatedGroup = 318 {
+    repeated string repeated_x_group = 319;
+  }
+}
+
+// An extension of an extension.
+message Extendable {
+  extensions 1 to max;
+}
+extend goproto.protoc.extension.base.BaseMessage {
+  optional Extendable extendable_field = 400;
+}
+extend Extendable {
+  optional string extendable_string_field = 1;
+}
+
+// Message set wire format.
+message MessageSetWireFormatExtension {
+  extend goproto.protoc.extension.base.MessageSetWireFormatMessage {
+    optional MessageSetWireFormatExtension message_set_field = 100;
+  }
+}
diff --git a/cmd/protoc-gen-go/testdata/extensions/extra/extra.pb.go b/cmd/protoc-gen-go/testdata/extensions/extra/extra.pb.go
new file mode 100644
index 0000000..baf4a3d
--- /dev/null
+++ b/cmd/protoc-gen-go/testdata/extensions/extra/extra.pb.go
@@ -0,0 +1,79 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: extensions/extra/extra.proto
+
+package extra
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type ExtraMessage struct {
+	Data                 []byte   `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ExtraMessage) Reset()         { *m = ExtraMessage{} }
+func (m *ExtraMessage) String() string { return proto.CompactTextString(m) }
+func (*ExtraMessage) ProtoMessage()    {}
+func (*ExtraMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_496c2a5e9c1e8739, []int{0}
+}
+
+func (m *ExtraMessage) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ExtraMessage.Unmarshal(m, b)
+}
+func (m *ExtraMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ExtraMessage.Marshal(b, m, deterministic)
+}
+func (m *ExtraMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ExtraMessage.Merge(m, src)
+}
+func (m *ExtraMessage) XXX_Size() int {
+	return xxx_messageInfo_ExtraMessage.Size(m)
+}
+func (m *ExtraMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_ExtraMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ExtraMessage proto.InternalMessageInfo
+
+func (m *ExtraMessage) GetData() []byte {
+	if m != nil {
+		return m.Data
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterType((*ExtraMessage)(nil), "goproto.protoc.extension.extra.ExtraMessage")
+}
+
+func init() { proto.RegisterFile("extensions/extra/extra.proto", fileDescriptor_496c2a5e9c1e8739) }
+
+var fileDescriptor_496c2a5e9c1e8739 = []byte{
+	// 143 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x49, 0xad, 0x28, 0x49,
+	0xcd, 0x2b, 0xce, 0xcc, 0xcf, 0x2b, 0xd6, 0x4f, 0xad, 0x28, 0x29, 0x4a, 0x84, 0x90, 0x7a, 0x05,
+	0x45, 0xf9, 0x25, 0xf9, 0x42, 0x72, 0xe9, 0xf9, 0x60, 0x06, 0x84, 0x9b, 0xac, 0x07, 0x57, 0xac,
+	0x07, 0x56, 0xa5, 0xa4, 0xc4, 0xc5, 0xe3, 0x0a, 0x62, 0xf8, 0xa6, 0x16, 0x17, 0x27, 0xa6, 0xa7,
+	0x0a, 0x09, 0x71, 0xb1, 0xa4, 0x24, 0x96, 0x24, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x81,
+	0xd9, 0x4e, 0xae, 0x51, 0xce, 0xe9, 0xf9, 0xf9, 0xe9, 0x39, 0xa9, 0x7a, 0xe9, 0xf9, 0x39, 0x89,
+	0x79, 0xe9, 0x7a, 0xf9, 0x45, 0xe9, 0xfa, 0x60, 0xf3, 0xf4, 0x93, 0x73, 0x53, 0x20, 0xac, 0x64,
+	0xdd, 0xf4, 0xd4, 0x3c, 0xdd, 0xf4, 0x7c, 0xfd, 0x92, 0xd4, 0xe2, 0x12, 0x90, 0x2e, 0x7d, 0x74,
+	0x67, 0x01, 0x02, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xe3, 0x2f, 0xd9, 0xa9, 0x00, 0x00, 0x00,
+}
diff --git a/cmd/protoc-gen-go/testdata/extensions/extra/extra.proto b/cmd/protoc-gen-go/testdata/extensions/extra/extra.proto
new file mode 100644
index 0000000..84a4392
--- /dev/null
+++ b/cmd/protoc-gen-go/testdata/extensions/extra/extra.proto
@@ -0,0 +1,13 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+syntax = "proto2";
+
+package goproto.protoc.extension.extra;
+
+option go_package = "google.golang.org/proto/cmd/protoc-gen-go/testdata/extensions/extra";
+
+message ExtraMessage {
+  optional bytes data = 1;
+}
diff --git a/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go b/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go
index ee87a4f..570e348 100644
--- a/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go
+++ b/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go
@@ -66,6 +66,7 @@
 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)
 }
diff --git a/cmd/protoc-gen-go/testdata/imports/fmt/m.pb.go b/cmd/protoc-gen-go/testdata/imports/fmt/m.pb.go
index e58ba47..ec263db 100644
--- a/cmd/protoc-gen-go/testdata/imports/fmt/m.pb.go
+++ b/cmd/protoc-gen-go/testdata/imports/fmt/m.pb.go
@@ -32,6 +32,7 @@
 func (*M) Descriptor() ([]byte, []int) {
 	return fileDescriptor_72c126fcd452e392, []int{0}
 }
+
 func (m *M) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_M.Unmarshal(m, b)
 }
diff --git a/cmd/protoc-gen-go/testdata/imports/test_a_1/m1.pb.go b/cmd/protoc-gen-go/testdata/imports/test_a_1/m1.pb.go
index 36012e1..9043697 100644
--- a/cmd/protoc-gen-go/testdata/imports/test_a_1/m1.pb.go
+++ b/cmd/protoc-gen-go/testdata/imports/test_a_1/m1.pb.go
@@ -54,6 +54,7 @@
 func (*M1) Descriptor() ([]byte, []int) {
 	return fileDescriptor_c1091de3fa870a14, []int{0}
 }
+
 func (m *M1) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_M1.Unmarshal(m, b)
 }
@@ -85,6 +86,7 @@
 func (*M1_1) Descriptor() ([]byte, []int) {
 	return fileDescriptor_c1091de3fa870a14, []int{1}
 }
+
 func (m *M1_1) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_M1_1.Unmarshal(m, b)
 }
diff --git a/cmd/protoc-gen-go/testdata/imports/test_a_1/m2.pb.go b/cmd/protoc-gen-go/testdata/imports/test_a_1/m2.pb.go
index a87cecc..9b6cd05 100644
--- a/cmd/protoc-gen-go/testdata/imports/test_a_1/m2.pb.go
+++ b/cmd/protoc-gen-go/testdata/imports/test_a_1/m2.pb.go
@@ -32,6 +32,7 @@
 func (*M2) Descriptor() ([]byte, []int) {
 	return fileDescriptor_20cf27515c0d621c, []int{0}
 }
+
 func (m *M2) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_M2.Unmarshal(m, b)
 }
diff --git a/cmd/protoc-gen-go/testdata/imports/test_a_2/m3.pb.go b/cmd/protoc-gen-go/testdata/imports/test_a_2/m3.pb.go
index 437e3f8..61b5155 100644
--- a/cmd/protoc-gen-go/testdata/imports/test_a_2/m3.pb.go
+++ b/cmd/protoc-gen-go/testdata/imports/test_a_2/m3.pb.go
@@ -32,6 +32,7 @@
 func (*M3) Descriptor() ([]byte, []int) {
 	return fileDescriptor_ff9d8f834875c9c5, []int{0}
 }
+
 func (m *M3) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_M3.Unmarshal(m, b)
 }
diff --git a/cmd/protoc-gen-go/testdata/imports/test_a_2/m4.pb.go b/cmd/protoc-gen-go/testdata/imports/test_a_2/m4.pb.go
index 9f35f3f..19b0bd8 100644
--- a/cmd/protoc-gen-go/testdata/imports/test_a_2/m4.pb.go
+++ b/cmd/protoc-gen-go/testdata/imports/test_a_2/m4.pb.go
@@ -32,6 +32,7 @@
 func (*M4) Descriptor() ([]byte, []int) {
 	return fileDescriptor_fdd24f82f6c5a786, []int{0}
 }
+
 func (m *M4) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_M4.Unmarshal(m, b)
 }
diff --git a/cmd/protoc-gen-go/testdata/imports/test_b_1/m1.pb.go b/cmd/protoc-gen-go/testdata/imports/test_b_1/m1.pb.go
index a54118d..d15f4c9 100644
--- a/cmd/protoc-gen-go/testdata/imports/test_b_1/m1.pb.go
+++ b/cmd/protoc-gen-go/testdata/imports/test_b_1/m1.pb.go
@@ -32,6 +32,7 @@
 func (*M1) Descriptor() ([]byte, []int) {
 	return fileDescriptor_7f49573d035512a8, []int{0}
 }
+
 func (m *M1) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_M1.Unmarshal(m, b)
 }
diff --git a/cmd/protoc-gen-go/testdata/imports/test_b_1/m2.pb.go b/cmd/protoc-gen-go/testdata/imports/test_b_1/m2.pb.go
index 2b86237..66e66de 100644
--- a/cmd/protoc-gen-go/testdata/imports/test_b_1/m2.pb.go
+++ b/cmd/protoc-gen-go/testdata/imports/test_b_1/m2.pb.go
@@ -32,6 +32,7 @@
 func (*M2) Descriptor() ([]byte, []int) {
 	return fileDescriptor_a1becddceeb586f2, []int{0}
 }
+
 func (m *M2) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_M2.Unmarshal(m, b)
 }
diff --git a/cmd/protoc-gen-go/testdata/imports/test_import_a1m1.pb.go b/cmd/protoc-gen-go/testdata/imports/test_import_a1m1.pb.go
index 58e1437..6713a20 100644
--- a/cmd/protoc-gen-go/testdata/imports/test_import_a1m1.pb.go
+++ b/cmd/protoc-gen-go/testdata/imports/test_import_a1m1.pb.go
@@ -34,6 +34,7 @@
 func (*A1M1) Descriptor() ([]byte, []int) {
 	return fileDescriptor_3b904a47327455f3, []int{0}
 }
+
 func (m *A1M1) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_A1M1.Unmarshal(m, b)
 }
diff --git a/cmd/protoc-gen-go/testdata/imports/test_import_a1m2.pb.go b/cmd/protoc-gen-go/testdata/imports/test_import_a1m2.pb.go
index 0586065..a0a1588 100644
--- a/cmd/protoc-gen-go/testdata/imports/test_import_a1m2.pb.go
+++ b/cmd/protoc-gen-go/testdata/imports/test_import_a1m2.pb.go
@@ -34,6 +34,7 @@
 func (*A1M2) Descriptor() ([]byte, []int) {
 	return fileDescriptor_bdb27b114687957d, []int{0}
 }
+
 func (m *A1M2) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_A1M2.Unmarshal(m, b)
 }
diff --git a/cmd/protoc-gen-go/testdata/imports/test_import_all.pb.go b/cmd/protoc-gen-go/testdata/imports/test_import_all.pb.go
index 6722483..1746f9d 100644
--- a/cmd/protoc-gen-go/testdata/imports/test_import_all.pb.go
+++ b/cmd/protoc-gen-go/testdata/imports/test_import_all.pb.go
@@ -43,6 +43,7 @@
 func (*All) Descriptor() ([]byte, []int) {
 	return fileDescriptor_324466f0afc16f77, []int{0}
 }
+
 func (m *All) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_All.Unmarshal(m, b)
 }
diff --git a/cmd/protoc-gen-go/testdata/proto2/enum.pb.go b/cmd/protoc-gen-go/testdata/proto2/enum.pb.go
index 7842bc7..b592bd0 100644
--- a/cmd/protoc-gen-go/testdata/proto2/enum.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/enum.pb.go
@@ -267,6 +267,7 @@
 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)
 }
@@ -301,6 +302,7 @@
 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)
 }
diff --git a/cmd/protoc-gen-go/testdata/proto2/fields.pb.go b/cmd/protoc-gen-go/testdata/proto2/fields.pb.go
index 9f6421d..bba5924 100644
--- a/cmd/protoc-gen-go/testdata/proto2/fields.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/fields.pb.go
@@ -175,6 +175,7 @@
 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)
 }
@@ -1409,6 +1410,7 @@
 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)
 }
@@ -1447,6 +1449,7 @@
 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)
 }
@@ -1485,6 +1488,7 @@
 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)
 }
@@ -1523,6 +1527,7 @@
 func (*FieldTestMessage_OneofGroup) Descriptor() ([]byte, []int) {
 	return fileDescriptor_fd8a9d72b841fd68, []int{0, 6}
 }
+
 func (m *FieldTestMessage_OneofGroup) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_FieldTestMessage_OneofGroup.Unmarshal(m, b)
 }
@@ -1560,6 +1565,7 @@
 func (*FieldTestMessage_Message) Descriptor() ([]byte, []int) {
 	return fileDescriptor_fd8a9d72b841fd68, []int{0, 7}
 }
+
 func (m *FieldTestMessage_Message) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_FieldTestMessage_Message.Unmarshal(m, b)
 }
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 f06711d..1daa2eb 100644
--- a/cmd/protoc-gen-go/testdata/proto2/nested_messages.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/nested_messages.pb.go
@@ -34,6 +34,7 @@
 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)
 }
@@ -79,6 +80,7 @@
 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)
 }
@@ -116,6 +118,7 @@
 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)
 }
diff --git a/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go b/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go
index 1812234..a912199 100644
--- a/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go
@@ -34,6 +34,7 @@
 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)
 }
diff --git a/cmd/protoc-gen-go/testdata/proto3/fields.pb.go b/cmd/protoc-gen-go/testdata/proto3/fields.pb.go
index 26d8165..92d9e23 100644
--- a/cmd/protoc-gen-go/testdata/proto3/fields.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto3/fields.pb.go
@@ -74,6 +74,7 @@
 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)
 }
@@ -244,6 +245,7 @@
 func (*FieldTestMessage_Message) Descriptor() ([]byte, []int) {
 	return fileDescriptor_f1e3ea068187307c, []int{0, 3}
 }
+
 func (m *FieldTestMessage_Message) XXX_Unmarshal(b []byte) error {
 	return xxx_messageInfo_FieldTestMessage_Message.Unmarshal(m, b)
 }
diff --git a/protogen/protogen.go b/protogen/protogen.go
index ae31fd2..753325e 100644
--- a/protogen/protogen.go
+++ b/protogen/protogen.go
@@ -348,6 +348,7 @@
 	GoImportPath  GoImportPath  // import path of this file's Go package
 	Messages      []*Message    // top-level message declarations
 	Enums         []*Enum       // top-level enum declarations
+	Extensions    []*Extension  // top-level extension declarations
 	Generate      bool          // true if we should generate code for this file
 
 	// GeneratedFilenamePrefix is used to construct filenames for generated
@@ -397,8 +398,18 @@
 	for i, edescs := 0, desc.Enums(); i < edescs.Len(); i++ {
 		f.Enums = append(f.Enums, newEnum(gen, f, nil, edescs.Get(i)))
 	}
+	for i, extdescs := 0, desc.Extensions(); i < extdescs.Len(); i++ {
+		f.Extensions = append(f.Extensions, newField(gen, f, nil, extdescs.Get(i)))
+	}
 	for _, message := range f.Messages {
-		message.init(gen)
+		if err := message.init(gen); err != nil {
+			return nil, err
+		}
+	}
+	for _, extension := range f.Extensions {
+		if err := extension.init(gen); err != nil {
+			return nil, err
+		}
 	}
 	return f, nil
 }
@@ -427,12 +438,13 @@
 type Message struct {
 	Desc protoreflect.MessageDescriptor
 
-	GoIdent  GoIdent    // name of the generated Go type
-	Fields   []*Field   // message field declarations
-	Oneofs   []*Oneof   // oneof declarations
-	Messages []*Message // nested message declarations
-	Enums    []*Enum    // nested enum declarations
-	Path     []int32    // location path of this message
+	GoIdent    GoIdent      // name of the generated Go type
+	Fields     []*Field     // message field declarations
+	Oneofs     []*Oneof     // oneof declarations
+	Messages   []*Message   // nested message declarations
+	Enums      []*Enum      // nested enum declarations
+	Extensions []*Extension // nested extension declarations
+	Path       []int32      // location path of this message
 }
 
 func newMessage(gen *Plugin, f *File, parent *Message, desc protoreflect.MessageDescriptor) *Message {
@@ -460,6 +472,9 @@
 	for i, fdescs := 0, desc.Fields(); i < fdescs.Len(); i++ {
 		message.Fields = append(message.Fields, newField(gen, f, message, fdescs.Get(i)))
 	}
+	for i, extdescs := 0, desc.Extensions(); i < extdescs.Len(); i++ {
+		message.Extensions = append(message.Extensions, newField(gen, f, message, extdescs.Get(i)))
+	}
 
 	// Field name conflict resolution.
 	//
@@ -524,6 +539,11 @@
 	for _, oneof := range message.Oneofs {
 		oneof.init(gen, message)
 	}
+	for _, extension := range message.Extensions {
+		if err := extension.init(gen); err != nil {
+			return err
+		}
+	}
 	return nil
 }
 
@@ -536,19 +556,29 @@
 	// '{{GoName}}' and a getter method named 'Get{{GoName}}'.
 	GoName string
 
-	ContainingType *Message // message in which this field occurs
-	MessageType    *Message // type for message or group fields; nil otherwise
-	EnumType       *Enum    // type for enum fields; nil otherwise
-	OneofType      *Oneof   // containing oneof; nil if not part of a oneof
-	Path           []int32  // location path of this field
+	ParentMessage *Message // message in which this field is defined; nil if top-level extension
+	ExtendedType  *Message // extended message for extension fields; nil otherwise
+	MessageType   *Message // type for message or group fields; nil otherwise
+	EnumType      *Enum    // type for enum fields; nil otherwise
+	OneofType     *Oneof   // containing oneof; nil if not part of a oneof
+	Path          []int32  // location path of this field
 }
 
 func newField(gen *Plugin, f *File, message *Message, desc protoreflect.FieldDescriptor) *Field {
+	var path []int32
+	switch {
+	case desc.ExtendedType() != nil && message == nil:
+		path = []int32{fileExtensionField, int32(desc.Index())}
+	case desc.ExtendedType() != nil && message != nil:
+		path = pathAppend(message.Path, messageExtensionField, int32(desc.Index()))
+	default:
+		path = pathAppend(message.Path, messageFieldField, int32(desc.Index()))
+	}
 	field := &Field{
-		Desc:           desc,
-		GoName:         camelCase(string(desc.Name())),
-		ContainingType: message,
-		Path:           pathAppend(message.Path, messageFieldField, int32(desc.Index())),
+		Desc:          desc,
+		GoName:        camelCase(string(desc.Name())),
+		ParentMessage: message,
+		Path:          path,
 	}
 	if desc.OneofType() != nil {
 		field.OneofType = message.Oneofs[desc.OneofType().Index()]
@@ -556,6 +586,9 @@
 	return field
 }
 
+// Extension is an alias of Field for documentation.
+type Extension = Field
+
 func (field *Field) init(gen *Plugin) error {
 	desc := field.Desc
 	switch desc.Kind() {
@@ -574,6 +607,14 @@
 		}
 		field.EnumType = enum
 	}
+	if desc.ExtendedType() != nil {
+		mname := desc.ExtendedType().FullName()
+		message, ok := gen.messagesByName[mname]
+		if !ok {
+			return fmt.Errorf("field %v: no descriptor for type %v", desc.FullName(), mname)
+		}
+		field.ExtendedType = message
+	}
 	return nil
 }
 
@@ -581,18 +622,18 @@
 type Oneof struct {
 	Desc protoreflect.OneofDescriptor
 
-	GoName         string   // Go field name of this oneof
-	ContainingType *Message // message in which this oneof occurs
-	Fields         []*Field // fields that are part of this oneof
-	Path           []int32  // location path of this oneof
+	GoName        string   // Go field name of this oneof
+	ParentMessage *Message // message in which this oneof occurs
+	Fields        []*Field // fields that are part of this oneof
+	Path          []int32  // location path of this oneof
 }
 
 func newOneof(gen *Plugin, f *File, message *Message, desc protoreflect.OneofDescriptor) *Oneof {
 	return &Oneof{
-		Desc:           desc,
-		ContainingType: message,
-		GoName:         camelCase(string(desc.Name())),
-		Path:           pathAppend(message.Path, messageOneofField, int32(desc.Index())),
+		Desc:          desc,
+		ParentMessage: message,
+		GoName:        camelCase(string(desc.Name())),
+		Path:          pathAppend(message.Path, messageOneofField, int32(desc.Index())),
 	}
 }
 
@@ -782,14 +823,16 @@
 // See descriptor.proto for more information about this.
 const (
 	// field numbers in FileDescriptorProto
-	filePackageField = 2 // package
-	fileMessageField = 4 // message_type
-	fileEnumField    = 5 // enum_type
+	filePackageField   = 2 // package
+	fileMessageField   = 4 // message_type
+	fileEnumField      = 5 // enum_type
+	fileExtensionField = 7 // extension
 	// field numbers in DescriptorProto
-	messageFieldField   = 2 // field
-	messageMessageField = 3 // nested_type
-	messageEnumField    = 4 // enum_type
-	messageOneofField   = 8 // oneof_decl
+	messageFieldField     = 2 // field
+	messageMessageField   = 3 // nested_type
+	messageEnumField      = 4 // enum_type
+	messageExtensionField = 6 // extension
+	messageOneofField     = 8 // oneof_decl
 	// field numbers in EnumDescriptorProto
 	enumValueField = 2 // value
 )