cmd/protoc-gen-go: add support for protobuf reflection

Implement support in protoc-gen-go for generating messages and enums
that satisfy the v2 protobuf reflection interfaces. Specifically, the following
are added:
* top-level variable representing the file descriptor
* ProtoReflect method on enums (to implement protoV2.Enum)
* ProtoReflect method on messages (to implement protoV2.Message)

The following are not supported yet:
* resolving transitive dependencies for file imports
* Extension descriptors
* Service descriptors

The implementation approach creates a single array for all the message and enum
declarations and references sections of that array to complete dependencies.
Since protobuf declarations can form a graph (a message may depend on itself),
it is difficult to construct a graph as a single literal. One way is to use
placeholder descriptors, but that is not efficient as it requires encoding
the full name of each dependent enum and message and then later resolving it;
thus, both expanding the binary size and also increasing initialization cost.
Instead, we add a prototype.{Enum,Message}.Reference method to obtain a
descriptor reference for the purposes for satisfying dependencies.
As such, nested declarations and dependencies are populated in an init function.

Other changes to support the implementation:
* Added a protoimpl package to expose the MessageType type and also the
MessageTypeOf and EnumTypeOf helper functions.
* Added a protogen.File.GoIdent field to provide a suggested variable name
for the file descriptor.
* Added prototype.{Enum,Message}.Reference that provides a descriptor reference
for the purposes for satisfying cyclic dependencies.
* Added protoreflect.{Syntax,Cardinality,Kind}.GoString to obtain a Go source
identifier that represents the given constant.

Change-Id: I9455764882dee6ad10f251901e7d419091e8bf1d
Reviewed-on: https://go-review.googlesource.com/c/150074
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/cmd/protoc-gen-go-grpc/testdata/grpc/deprecation.pb.go b/cmd/protoc-gen-go-grpc/testdata/grpc/deprecation.pb.go
index 680d030..f07e521 100644
--- a/cmd/protoc-gen-go-grpc/testdata/grpc/deprecation.pb.go
+++ b/cmd/protoc-gen-go-grpc/testdata/grpc/deprecation.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -37,3 +40,24 @@
 	0x12, 0x4b, 0x12, 0xc1, 0x8e, 0x4e, 0x62, 0x03, 0x4b, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff,
 	0x8d, 0xbe, 0xc2, 0x16, 0xf5, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	var err error
+	Deprecation_ProtoFile, err = prototype.NewFile(&xxx_Deprecation_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Deprecation_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Deprecation_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "grpc/deprecation.proto",
+	Package: "goproto.protoc.grpc",
+	Imports: []protoreflect.FileImport{
+		{FileDescriptor: prototype.PlaceholderFile("grpc/grpc.proto", "goproto.protoc.grpc")},
+	},
+}
diff --git a/cmd/protoc-gen-go-grpc/testdata/grpc/grpc.pb.go b/cmd/protoc-gen-go-grpc/testdata/grpc/grpc.pb.go
index ec8ea4a..79ee7ee 100644
--- a/cmd/protoc-gen-go-grpc/testdata/grpc/grpc.pb.go
+++ b/cmd/protoc-gen-go-grpc/testdata/grpc/grpc.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Request struct{ m *Request }
+
+func (m *Request) ProtoReflect() protoreflect.Message {
+	return xxx_Request{m}
+}
+func (m xxx_Request) Type() protoreflect.MessageType {
+	return xxx_Grpc_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_Request) KnownFields() protoreflect.KnownFields {
+	return xxx_Grpc_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_Request) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Grpc_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_Request) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Request) ProtoMutable() {}
+
 func (m *Request) Reset()         { *m = Request{} }
 func (m *Request) String() string { return proto.CompactTextString(m) }
 func (*Request) ProtoMessage()    {}
@@ -57,6 +79,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Response struct{ m *Response }
+
+func (m *Response) ProtoReflect() protoreflect.Message {
+	return xxx_Response{m}
+}
+func (m xxx_Response) Type() protoreflect.MessageType {
+	return xxx_Grpc_ProtoFile_MessageTypes[1].Type
+}
+func (m xxx_Response) KnownFields() protoreflect.KnownFields {
+	return xxx_Grpc_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
+}
+func (m xxx_Response) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Grpc_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
+}
+func (m xxx_Response) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Response) ProtoMutable() {}
+
 func (m *Response) Reset()         { *m = Response{} }
 func (m *Response) String() string { return proto.CompactTextString(m) }
 func (*Response) ProtoMessage()    {}
@@ -106,3 +147,44 @@
 	0xa6, 0x24, 0x36, 0xb0, 0xa4, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x29, 0xd5, 0xc4, 0xd0, 0xba,
 	0x01, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Grpc_ProtoFile_FileDesc.Messages = xxx_Grpc_ProtoFile_MessageDescs[0:2]
+	var err error
+	Grpc_ProtoFile, err = prototype.NewFile(&xxx_Grpc_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Grpc_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Grpc_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "grpc/grpc.proto",
+	Package: "goproto.protoc.grpc",
+}
+var xxx_Grpc_ProtoFile_MessageTypes = [2]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Grpc_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Request)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Grpc_ProtoFile_MessageDescs[1].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Response)
+		},
+	)},
+}
+var xxx_Grpc_ProtoFile_MessageDescs = [2]prototype.Message{
+	{
+		Name: "Request",
+	},
+	{
+		Name: "Response",
+	},
+}
diff --git a/cmd/protoc-gen-go/internal_gengo/main.go b/cmd/protoc-gen-go/internal_gengo/main.go
index 2a53d95..435eb5b 100644
--- a/cmd/protoc-gen-go/internal_gengo/main.go
+++ b/cmd/protoc-gen-go/internal_gengo/main.go
@@ -42,6 +42,8 @@
 	allEnums      []*protogen.Enum
 	allMessages   []*protogen.Message
 	allExtensions []*protogen.Extension
+
+	fileReflect fileReflect
 }
 
 // GenerateFile generates the contents of a .pb.go file.
@@ -53,7 +55,7 @@
 	// The different order for enums and extensions is to match the output
 	// of the previous implementation.
 	//
-	// TODO: Eventually make this consistent.
+	// TODO: Eventually make this consistent (and remove fileReflect).
 	f.allEnums = append(f.allEnums, f.File.Enums...)
 	walkMessages(f.Messages, func(message *protogen.Message) {
 		f.allMessages = append(f.allMessages, message)
@@ -62,6 +64,9 @@
 	})
 	f.allExtensions = append(f.allExtensions, f.File.Extensions...)
 
+	// Initialize data structures needed for reflection.
+	f.fileReflect.init(f)
+
 	// Determine the name of the var holding the file descriptor:
 	//
 	//     fileDescriptor_<hash of filename>
@@ -121,6 +126,8 @@
 
 	genInitFunction(gen, g, f)
 	genFileDescriptor(gen, g, f)
+	genReflectInitFunction(gen, g, f)
+	genReflectFileDescriptor(gen, g, f)
 }
 
 // walkMessages calls f on each message and all of its descendants.
@@ -264,6 +271,10 @@
 	}
 	g.P(")")
 	g.P()
+
+	// Generate support for protobuf reflection.
+	genReflectEnum(gen, g, f, enum)
+
 	nameMap := enum.GoIdent.GoName + "_name"
 	g.P("var ", nameMap, " = map[int32]string{")
 	generated := make(map[protoreflect.EnumNumber]bool)
@@ -406,6 +417,9 @@
 	g.P("}")
 	g.P()
 
+	// Generate support for protobuf reflection.
+	genReflectMessage(gen, g, f, message)
+
 	// Reset
 	g.P("func (m *", message.GoIdent, ") Reset() { *m = ", message.GoIdent, "{} }")
 	// String
@@ -736,7 +750,7 @@
 // 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 *fileInfo) {
-	if len(f.allMessages) == 0 && len(f.allEnums) == 0 && len(f.allExtensions) == 0 {
+	if len(f.allEnums)+len(f.allMessages)+len(f.allExtensions) == 0 {
 		return
 	}
 
diff --git a/cmd/protoc-gen-go/internal_gengo/reflect.go b/cmd/protoc-gen-go/internal_gengo/reflect.go
new file mode 100644
index 0000000..a03373f
--- /dev/null
+++ b/cmd/protoc-gen-go/internal_gengo/reflect.go
@@ -0,0 +1,392 @@
+// 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.
+
+package internal_gengo
+
+import (
+	"fmt"
+	"math"
+	"reflect"
+	"strconv"
+	"strings"
+
+	"github.com/golang/protobuf/v2/protogen"
+	"github.com/golang/protobuf/v2/reflect/protoreflect"
+)
+
+// TODO: Remove this flag.
+const enableReflect = true
+
+// minimumVersion is minimum version of the v2 proto package that is required.
+// This is incremented every time the generated code relies on some property
+// in the proto package that was introduced in a later version.
+const minimumVersion = 0
+
+const (
+	protoimplPackage    = protogen.GoImportPath("github.com/golang/protobuf/v2/runtime/protoimpl")
+	protoreflectPackage = protogen.GoImportPath("github.com/golang/protobuf/v2/reflect/protoreflect")
+	prototypePackage    = protogen.GoImportPath("github.com/golang/protobuf/v2/reflect/prototype")
+)
+
+// TODO: Add support for proto options.
+
+// fileReflect is embedded in fileInfo to maintain state needed for reflection.
+//
+// TODO: Remove this when we have the freedom to change the order of
+// fileInfo.{allEnums,allMessages,allExtensions} to be a breadth-first search
+// to ensure that all declarations are coalesced together.
+type fileReflect struct {
+	allEnums         []*protogen.Enum
+	allEnumsByPtr    map[*protogen.Enum]int // value is index into allEnums
+	allMessages      []*protogen.Message
+	allMessagesByPtr map[*protogen.Message]int // value is index into allMessages
+}
+
+func (r *fileReflect) init(f *fileInfo) {
+	r.allEnums = append(r.allEnums, f.Enums...)
+	r.allMessages = append(r.allMessages, f.Messages...)
+	walkMessages(f.Messages, func(m *protogen.Message) {
+		r.allEnums = append(r.allEnums, m.Enums...)
+		r.allMessages = append(r.allMessages, m.Messages...)
+	})
+
+	// Derive a reverse mapping of enum and message pointers to their index
+	// in allEnums and allMessages.
+	if len(r.allEnums) > 0 {
+		r.allEnumsByPtr = make(map[*protogen.Enum]int)
+		for i, e := range r.allEnums {
+			r.allEnumsByPtr[e] = i
+		}
+	}
+	if len(r.allMessages) > 0 {
+		r.allMessagesByPtr = make(map[*protogen.Message]int)
+		for i, m := range r.allMessages {
+			r.allMessagesByPtr[m] = i
+		}
+	}
+}
+
+func genReflectInitFunction(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
+	if !enableReflect {
+		return
+	}
+
+	if len(f.fileReflect.allEnums)+len(f.fileReflect.allMessages)+len(f.allExtensions)+len(f.Services) == 0 {
+		return
+	}
+
+	g.P("func init() {")
+
+	// TODO: Fix up file imports to reference a protoreflect.FileDescriptor
+	// in a remote dependency. Since we cannot yet rely on the existence of
+	// a variable containing the file descriptor, we find a random message or
+	// enum the package and see if we can ascend to the parent file descriptor.
+
+	fileDescVar := fileDescVarName(f)
+	enumTypesVar := enumTypesVarName(f)
+	enumDescsVar := enumDescsVarName(f)
+	messageTypesVar := messageTypesVarName(f)
+	messageDescsVar := messageDescsVarName(f)
+
+	// Populate all declarations for messages and enums.
+	// These are not declared in the literals to avoid an initialization loop.
+	if enums := f.Enums; len(enums) > 0 {
+		i := f.fileReflect.allEnumsByPtr[enums[0]]
+		g.P(fileDescVar, ".Enums = ", enumDescsVar, "[", i, ":", i+len(enums), "]")
+	}
+	if messages := f.Messages; len(messages) > 0 {
+		i := f.fileReflect.allMessagesByPtr[messages[0]]
+		g.P(fileDescVar, ".Messages = ", messageDescsVar, "[", i, ":", i+len(messages), "]")
+	}
+	for i, message := range f.fileReflect.allMessages {
+		if enums := message.Enums; len(enums) > 0 {
+			j := f.fileReflect.allEnumsByPtr[enums[0]]
+			g.P(messageDescsVar, "[", i, "].Enums = ", enumDescsVar, "[", j, ":", j+len(enums), "]")
+		}
+		if messages := message.Messages; len(messages) > 0 {
+			j := f.fileReflect.allMessagesByPtr[messages[0]]
+			g.P(messageDescsVar, "[", i, "].Messages = ", messageDescsVar, "[", j, ":", j+len(messages), "]")
+		}
+	}
+
+	// Populate all dependencies for messages and enums.
+	//
+	// Externally defined enums and messages may or may not support the
+	// v2 protobuf reflection interfaces. The EnumTypeOf and MessageTypeOf
+	// helper functions checks for compliance and derives a v2 type from the
+	// legacy v1 enum or message if necessary.
+	for i, message := range f.fileReflect.allMessages {
+		for j, field := range message.Fields {
+			fieldSel := fmt.Sprintf("[%d].Fields[%d]", i, j)
+			if et := field.EnumType; et != nil {
+				idx, ok := f.fileReflect.allEnumsByPtr[et]
+				if ok {
+					// Locally defined enums are found in the type array.
+					g.P(messageDescsVar, fieldSel, ".EnumType = ", enumTypesVar, "[", idx, "]")
+				} else {
+					// Externally defined enums may need special handling.
+					g.P(messageDescsVar, fieldSel, ".EnumType = ", protoimplPackage.Ident("X"), ".EnumTypeOf(", et.GoIdent, "(0))")
+				}
+			}
+			if mt := field.MessageType; mt != nil {
+				idx, ok := f.fileReflect.allMessagesByPtr[mt]
+				if ok {
+					if mt.Desc.IsMapEntry() {
+						// Map entry types have no Go type generated for them.
+						g.P(messageDescsVar, fieldSel, ".MessageType = ", messageDescsVar, "[", idx, "].Reference()")
+					} else {
+						// Locally defined messages are found in the type array.
+						g.P(messageDescsVar, fieldSel, ".MessageType = ", messageTypesVar, "[", idx, "].Type")
+					}
+				} else {
+					// Externally defined messages may need special handling.
+					g.P(messageDescsVar, fieldSel, ".MessageType = ", protoimplPackage.Ident("X"), ".MessageTypeOf((*", mt.GoIdent, ")(nil))")
+				}
+			}
+		}
+	}
+	// TODO: Fix up extension dependencies.
+	// TODO: Fix up method dependencies.
+
+	// Construct the file descriptor.
+	g.P("var err error")
+	g.P(f.GoDescriptorIdent, ", err = ", prototypePackage.Ident("NewFile"), "(&", fileDescVarName(f), ")")
+	g.P("if err != nil { panic(err) }")
+
+	// TODO: Add v2 registration and stop v1 registration in genInitFunction.
+
+	g.P("}")
+}
+
+func genReflectFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) {
+	if !enableReflect {
+		return
+	}
+
+	// Emit a static check that enforces a minimum version of the proto package.
+	g.P("const _ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimplPackage.Ident("Version"), " - ", minimumVersion, ")")
+
+	g.P("var ", f.GoDescriptorIdent, " ", protoreflectPackage.Ident("FileDescriptor"))
+	g.P()
+
+	// Generate literal for file descriptor.
+	fileDescVar := fileDescVarName(f)
+	g.P("var ", fileDescVar, " = ", prototypePackage.Ident("File"), "{")
+	g.P("Syntax: ", protoreflectPackage.Ident(f.Desc.Syntax().GoString()), ",")
+	g.P("Path: ", strconv.Quote(f.Desc.Path()), ",")
+	g.P("Package: ", strconv.Quote(string(f.Desc.Package())), ",")
+	if imps := f.Desc.Imports(); imps.Len() > 0 {
+		g.P("Imports: ", "[]", protoreflectPackage.Ident("FileImport"), "{")
+		for i := 0; i < imps.Len(); i++ {
+			imp := imps.Get(i)
+			path := strconv.Quote(imp.Path())
+			pkg := strconv.Quote(string(imp.Package()))
+			var isPublic, isWeak string
+			if imp.IsPublic {
+				isPublic = ", IsPublic: true"
+			}
+			if imp.IsWeak {
+				isWeak = ", IsWeak: true"
+			}
+			// NOTE: FileDescriptor may be updated later by init.
+			g.P("{FileDescriptor: ", prototypePackage.Ident("PlaceholderFile"), "(", path, ", ", pkg, ")", isPublic, isWeak, "},")
+		}
+		g.P("},")
+	}
+	// NOTE: Messages, Enums, Extensions, and Services are populated by init.
+	g.P("}")
+
+	// Generate literals for enum descriptors.
+	if len(f.fileReflect.allEnums) > 0 {
+		enumTypesVar := enumTypesVarName(f)
+		enumDescsVar := enumDescsVarName(f)
+		g.P("var ", enumTypesVar, " = [", len(f.fileReflect.allEnums), "]", protoreflectPackage.Ident("EnumType"), "{")
+		for i, enum := range f.fileReflect.allEnums {
+			g.P(prototypePackage.Ident("GoEnum"), "(")
+			g.P(enumDescsVar, "[", i, "].Reference(),")
+			g.P("func(_ ", protoreflectPackage.Ident("EnumType"), ", n ", protoreflectPackage.Ident("EnumNumber"), ") ", protoreflectPackage.Ident("ProtoEnum"), " {")
+			g.P("return ", enum.GoIdent, "(n)")
+			g.P("},")
+			g.P("),")
+		}
+		g.P("}")
+
+		g.P("var ", enumDescsVar, " = [", len(f.fileReflect.allEnums), "]", prototypePackage.Ident("Enum"), "{")
+		for _, enum := range f.fileReflect.allEnums {
+			g.P("{")
+			g.P("Name: ", strconv.Quote(string(enum.Desc.Name())), ",")
+			g.P("Values: []", prototypePackage.Ident("EnumValue"), "{")
+			for _, value := range enum.Values {
+				g.P("{Name: ", strconv.Quote(string(value.Desc.Name())), ", Number: ", value.Desc.Number(), "},")
+			}
+			g.P("},")
+			g.P("},")
+		}
+		g.P("}")
+	}
+
+	// Generate literals for message descriptors.
+	if len(f.fileReflect.allMessages) > 0 {
+		messageTypesVar := messageTypesVarName(f)
+		messageDescsVar := messageDescsVarName(f)
+		g.P("var ", messageTypesVar, " = [", len(f.fileReflect.allMessages), "]", protoimplPackage.Ident("MessageType"), "{")
+		for i, message := range f.fileReflect.allMessages {
+			if message.Desc.IsMapEntry() {
+				// Map entry types have no Go type generated for them.
+				g.P("{ /* no message type for ", message.GoIdent, " */ },")
+				continue
+			}
+			g.P("{Type: ", prototypePackage.Ident("GoMessage"), "(")
+			g.P(messageDescsVar, "[", i, "].Reference(),")
+			g.P("func(", protoreflectPackage.Ident("MessageType"), ") ", protoreflectPackage.Ident("ProtoMessage"), " {")
+			g.P("return new(", message.GoIdent, ")")
+			g.P("},")
+			g.P(")},")
+		}
+		g.P("}")
+
+		g.P("var ", messageDescsVar, " = [", len(f.fileReflect.allMessages), "]", prototypePackage.Ident("Message"), "{")
+		for _, message := range f.fileReflect.allMessages {
+			g.P("{")
+			g.P("Name: ", strconv.Quote(string(message.Desc.Name())), ",")
+			if fields := message.Desc.Fields(); fields.Len() > 0 {
+				g.P("Fields: []", prototypePackage.Ident("Field"), "{")
+				for i := 0; i < fields.Len(); i++ {
+					field := fields.Get(i)
+					g.P("{")
+					g.P("Name: ", strconv.Quote(string(field.Name())), ",")
+					g.P("Number: ", field.Number(), ",")
+					g.P("Cardinality: ", protoreflectPackage.Ident(field.Cardinality().GoString()), ",")
+					g.P("Kind: ", protoreflectPackage.Ident(field.Kind().GoString()), ",")
+					// TODO: omit JSONName if it can be derived from Name?
+					g.P("JSONName: ", strconv.Quote(field.JSONName()), ",")
+					if field.HasDefault() {
+						v := field.Default().Interface()
+						typeName := reflect.TypeOf(v).Name()
+						valLit := fmt.Sprint(v)
+						switch v.(type) {
+						case protoreflect.EnumNumber:
+							typeName = "string"
+							valLit = strconv.Quote(string(field.DefaultEnumValue().Name()))
+						case float32, float64:
+							switch f := field.Default().Float(); {
+							case math.IsInf(f, -1):
+								valLit = g.QualifiedGoIdent(mathPackage.Ident("Inf")) + "(-1)"
+							case math.IsInf(f, +1):
+								valLit = g.QualifiedGoIdent(mathPackage.Ident("Inf")) + "(+1)"
+							case math.IsNaN(f):
+								valLit = g.QualifiedGoIdent(mathPackage.Ident("NaN")) + "()"
+							}
+						case string, []byte:
+							valLit = fmt.Sprintf("%q", v)
+						}
+						g.P("Default: ", protoreflectPackage.Ident("ValueOf"), "(", typeName, "(", valLit, ")),")
+					}
+					if oneof := field.OneofType(); oneof != nil {
+						g.P("OneofName: ", strconv.Quote(string(oneof.Name())), ",")
+					}
+					// NOTE: MessageType and EnumType are populated by init.
+					g.P("},")
+				}
+				g.P("},")
+			}
+			if oneofs := message.Desc.Oneofs(); oneofs.Len() > 0 {
+				g.P("Oneofs: []", prototypePackage.Ident("Oneof"), "{")
+				for i := 0; i < oneofs.Len(); i++ {
+					oneof := oneofs.Get(i)
+					g.P("{Name: ", strconv.Quote(string(oneof.Name())), "},")
+				}
+				g.P("},")
+			}
+			if extRanges := message.Desc.ExtensionRanges(); extRanges.Len() > 0 {
+				var ss []string
+				for i := 0; i < extRanges.Len(); i++ {
+					r := extRanges.Get(i)
+					ss = append(ss, fmt.Sprintf("{%d,%d}", r[0], r[1]))
+				}
+				g.P("ExtensionRanges: [][2]", protoreflectPackage.Ident("FieldNumber"), "{", strings.Join(ss, ","), "},")
+			}
+			// NOTE: Messages, Enums, and Extensions are populated by init.
+			g.P("},")
+		}
+		g.P("}")
+	}
+
+	// TODO: Add support for extensions.
+	// TODO: Add support for services.
+}
+
+func genReflectEnum(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, enum *protogen.Enum) {
+	if !enableReflect {
+		return
+	}
+
+	shadowType := shadowTypeName(enum.GoIdent)
+	g.P("type ", shadowType, " ", enum.GoIdent)
+	g.P()
+
+	idx := f.fileReflect.allEnumsByPtr[enum]
+	typesVar := enumTypesVarName(f)
+	g.P("func (e ", enum.GoIdent, ") ProtoReflect() ", protoreflectPackage.Ident("Enum"), " {")
+	g.P("return (", shadowType, ")(e)")
+	g.P("}")
+	g.P("func (e ", shadowType, ") Type() ", protoreflectPackage.Ident("EnumType"), " {")
+	g.P("return ", typesVar, "[", idx, "]")
+	g.P("}")
+	g.P("func (e ", shadowType, ") Number() ", protoreflectPackage.Ident("EnumNumber"), " {")
+	g.P("return ", protoreflectPackage.Ident("EnumNumber"), "(e)")
+	g.P("}")
+}
+
+func genReflectMessage(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, message *protogen.Message) {
+	if !enableReflect {
+		return
+	}
+
+	shadowType := shadowTypeName(message.GoIdent)
+	g.P("type ", shadowType, " struct{m *", message.GoIdent, "}")
+	g.P()
+
+	idx := f.fileReflect.allMessagesByPtr[message]
+	typesVar := messageTypesVarName(f)
+	g.P("func (m *", message.GoIdent, ") ProtoReflect() ", protoreflectPackage.Ident("Message"), " {")
+	g.P("return ", shadowType, "{m}")
+	g.P("}")
+	g.P("func (m ", shadowType, ") Type() ", protoreflectPackage.Ident("MessageType"), " {")
+	g.P("return ", typesVar, "[", idx, "].Type")
+	g.P("}")
+	g.P("func (m ", shadowType, ") KnownFields() ", protoreflectPackage.Ident("KnownFields"), " {")
+	g.P("return ", typesVar, "[", idx, "].KnownFieldsOf(m.m)")
+	g.P("}")
+	g.P("func (m ", shadowType, ") UnknownFields() ", protoreflectPackage.Ident("UnknownFields"), " {")
+	g.P("return ", typesVar, "[", idx, "].UnknownFieldsOf(m.m)")
+	g.P("}")
+	g.P("func (m ", shadowType, ") Interface() ", protoreflectPackage.Ident("ProtoMessage"), " {")
+	g.P("return m.m")
+	g.P("}")
+	g.P("func (m ", shadowType, ") ProtoMutable() {}")
+	g.P()
+}
+
+func fileDescVarName(f *fileInfo) string {
+	return "xxx_" + f.GoDescriptorIdent.GoName + "_FileDesc"
+}
+func enumTypesVarName(f *fileInfo) string {
+	return "xxx_" + f.GoDescriptorIdent.GoName + "_EnumTypes"
+}
+func enumDescsVarName(f *fileInfo) string {
+	return "xxx_" + f.GoDescriptorIdent.GoName + "_EnumDescs"
+}
+func messageTypesVarName(f *fileInfo) string {
+	return "xxx_" + f.GoDescriptorIdent.GoName + "_MessageTypes"
+}
+func messageDescsVarName(f *fileInfo) string {
+	return "xxx_" + f.GoDescriptorIdent.GoName + "_MessageDescs"
+}
+func extensionDescsVarName(f *fileInfo) string {
+	return "xxx_" + f.GoDescriptorIdent.GoName + "_ExtensionDescs"
+}
+func shadowTypeName(ident protogen.GoIdent) string {
+	return "xxx_" + ident.GoName
+}
diff --git a/cmd/protoc-gen-go/testdata/annotations/annotations.pb.go b/cmd/protoc-gen-go/testdata/annotations/annotations.pb.go
index 71a8e5d..f464c2c 100644
--- a/cmd/protoc-gen-go/testdata/annotations/annotations.pb.go
+++ b/cmd/protoc-gen-go/testdata/annotations/annotations.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,18 @@
 	AnnotationsTestEnum_ANNOTATIONS_TEST_ENUM_VALUE AnnotationsTestEnum = 0
 )
 
+type xxx_AnnotationsTestEnum AnnotationsTestEnum
+
+func (e AnnotationsTestEnum) ProtoReflect() protoreflect.Enum {
+	return (xxx_AnnotationsTestEnum)(e)
+}
+func (e xxx_AnnotationsTestEnum) Type() protoreflect.EnumType {
+	return xxx_Annotations_ProtoFile_EnumTypes[0]
+}
+func (e xxx_AnnotationsTestEnum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var AnnotationsTestEnum_name = map[int32]string{
 	0: "ANNOTATIONS_TEST_ENUM_VALUE",
 }
@@ -64,6 +79,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_AnnotationsTestMessage struct{ m *AnnotationsTestMessage }
+
+func (m *AnnotationsTestMessage) ProtoReflect() protoreflect.Message {
+	return xxx_AnnotationsTestMessage{m}
+}
+func (m xxx_AnnotationsTestMessage) Type() protoreflect.MessageType {
+	return xxx_Annotations_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_AnnotationsTestMessage) KnownFields() protoreflect.KnownFields {
+	return xxx_Annotations_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_AnnotationsTestMessage) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Annotations_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_AnnotationsTestMessage) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_AnnotationsTestMessage) ProtoMutable() {}
+
 func (m *AnnotationsTestMessage) Reset()         { *m = AnnotationsTestMessage{} }
 func (m *AnnotationsTestMessage) String() string { return proto.CompactTextString(m) }
 func (*AnnotationsTestMessage) ProtoMessage()    {}
@@ -119,3 +153,61 @@
 	0x49, 0x22, 0xb2, 0x7f, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x40, 0xd6, 0xe5, 0x9d, 0x09, 0x01,
 	0x00, 0x00,
 }
+
+func init() {
+	xxx_Annotations_ProtoFile_FileDesc.Enums = xxx_Annotations_ProtoFile_EnumDescs[0:1]
+	xxx_Annotations_ProtoFile_FileDesc.Messages = xxx_Annotations_ProtoFile_MessageDescs[0:1]
+	var err error
+	Annotations_ProtoFile, err = prototype.NewFile(&xxx_Annotations_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Annotations_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Annotations_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "annotations/annotations.proto",
+	Package: "goproto.protoc.annotations",
+}
+var xxx_Annotations_ProtoFile_EnumTypes = [1]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_Annotations_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return AnnotationsTestEnum(n)
+		},
+	),
+}
+var xxx_Annotations_ProtoFile_EnumDescs = [1]prototype.Enum{
+	{
+		Name: "AnnotationsTestEnum",
+		Values: []prototype.EnumValue{
+			{Name: "ANNOTATIONS_TEST_ENUM_VALUE", Number: 0},
+		},
+	},
+}
+var xxx_Annotations_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Annotations_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(AnnotationsTestMessage)
+		},
+	)},
+}
+var xxx_Annotations_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "AnnotationsTestMessage",
+		Fields: []prototype.Field{
+			{
+				Name:        "AnnotationsTestField",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "AnnotationsTestField",
+			},
+		},
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/comments/comments.pb.go b/cmd/protoc-gen-go/testdata/comments/comments.pb.go
index 62bfafd..dc96538 100644
--- a/cmd/protoc-gen-go/testdata/comments/comments.pb.go
+++ b/cmd/protoc-gen-go/testdata/comments/comments.pb.go
@@ -8,6 +8,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -37,6 +40,25 @@
 	XXX_sizecache        int32              `json:"-"`
 }
 
+type xxx_Message1 struct{ m *Message1 }
+
+func (m *Message1) ProtoReflect() protoreflect.Message {
+	return xxx_Message1{m}
+}
+func (m xxx_Message1) Type() protoreflect.MessageType {
+	return xxx_Comments_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_Message1) KnownFields() protoreflect.KnownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_Message1) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message1) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message1) ProtoMutable() {}
+
 func (m *Message1) Reset()         { *m = Message1{} }
 func (m *Message1) String() string { return proto.CompactTextString(m) }
 func (*Message1) ProtoMessage()    {}
@@ -107,6 +129,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Message1_Message1A struct{ m *Message1_Message1A }
+
+func (m *Message1_Message1A) ProtoReflect() protoreflect.Message {
+	return xxx_Message1_Message1A{m}
+}
+func (m xxx_Message1_Message1A) Type() protoreflect.MessageType {
+	return xxx_Comments_ProtoFile_MessageTypes[2].Type
+}
+func (m xxx_Message1_Message1A) KnownFields() protoreflect.KnownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[2].KnownFieldsOf(m.m)
+}
+func (m xxx_Message1_Message1A) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[2].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message1_Message1A) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message1_Message1A) ProtoMutable() {}
+
 func (m *Message1_Message1A) Reset()         { *m = Message1_Message1A{} }
 func (m *Message1_Message1A) String() string { return proto.CompactTextString(m) }
 func (*Message1_Message1A) ProtoMessage()    {}
@@ -139,6 +180,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Message1_Message1B struct{ m *Message1_Message1B }
+
+func (m *Message1_Message1B) ProtoReflect() protoreflect.Message {
+	return xxx_Message1_Message1B{m}
+}
+func (m xxx_Message1_Message1B) Type() protoreflect.MessageType {
+	return xxx_Comments_ProtoFile_MessageTypes[3].Type
+}
+func (m xxx_Message1_Message1B) KnownFields() protoreflect.KnownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[3].KnownFieldsOf(m.m)
+}
+func (m xxx_Message1_Message1B) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[3].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message1_Message1B) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message1_Message1B) ProtoMutable() {}
+
 func (m *Message1_Message1B) Reset()         { *m = Message1_Message1B{} }
 func (m *Message1_Message1B) String() string { return proto.CompactTextString(m) }
 func (*Message1_Message1B) ProtoMessage()    {}
@@ -171,6 +231,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Message2 struct{ m *Message2 }
+
+func (m *Message2) ProtoReflect() protoreflect.Message {
+	return xxx_Message2{m}
+}
+func (m xxx_Message2) Type() protoreflect.MessageType {
+	return xxx_Comments_ProtoFile_MessageTypes[1].Type
+}
+func (m xxx_Message2) KnownFields() protoreflect.KnownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
+}
+func (m xxx_Message2) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message2) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message2) ProtoMutable() {}
+
 func (m *Message2) Reset()         { *m = Message2{} }
 func (m *Message2) String() string { return proto.CompactTextString(m) }
 func (*Message2) ProtoMessage()    {}
@@ -203,6 +282,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Message2_Message2A struct{ m *Message2_Message2A }
+
+func (m *Message2_Message2A) ProtoReflect() protoreflect.Message {
+	return xxx_Message2_Message2A{m}
+}
+func (m xxx_Message2_Message2A) Type() protoreflect.MessageType {
+	return xxx_Comments_ProtoFile_MessageTypes[4].Type
+}
+func (m xxx_Message2_Message2A) KnownFields() protoreflect.KnownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[4].KnownFieldsOf(m.m)
+}
+func (m xxx_Message2_Message2A) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[4].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message2_Message2A) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message2_Message2A) ProtoMutable() {}
+
 func (m *Message2_Message2A) Reset()         { *m = Message2_Message2A{} }
 func (m *Message2_Message2A) String() string { return proto.CompactTextString(m) }
 func (*Message2_Message2A) ProtoMessage()    {}
@@ -235,6 +333,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Message2_Message2B struct{ m *Message2_Message2B }
+
+func (m *Message2_Message2B) ProtoReflect() protoreflect.Message {
+	return xxx_Message2_Message2B{m}
+}
+func (m xxx_Message2_Message2B) Type() protoreflect.MessageType {
+	return xxx_Comments_ProtoFile_MessageTypes[5].Type
+}
+func (m xxx_Message2_Message2B) KnownFields() protoreflect.KnownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[5].KnownFieldsOf(m.m)
+}
+func (m xxx_Message2_Message2B) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Comments_ProtoFile_MessageTypes[5].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message2_Message2B) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message2_Message2B) ProtoMutable() {}
+
 func (m *Message2_Message2B) Reset()         { *m = Message2_Message2B{} }
 func (m *Message2_Message2B) String() string { return proto.CompactTextString(m) }
 func (*Message2_Message2B) ProtoMessage()    {}
@@ -286,3 +403,102 @@
 	0x3d, 0x35, 0x4f, 0x37, 0x3d, 0x5f, 0xbf, 0x24, 0xb5, 0xb8, 0x24, 0x25, 0xb1, 0x24, 0x11, 0xee,
 	0x79, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x27, 0xeb, 0x57, 0xe0, 0x10, 0x01, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Comments_ProtoFile_FileDesc.Messages = xxx_Comments_ProtoFile_MessageDescs[0:2]
+	xxx_Comments_ProtoFile_MessageDescs[0].Messages = xxx_Comments_ProtoFile_MessageDescs[2:4]
+	xxx_Comments_ProtoFile_MessageDescs[1].Messages = xxx_Comments_ProtoFile_MessageDescs[4:6]
+	var err error
+	Comments_ProtoFile, err = prototype.NewFile(&xxx_Comments_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Comments_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Comments_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "comments/comments.proto",
+	Package: "goproto.protoc.comments",
+}
+var xxx_Comments_ProtoFile_MessageTypes = [6]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Comments_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message1)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Comments_ProtoFile_MessageDescs[1].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message2)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Comments_ProtoFile_MessageDescs[2].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message1_Message1A)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Comments_ProtoFile_MessageDescs[3].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message1_Message1B)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Comments_ProtoFile_MessageDescs[4].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message2_Message2A)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Comments_ProtoFile_MessageDescs[5].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message2_Message2B)
+		},
+	)},
+}
+var xxx_Comments_ProtoFile_MessageDescs = [6]prototype.Message{
+	{
+		Name: "Message1",
+		Fields: []prototype.Field{
+			{
+				Name:        "Field1A",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "Field1A",
+			},
+			{
+				Name:        "Oneof1AField1",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "Oneof1AField1",
+				OneofName:   "Oneof1a",
+			},
+		},
+		Oneofs: []prototype.Oneof{
+			{Name: "Oneof1a"},
+		},
+	},
+	{
+		Name: "Message2",
+	},
+	{
+		Name: "Message1A",
+	},
+	{
+		Name: "Message1B",
+	},
+	{
+		Name: "Message2A",
+	},
+	{
+		Name: "Message2B",
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/comments/deprecated.pb.go b/cmd/protoc-gen-go/testdata/comments/deprecated.pb.go
index 02cb7af..7948064 100644
--- a/cmd/protoc-gen-go/testdata/comments/deprecated.pb.go
+++ b/cmd/protoc-gen-go/testdata/comments/deprecated.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -25,6 +28,18 @@
 	DeprecatedEnum_DEPRECATED DeprecatedEnum = 0 // Deprecated: Do not use.
 )
 
+type xxx_DeprecatedEnum DeprecatedEnum
+
+func (e DeprecatedEnum) ProtoReflect() protoreflect.Enum {
+	return (xxx_DeprecatedEnum)(e)
+}
+func (e xxx_DeprecatedEnum) Type() protoreflect.EnumType {
+	return xxx_Deprecated_ProtoFile_EnumTypes[0]
+}
+func (e xxx_DeprecatedEnum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var DeprecatedEnum_name = map[int32]string{
 	0: "DEPRECATED",
 }
@@ -49,6 +64,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_DeprecatedMessage struct{ m *DeprecatedMessage }
+
+func (m *DeprecatedMessage) ProtoReflect() protoreflect.Message {
+	return xxx_DeprecatedMessage{m}
+}
+func (m xxx_DeprecatedMessage) Type() protoreflect.MessageType {
+	return xxx_Deprecated_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_DeprecatedMessage) KnownFields() protoreflect.KnownFields {
+	return xxx_Deprecated_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_DeprecatedMessage) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Deprecated_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_DeprecatedMessage) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_DeprecatedMessage) ProtoMutable() {}
+
 func (m *DeprecatedMessage) Reset()         { *m = DeprecatedMessage{} }
 func (m *DeprecatedMessage) String() string { return proto.CompactTextString(m) }
 func (*DeprecatedMessage) ProtoMessage()    {}
@@ -105,3 +139,61 @@
 	0x4b, 0x52, 0x12, 0x4b, 0x12, 0xf5, 0x61, 0xce, 0xde, 0xc1, 0xc8, 0x98, 0xc4, 0x06, 0x56, 0x63,
 	0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x39, 0xab, 0x43, 0x93, 0xf6, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Deprecated_ProtoFile_FileDesc.Enums = xxx_Deprecated_ProtoFile_EnumDescs[0:1]
+	xxx_Deprecated_ProtoFile_FileDesc.Messages = xxx_Deprecated_ProtoFile_MessageDescs[0:1]
+	var err error
+	Deprecated_ProtoFile, err = prototype.NewFile(&xxx_Deprecated_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Deprecated_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Deprecated_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "comments/deprecated.proto",
+	Package: "goproto.protoc.comments",
+}
+var xxx_Deprecated_ProtoFile_EnumTypes = [1]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_Deprecated_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return DeprecatedEnum(n)
+		},
+	),
+}
+var xxx_Deprecated_ProtoFile_EnumDescs = [1]prototype.Enum{
+	{
+		Name: "DeprecatedEnum",
+		Values: []prototype.EnumValue{
+			{Name: "DEPRECATED", Number: 0},
+		},
+	},
+}
+var xxx_Deprecated_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Deprecated_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(DeprecatedMessage)
+		},
+	)},
+}
+var xxx_Deprecated_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "DeprecatedMessage",
+		Fields: []prototype.Field{
+			{
+				Name:        "deprecated_field",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "deprecatedField",
+			},
+		},
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/extensions/base/base.pb.go b/cmd/protoc-gen-go/testdata/extensions/base/base.pb.go
index fd147a3..45f59fc 100644
--- a/cmd/protoc-gen-go/testdata/extensions/base/base.pb.go
+++ b/cmd/protoc-gen-go/testdata/extensions/base/base.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -28,6 +31,25 @@
 	XXX_sizecache                int32  `json:"-"`
 }
 
+type xxx_BaseMessage struct{ m *BaseMessage }
+
+func (m *BaseMessage) ProtoReflect() protoreflect.Message {
+	return xxx_BaseMessage{m}
+}
+func (m xxx_BaseMessage) Type() protoreflect.MessageType {
+	return xxx_Base_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_BaseMessage) KnownFields() protoreflect.KnownFields {
+	return xxx_Base_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_BaseMessage) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Base_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_BaseMessage) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_BaseMessage) ProtoMutable() {}
+
 func (m *BaseMessage) Reset()         { *m = BaseMessage{} }
 func (m *BaseMessage) String() string { return proto.CompactTextString(m) }
 func (*BaseMessage) ProtoMessage()    {}
@@ -76,6 +98,25 @@
 	XXX_sizecache                int32  `json:"-"`
 }
 
+type xxx_MessageSetWireFormatMessage struct{ m *MessageSetWireFormatMessage }
+
+func (m *MessageSetWireFormatMessage) ProtoReflect() protoreflect.Message {
+	return xxx_MessageSetWireFormatMessage{m}
+}
+func (m xxx_MessageSetWireFormatMessage) Type() protoreflect.MessageType {
+	return xxx_Base_ProtoFile_MessageTypes[1].Type
+}
+func (m xxx_MessageSetWireFormatMessage) KnownFields() protoreflect.KnownFields {
+	return xxx_Base_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
+}
+func (m xxx_MessageSetWireFormatMessage) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Base_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
+}
+func (m xxx_MessageSetWireFormatMessage) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_MessageSetWireFormatMessage) ProtoMutable() {}
+
 func (m *MessageSetWireFormatMessage) Reset()         { *m = MessageSetWireFormatMessage{} }
 func (m *MessageSetWireFormatMessage) String() string { return proto.CompactTextString(m) }
 func (*MessageSetWireFormatMessage) ProtoMessage()    {}
@@ -132,3 +173,55 @@
 	0x3d, 0x5f, 0xbf, 0x24, 0xb5, 0xb8, 0x24, 0x25, 0xb1, 0x24, 0x51, 0x1f, 0xcd, 0x5f, 0x80, 0x00,
 	0x00, 0x00, 0xff, 0xff, 0x1c, 0x75, 0xde, 0x5a, 0xe9, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Base_ProtoFile_FileDesc.Messages = xxx_Base_ProtoFile_MessageDescs[0:2]
+	var err error
+	Base_ProtoFile, err = prototype.NewFile(&xxx_Base_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Base_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Base_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "extensions/base/base.proto",
+	Package: "goproto.protoc.extension.base",
+}
+var xxx_Base_ProtoFile_MessageTypes = [2]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Base_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(BaseMessage)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Base_ProtoFile_MessageDescs[1].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(MessageSetWireFormatMessage)
+		},
+	)},
+}
+var xxx_Base_ProtoFile_MessageDescs = [2]prototype.Message{
+	{
+		Name: "BaseMessage",
+		Fields: []prototype.Field{
+			{
+				Name:        "field",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "field",
+			},
+		},
+		ExtensionRanges: [][2]protoreflect.FieldNumber{{4, 10}, {16, 536870912}},
+	},
+	{
+		Name:            "MessageSetWireFormatMessage",
+		ExtensionRanges: [][2]protoreflect.FieldNumber{{100, 2147483647}},
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/extensions/ext/ext.pb.go b/cmd/protoc-gen-go/testdata/extensions/ext/ext.pb.go
index cc35967..38dd2d4 100644
--- a/cmd/protoc-gen-go/testdata/extensions/ext/ext.pb.go
+++ b/cmd/protoc-gen-go/testdata/extensions/ext/ext.pb.go
@@ -8,6 +8,9 @@
 	proto "github.com/golang/protobuf/proto"
 	base "github.com/golang/protobuf/v2/cmd/protoc-gen-go/testdata/extensions/base"
 	extra "github.com/golang/protobuf/v2/cmd/protoc-gen-go/testdata/extensions/extra"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -28,6 +31,18 @@
 	Enum_ZERO Enum = 0
 )
 
+type xxx_Enum Enum
+
+func (e Enum) ProtoReflect() protoreflect.Enum {
+	return (xxx_Enum)(e)
+}
+func (e xxx_Enum) Type() protoreflect.EnumType {
+	return xxx_Ext_ProtoFile_EnumTypes[0]
+}
+func (e xxx_Enum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var Enum_name = map[int32]string{
 	0: "ZERO",
 }
@@ -66,6 +81,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Message struct{ m *Message }
+
+func (m *Message) ProtoReflect() protoreflect.Message {
+	return xxx_Message{m}
+}
+func (m xxx_Message) Type() protoreflect.MessageType {
+	return xxx_Ext_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_Message) KnownFields() protoreflect.KnownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_Message) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message) ProtoMutable() {}
+
 func (m *Message) Reset()         { *m = Message{} }
 func (m *Message) String() string { return proto.CompactTextString(m) }
 func (*Message) ProtoMessage()    {}
@@ -104,6 +138,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Message_M struct{ m *Message_M }
+
+func (m *Message_M) ProtoReflect() protoreflect.Message {
+	return xxx_Message_M{m}
+}
+func (m xxx_Message_M) Type() protoreflect.MessageType {
+	return xxx_Ext_ProtoFile_MessageTypes[6].Type
+}
+func (m xxx_Message_M) KnownFields() protoreflect.KnownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[6].KnownFieldsOf(m.m)
+}
+func (m xxx_Message_M) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[6].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message_M) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message_M) ProtoMutable() {}
+
 func (m *Message_M) Reset()         { *m = Message_M{} }
 func (m *Message_M) String() string { return proto.CompactTextString(m) }
 func (*Message_M) ProtoMessage()    {}
@@ -136,6 +189,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_ExtensionGroup struct{ m *ExtensionGroup }
+
+func (m *ExtensionGroup) ProtoReflect() protoreflect.Message {
+	return xxx_ExtensionGroup{m}
+}
+func (m xxx_ExtensionGroup) Type() protoreflect.MessageType {
+	return xxx_Ext_ProtoFile_MessageTypes[1].Type
+}
+func (m xxx_ExtensionGroup) KnownFields() protoreflect.KnownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
+}
+func (m xxx_ExtensionGroup) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
+}
+func (m xxx_ExtensionGroup) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_ExtensionGroup) ProtoMutable() {}
+
 func (m *ExtensionGroup) Reset()         { *m = ExtensionGroup{} }
 func (m *ExtensionGroup) String() string { return proto.CompactTextString(m) }
 func (*ExtensionGroup) ProtoMessage()    {}
@@ -175,6 +247,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_ExtendingMessage struct{ m *ExtendingMessage }
+
+func (m *ExtendingMessage) ProtoReflect() protoreflect.Message {
+	return xxx_ExtendingMessage{m}
+}
+func (m xxx_ExtendingMessage) Type() protoreflect.MessageType {
+	return xxx_Ext_ProtoFile_MessageTypes[2].Type
+}
+func (m xxx_ExtendingMessage) KnownFields() protoreflect.KnownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[2].KnownFieldsOf(m.m)
+}
+func (m xxx_ExtendingMessage) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[2].UnknownFieldsOf(m.m)
+}
+func (m xxx_ExtendingMessage) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_ExtendingMessage) ProtoMutable() {}
+
 func (m *ExtendingMessage) Reset()         { *m = ExtendingMessage{} }
 func (m *ExtendingMessage) String() string { return proto.CompactTextString(m) }
 func (*ExtendingMessage) ProtoMessage()    {}
@@ -224,6 +315,27 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_ExtendingMessage_ExtendingMessageSubmessage struct {
+	m *ExtendingMessage_ExtendingMessageSubmessage
+}
+
+func (m *ExtendingMessage_ExtendingMessageSubmessage) ProtoReflect() protoreflect.Message {
+	return xxx_ExtendingMessage_ExtendingMessageSubmessage{m}
+}
+func (m xxx_ExtendingMessage_ExtendingMessageSubmessage) Type() protoreflect.MessageType {
+	return xxx_Ext_ProtoFile_MessageTypes[7].Type
+}
+func (m xxx_ExtendingMessage_ExtendingMessageSubmessage) KnownFields() protoreflect.KnownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[7].KnownFieldsOf(m.m)
+}
+func (m xxx_ExtendingMessage_ExtendingMessageSubmessage) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[7].UnknownFieldsOf(m.m)
+}
+func (m xxx_ExtendingMessage_ExtendingMessageSubmessage) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_ExtendingMessage_ExtendingMessageSubmessage) ProtoMutable() {}
+
 func (m *ExtendingMessage_ExtendingMessageSubmessage) Reset() {
 	*m = ExtendingMessage_ExtendingMessageSubmessage{}
 }
@@ -260,6 +372,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_RepeatedGroup struct{ m *RepeatedGroup }
+
+func (m *RepeatedGroup) ProtoReflect() protoreflect.Message {
+	return xxx_RepeatedGroup{m}
+}
+func (m xxx_RepeatedGroup) Type() protoreflect.MessageType {
+	return xxx_Ext_ProtoFile_MessageTypes[3].Type
+}
+func (m xxx_RepeatedGroup) KnownFields() protoreflect.KnownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[3].KnownFieldsOf(m.m)
+}
+func (m xxx_RepeatedGroup) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[3].UnknownFieldsOf(m.m)
+}
+func (m xxx_RepeatedGroup) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_RepeatedGroup) ProtoMutable() {}
+
 func (m *RepeatedGroup) Reset()         { *m = RepeatedGroup{} }
 func (m *RepeatedGroup) String() string { return proto.CompactTextString(m) }
 func (*RepeatedGroup) ProtoMessage()    {}
@@ -300,6 +431,25 @@
 	XXX_sizecache                int32  `json:"-"`
 }
 
+type xxx_Extendable struct{ m *Extendable }
+
+func (m *Extendable) ProtoReflect() protoreflect.Message {
+	return xxx_Extendable{m}
+}
+func (m xxx_Extendable) Type() protoreflect.MessageType {
+	return xxx_Ext_ProtoFile_MessageTypes[4].Type
+}
+func (m xxx_Extendable) KnownFields() protoreflect.KnownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[4].KnownFieldsOf(m.m)
+}
+func (m xxx_Extendable) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[4].UnknownFieldsOf(m.m)
+}
+func (m xxx_Extendable) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Extendable) ProtoMutable() {}
+
 func (m *Extendable) Reset()         { *m = Extendable{} }
 func (m *Extendable) String() string { return proto.CompactTextString(m) }
 func (*Extendable) ProtoMessage()    {}
@@ -340,6 +490,27 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_MessageSetWireFormatExtension struct {
+	m *MessageSetWireFormatExtension
+}
+
+func (m *MessageSetWireFormatExtension) ProtoReflect() protoreflect.Message {
+	return xxx_MessageSetWireFormatExtension{m}
+}
+func (m xxx_MessageSetWireFormatExtension) Type() protoreflect.MessageType {
+	return xxx_Ext_ProtoFile_MessageTypes[5].Type
+}
+func (m xxx_MessageSetWireFormatExtension) KnownFields() protoreflect.KnownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[5].KnownFieldsOf(m.m)
+}
+func (m xxx_MessageSetWireFormatExtension) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Ext_ProtoFile_MessageTypes[5].UnknownFieldsOf(m.m)
+}
+func (m xxx_MessageSetWireFormatExtension) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_MessageSetWireFormatExtension) ProtoMutable() {}
+
 func (m *MessageSetWireFormatExtension) Reset()         { *m = MessageSetWireFormatExtension{} }
 func (m *MessageSetWireFormatExtension) String() string { return proto.CompactTextString(m) }
 func (*MessageSetWireFormatExtension) ProtoMessage()    {}
@@ -874,3 +1045,149 @@
 	0xc5, 0x5d, 0x9b, 0xb8, 0x77, 0x6d, 0xaf, 0x1f, 0x92, 0x20, 0xb4, 0xcc, 0x90, 0xbd, 0x0e, 0x13,
 	0xde, 0x8f, 0x3d, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xe1, 0x33, 0x5c, 0xd7, 0x84, 0x13, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Ext_ProtoFile_FileDesc.Enums = xxx_Ext_ProtoFile_EnumDescs[0:1]
+	xxx_Ext_ProtoFile_FileDesc.Messages = xxx_Ext_ProtoFile_MessageDescs[0:6]
+	xxx_Ext_ProtoFile_MessageDescs[0].Messages = xxx_Ext_ProtoFile_MessageDescs[6:7]
+	xxx_Ext_ProtoFile_MessageDescs[2].Messages = xxx_Ext_ProtoFile_MessageDescs[7:8]
+	var err error
+	Ext_ProtoFile, err = prototype.NewFile(&xxx_Ext_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Ext_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Ext_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "extensions/ext/ext.proto",
+	Package: "goproto.protoc.extension.ext",
+	Imports: []protoreflect.FileImport{
+		{FileDescriptor: prototype.PlaceholderFile("extensions/base/base.proto", "goproto.protoc.extension.base")},
+		{FileDescriptor: prototype.PlaceholderFile("extensions/extra/extra.proto", "goproto.protoc.extension.extra")},
+	},
+}
+var xxx_Ext_ProtoFile_EnumTypes = [1]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_Ext_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return Enum(n)
+		},
+	),
+}
+var xxx_Ext_ProtoFile_EnumDescs = [1]prototype.Enum{
+	{
+		Name: "Enum",
+		Values: []prototype.EnumValue{
+			{Name: "ZERO", Number: 0},
+		},
+	},
+}
+var xxx_Ext_ProtoFile_MessageTypes = [8]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Ext_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Ext_ProtoFile_MessageDescs[1].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(ExtensionGroup)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Ext_ProtoFile_MessageDescs[2].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(ExtendingMessage)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Ext_ProtoFile_MessageDescs[3].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(RepeatedGroup)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Ext_ProtoFile_MessageDescs[4].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Extendable)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Ext_ProtoFile_MessageDescs[5].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(MessageSetWireFormatExtension)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Ext_ProtoFile_MessageDescs[6].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message_M)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Ext_ProtoFile_MessageDescs[7].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(ExtendingMessage_ExtendingMessageSubmessage)
+		},
+	)},
+}
+var xxx_Ext_ProtoFile_MessageDescs = [8]prototype.Message{
+	{
+		Name: "Message",
+		Fields: []prototype.Field{
+			{
+				Name:        "data",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "data",
+			},
+		},
+	},
+	{
+		Name: "ExtensionGroup",
+		Fields: []prototype.Field{
+			{
+				Name:        "extension_group",
+				Number:      120,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "extensionGroup",
+			},
+		},
+	},
+	{
+		Name: "ExtendingMessage",
+	},
+	{
+		Name: "RepeatedGroup",
+		Fields: []prototype.Field{
+			{
+				Name:        "repeated_x_group",
+				Number:      319,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "repeatedXGroup",
+			},
+		},
+	},
+	{
+		Name:            "Extendable",
+		ExtensionRanges: [][2]protoreflect.FieldNumber{{1, 536870912}},
+	},
+	{
+		Name: "MessageSetWireFormatExtension",
+	},
+	{
+		Name: "M",
+	},
+	{
+		Name: "ExtendingMessageSubmessage",
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/extensions/extra/extra.pb.go b/cmd/protoc-gen-go/testdata/extensions/extra/extra.pb.go
index ad3b3f2..3761b44 100644
--- a/cmd/protoc-gen-go/testdata/extensions/extra/extra.pb.go
+++ b/cmd/protoc-gen-go/testdata/extensions/extra/extra.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -27,6 +30,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_ExtraMessage struct{ m *ExtraMessage }
+
+func (m *ExtraMessage) ProtoReflect() protoreflect.Message {
+	return xxx_ExtraMessage{m}
+}
+func (m xxx_ExtraMessage) Type() protoreflect.MessageType {
+	return xxx_Extra_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_ExtraMessage) KnownFields() protoreflect.KnownFields {
+	return xxx_Extra_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_ExtraMessage) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Extra_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_ExtraMessage) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_ExtraMessage) ProtoMutable() {}
+
 func (m *ExtraMessage) Reset()         { *m = ExtraMessage{} }
 func (m *ExtraMessage) String() string { return proto.CompactTextString(m) }
 func (*ExtraMessage) ProtoMessage()    {}
@@ -78,3 +100,44 @@
 	0xe2, 0x12, 0x90, 0x5e, 0x7d, 0x74, 0xc7, 0x01, 0x02, 0x00, 0x00, 0xff, 0xff, 0xcb, 0xfb, 0x31,
 	0xfc, 0xaf, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Extra_ProtoFile_FileDesc.Messages = xxx_Extra_ProtoFile_MessageDescs[0:1]
+	var err error
+	Extra_ProtoFile, err = prototype.NewFile(&xxx_Extra_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Extra_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Extra_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "extensions/extra/extra.proto",
+	Package: "goproto.protoc.extension.extra",
+}
+var xxx_Extra_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Extra_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(ExtraMessage)
+		},
+	)},
+}
+var xxx_Extra_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "ExtraMessage",
+		Fields: []prototype.Field{
+			{
+				Name:        "data",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "data",
+			},
+		},
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/extensions/proto3/ext3.pb.go b/cmd/protoc-gen-go/testdata/extensions/proto3/ext3.pb.go
index f2ae2e2..db91063 100644
--- a/cmd/protoc-gen-go/testdata/extensions/proto3/ext3.pb.go
+++ b/cmd/protoc-gen-go/testdata/extensions/proto3/ext3.pb.go
@@ -7,6 +7,9 @@
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
 	descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -27,6 +30,18 @@
 	Enum_ZERO Enum = 0
 )
 
+type xxx_Enum Enum
+
+func (e Enum) ProtoReflect() protoreflect.Enum {
+	return (xxx_Enum)(e)
+}
+func (e xxx_Enum) Type() protoreflect.EnumType {
+	return xxx_Ext3_ProtoFile_EnumTypes[0]
+}
+func (e xxx_Enum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var Enum_name = map[int32]string{
 	0: "ZERO",
 }
@@ -49,6 +64,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Message struct{ m *Message }
+
+func (m *Message) ProtoReflect() protoreflect.Message {
+	return xxx_Message{m}
+}
+func (m xxx_Message) Type() protoreflect.MessageType {
+	return xxx_Ext3_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_Message) KnownFields() protoreflect.KnownFields {
+	return xxx_Ext3_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_Message) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Ext3_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message) ProtoMutable() {}
+
 func (m *Message) Reset()         { *m = Message{} }
 func (m *Message) String() string { return proto.CompactTextString(m) }
 func (*Message) ProtoMessage()    {}
@@ -472,3 +506,55 @@
 	0x2d, 0x35, 0xf3, 0xc9, 0x62, 0x8d, 0x8a, 0xbf, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x65, 0x92,
 	0xaa, 0xed, 0xce, 0x0c, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Ext3_ProtoFile_FileDesc.Enums = xxx_Ext3_ProtoFile_EnumDescs[0:1]
+	xxx_Ext3_ProtoFile_FileDesc.Messages = xxx_Ext3_ProtoFile_MessageDescs[0:1]
+	var err error
+	Ext3_ProtoFile, err = prototype.NewFile(&xxx_Ext3_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Ext3_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Ext3_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "extensions/proto3/ext3.proto",
+	Package: "goproto.protoc.extension.proto3",
+	Imports: []protoreflect.FileImport{
+		{FileDescriptor: prototype.PlaceholderFile("google/protobuf/descriptor.proto", "google.protobuf")},
+	},
+}
+var xxx_Ext3_ProtoFile_EnumTypes = [1]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_Ext3_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return Enum(n)
+		},
+	),
+}
+var xxx_Ext3_ProtoFile_EnumDescs = [1]prototype.Enum{
+	{
+		Name: "Enum",
+		Values: []prototype.EnumValue{
+			{Name: "ZERO", Number: 0},
+		},
+	},
+}
+var xxx_Ext3_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Ext3_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message)
+		},
+	)},
+}
+var xxx_Ext3_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "Message",
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go b/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go
index 96676ef..3439cdb 100644
--- a/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go
+++ b/cmd/protoc-gen-go/testdata/fieldnames/fieldnames.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -65,6 +68,25 @@
 	XXX_sizecache        int32                    `json:"-"`
 }
 
+type xxx_Message struct{ m *Message }
+
+func (m *Message) ProtoReflect() protoreflect.Message {
+	return xxx_Message{m}
+}
+func (m xxx_Message) Type() protoreflect.MessageType {
+	return xxx_Fieldnames_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_Message) KnownFields() protoreflect.KnownFields {
+	return xxx_Fieldnames_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_Message) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Fieldnames_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message) ProtoMutable() {}
+
 func (m *Message) Reset()         { *m = Message{} }
 func (m *Message) String() string { return proto.CompactTextString(m) }
 func (*Message) ProtoMessage()    {}
@@ -289,6 +311,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Message_OneofMessageConflict struct{ m *Message_OneofMessageConflict }
+
+func (m *Message_OneofMessageConflict) ProtoReflect() protoreflect.Message {
+	return xxx_Message_OneofMessageConflict{m}
+}
+func (m xxx_Message_OneofMessageConflict) Type() protoreflect.MessageType {
+	return xxx_Fieldnames_ProtoFile_MessageTypes[1].Type
+}
+func (m xxx_Message_OneofMessageConflict) KnownFields() protoreflect.KnownFields {
+	return xxx_Fieldnames_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
+}
+func (m xxx_Message_OneofMessageConflict) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Fieldnames_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message_OneofMessageConflict) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message_OneofMessageConflict) ProtoMutable() {}
+
 func (m *Message_OneofMessageConflict) Reset()         { *m = Message_OneofMessageConflict{} }
 func (m *Message_OneofMessageConflict) String() string { return proto.CompactTextString(m) }
 func (*Message_OneofMessageConflict) ProtoMessage()    {}
@@ -351,3 +392,182 @@
 	0xfd, 0xe8, 0x2f, 0xf2, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xbd, 0xee, 0x38, 0xe6, 0x3a, 0x03, 0x00,
 	0x00,
 }
+
+func init() {
+	xxx_Fieldnames_ProtoFile_FileDesc.Messages = xxx_Fieldnames_ProtoFile_MessageDescs[0:1]
+	xxx_Fieldnames_ProtoFile_MessageDescs[0].Messages = xxx_Fieldnames_ProtoFile_MessageDescs[1:2]
+	var err error
+	Fieldnames_ProtoFile, err = prototype.NewFile(&xxx_Fieldnames_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Fieldnames_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Fieldnames_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "fieldnames/fieldnames.proto",
+	Package: "goproto.protoc.fieldnames",
+}
+var xxx_Fieldnames_ProtoFile_MessageTypes = [2]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Fieldnames_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Fieldnames_ProtoFile_MessageDescs[1].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message_OneofMessageConflict)
+		},
+	)},
+}
+var xxx_Fieldnames_ProtoFile_MessageDescs = [2]prototype.Message{
+	{
+		Name: "Message",
+		Fields: []prototype.Field{
+			{
+				Name:        "field_one",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "fieldOne",
+			},
+			{
+				Name:        "FieldTwo",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "FieldTwo",
+			},
+			{
+				Name:        "fieldThree",
+				Number:      3,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "fieldThree",
+			},
+			{
+				Name:        "field__four",
+				Number:      4,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "fieldFour",
+			},
+			{
+				Name:        "descriptor",
+				Number:      10,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "descriptor",
+			},
+			{
+				Name:        "marshal",
+				Number:      11,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "marshal",
+			},
+			{
+				Name:        "unmarshal",
+				Number:      12,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "unmarshal",
+			},
+			{
+				Name:        "proto_message",
+				Number:      13,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "protoMessage",
+			},
+			{
+				Name:        "CamelCase",
+				Number:      20,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "CamelCase",
+			},
+			{
+				Name:        "CamelCase_",
+				Number:      21,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "CamelCase",
+			},
+			{
+				Name:        "camel_case",
+				Number:      22,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "camelCase",
+			},
+			{
+				Name:        "CamelCase__",
+				Number:      23,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "CamelCase",
+			},
+			{
+				Name:        "get_name",
+				Number:      30,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "getName",
+			},
+			{
+				Name:        "name",
+				Number:      31,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "name",
+			},
+			{
+				Name:        "OneofConflictA",
+				Number:      40,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "OneofConflictA",
+				OneofName:   "oneof_conflict_a",
+			},
+			{
+				Name:        "oneof_no_conflict",
+				Number:      50,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "oneofNoConflict",
+				OneofName:   "oneof_conflict_b",
+			},
+			{
+				Name:        "OneofConflictB",
+				Number:      51,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "OneofConflictB",
+				OneofName:   "oneof_conflict_b",
+			},
+			{
+				Name:        "oneof_message_conflict",
+				Number:      60,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "oneofMessageConflict",
+				OneofName:   "oneof_conflict_c",
+			},
+		},
+		Oneofs: []prototype.Oneof{
+			{Name: "oneof_conflict_a"},
+			{Name: "oneof_conflict_b"},
+			{Name: "oneof_conflict_c"},
+		},
+	},
+	{
+		Name: "OneofMessageConflict",
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/import_public/a.pb.go b/cmd/protoc-gen-go/testdata/import_public/a.pb.go
index 62a4341..9b61bb6 100644
--- a/cmd/protoc-gen-go/testdata/import_public/a.pb.go
+++ b/cmd/protoc-gen-go/testdata/import_public/a.pb.go
@@ -7,6 +7,9 @@
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
 	sub "github.com/golang/protobuf/v2/cmd/protoc-gen-go/testdata/import_public/sub"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -71,6 +74,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Public struct{ m *Public }
+
+func (m *Public) ProtoReflect() protoreflect.Message {
+	return xxx_Public{m}
+}
+func (m xxx_Public) Type() protoreflect.MessageType {
+	return xxx_A_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_Public) KnownFields() protoreflect.KnownFields {
+	return xxx_A_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_Public) UnknownFields() protoreflect.UnknownFields {
+	return xxx_A_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_Public) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Public) ProtoMutable() {}
+
 func (m *Public) Reset()         { *m = Public{} }
 func (m *Public) String() string { return proto.CompactTextString(m) }
 func (*Public) ProtoMessage()    {}
@@ -139,3 +161,65 @@
 	0x97, 0xa4, 0x24, 0x96, 0x24, 0xea, 0xa3, 0x18, 0x1b, 0xc0, 0x10, 0xc0, 0x08, 0x08, 0x00, 0x00,
 	0xff, 0xff, 0xfa, 0x3e, 0xda, 0xad, 0x61, 0x01, 0x00, 0x00,
 }
+
+func init() {
+	xxx_A_ProtoFile_FileDesc.Messages = xxx_A_ProtoFile_MessageDescs[0:1]
+	xxx_A_ProtoFile_MessageDescs[0].Fields[0].MessageType = protoimpl.X.MessageTypeOf((*sub.M)(nil))
+	xxx_A_ProtoFile_MessageDescs[0].Fields[1].EnumType = protoimpl.X.EnumTypeOf(sub.E(0))
+	xxx_A_ProtoFile_MessageDescs[0].Fields[2].MessageType = protoimpl.X.MessageTypeOf((*Local)(nil))
+	var err error
+	A_ProtoFile, err = prototype.NewFile(&xxx_A_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var A_ProtoFile protoreflect.FileDescriptor
+
+var xxx_A_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "import_public/a.proto",
+	Package: "goproto.protoc.import_public",
+	Imports: []protoreflect.FileImport{
+		{FileDescriptor: prototype.PlaceholderFile("import_public/sub/a.proto", "goproto.protoc.import_public.sub"), IsPublic: true},
+		{FileDescriptor: prototype.PlaceholderFile("import_public/b.proto", "goproto.protoc.import_public"), IsPublic: true},
+	},
+}
+var xxx_A_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_A_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Public)
+		},
+	)},
+}
+var xxx_A_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "Public",
+		Fields: []prototype.Field{
+			{
+				Name:        "m",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "m",
+			},
+			{
+				Name:        "e",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "e",
+			},
+			{
+				Name:        "local",
+				Number:      3,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "local",
+			},
+		},
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/import_public/b.pb.go b/cmd/protoc-gen-go/testdata/import_public/b.pb.go
index 0b1ce40..5660ffe 100644
--- a/cmd/protoc-gen-go/testdata/import_public/b.pb.go
+++ b/cmd/protoc-gen-go/testdata/import_public/b.pb.go
@@ -7,6 +7,9 @@
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
 	sub "github.com/golang/protobuf/v2/cmd/protoc-gen-go/testdata/import_public/sub"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -29,6 +32,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Local struct{ m *Local }
+
+func (m *Local) ProtoReflect() protoreflect.Message {
+	return xxx_Local{m}
+}
+func (m xxx_Local) Type() protoreflect.MessageType {
+	return xxx_B_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_Local) KnownFields() protoreflect.KnownFields {
+	return xxx_B_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_Local) UnknownFields() protoreflect.UnknownFields {
+	return xxx_B_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_Local) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Local) ProtoMutable() {}
+
 func (m *Local) Reset()         { *m = Local{} }
 func (m *Local) String() string { return proto.CompactTextString(m) }
 func (*Local) ProtoMessage()    {}
@@ -88,3 +110,56 @@
 	0x3d, 0x35, 0x4f, 0x37, 0x3d, 0x5f, 0xbf, 0x24, 0xb5, 0xb8, 0x24, 0x25, 0xb1, 0x24, 0x51, 0x1f,
 	0xc5, 0x48, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0x34, 0xb9, 0xda, 0x09, 0x01, 0x00, 0x00,
 }
+
+func init() {
+	xxx_B_ProtoFile_FileDesc.Messages = xxx_B_ProtoFile_MessageDescs[0:1]
+	xxx_B_ProtoFile_MessageDescs[0].Fields[0].MessageType = protoimpl.X.MessageTypeOf((*sub.M)(nil))
+	xxx_B_ProtoFile_MessageDescs[0].Fields[1].EnumType = protoimpl.X.EnumTypeOf(sub.E(0))
+	var err error
+	B_ProtoFile, err = prototype.NewFile(&xxx_B_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var B_ProtoFile protoreflect.FileDescriptor
+
+var xxx_B_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "import_public/b.proto",
+	Package: "goproto.protoc.import_public",
+	Imports: []protoreflect.FileImport{
+		{FileDescriptor: prototype.PlaceholderFile("import_public/sub/a.proto", "goproto.protoc.import_public.sub")},
+	},
+}
+var xxx_B_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_B_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Local)
+		},
+	)},
+}
+var xxx_B_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "Local",
+		Fields: []prototype.Field{
+			{
+				Name:        "m",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "m",
+			},
+			{
+				Name:        "e",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "e",
+			},
+		},
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/import_public/sub/a.pb.go b/cmd/protoc-gen-go/testdata/import_public/sub/a.pb.go
index 9394cb1..b3b4c14 100644
--- a/cmd/protoc-gen-go/testdata/import_public/sub/a.pb.go
+++ b/cmd/protoc-gen-go/testdata/import_public/sub/a.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,18 @@
 	E_ZERO E = 0
 )
 
+type xxx_E E
+
+func (e E) ProtoReflect() protoreflect.Enum {
+	return (xxx_E)(e)
+}
+func (e xxx_E) Type() protoreflect.EnumType {
+	return xxx_A_ProtoFile_EnumTypes[0]
+}
+func (e xxx_E) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var E_name = map[int32]string{
 	0: "ZERO",
 }
@@ -63,6 +78,18 @@
 	M_M_ZERO M_Subenum = 0
 )
 
+type xxx_M_Subenum M_Subenum
+
+func (e M_Subenum) ProtoReflect() protoreflect.Enum {
+	return (xxx_M_Subenum)(e)
+}
+func (e xxx_M_Subenum) Type() protoreflect.EnumType {
+	return xxx_A_ProtoFile_EnumTypes[1]
+}
+func (e xxx_M_Subenum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var M_Subenum_name = map[int32]string{
 	0: "M_ZERO",
 }
@@ -100,6 +127,18 @@
 	M_Submessage_M_SUBMESSAGE_ZERO M_Submessage_Submessage_Subenum = 0
 )
 
+type xxx_M_Submessage_Submessage_Subenum M_Submessage_Submessage_Subenum
+
+func (e M_Submessage_Submessage_Subenum) ProtoReflect() protoreflect.Enum {
+	return (xxx_M_Submessage_Submessage_Subenum)(e)
+}
+func (e xxx_M_Submessage_Submessage_Subenum) Type() protoreflect.EnumType {
+	return xxx_A_ProtoFile_EnumTypes[2]
+}
+func (e xxx_M_Submessage_Submessage_Subenum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var M_Submessage_Submessage_Subenum_name = map[int32]string{
 	0: "M_SUBMESSAGE_ZERO",
 }
@@ -147,6 +186,25 @@
 	XXX_sizecache                int32  `json:"-"`
 }
 
+type xxx_M struct{ m *M }
+
+func (m *M) ProtoReflect() protoreflect.Message {
+	return xxx_M{m}
+}
+func (m xxx_M) Type() protoreflect.MessageType {
+	return xxx_A_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_M) KnownFields() protoreflect.KnownFields {
+	return xxx_A_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_M) UnknownFields() protoreflect.UnknownFields {
+	return xxx_A_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_M) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_M) ProtoMutable() {}
+
 func (m *M) Reset()         { *m = M{} }
 func (m *M) String() string { return proto.CompactTextString(m) }
 func (*M) ProtoMessage()    {}
@@ -268,6 +326,25 @@
 	XXX_sizecache        int32                               `json:"-"`
 }
 
+type xxx_M_Submessage struct{ m *M_Submessage }
+
+func (m *M_Submessage) ProtoReflect() protoreflect.Message {
+	return xxx_M_Submessage{m}
+}
+func (m xxx_M_Submessage) Type() protoreflect.MessageType {
+	return xxx_A_ProtoFile_MessageTypes[1].Type
+}
+func (m xxx_M_Submessage) KnownFields() protoreflect.KnownFields {
+	return xxx_A_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
+}
+func (m xxx_M_Submessage) UnknownFields() protoreflect.UnknownFields {
+	return xxx_A_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
+}
+func (m xxx_M_Submessage) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_M_Submessage) ProtoMutable() {}
+
 func (m *M_Submessage) Reset()         { *m = M_Submessage{} }
 func (m *M_Submessage) String() string { return proto.CompactTextString(m) }
 func (*M_Submessage) ProtoMessage()    {}
@@ -387,3 +464,166 @@
 	0xe4, 0xec, 0xaf, 0xbb, 0xf6, 0x27, 0x00, 0x00, 0xff, 0xff, 0xfb, 0xa9, 0x17, 0xb5, 0xbc, 0x02,
 	0x00, 0x00,
 }
+
+func init() {
+	xxx_A_ProtoFile_FileDesc.Enums = xxx_A_ProtoFile_EnumDescs[0:1]
+	xxx_A_ProtoFile_FileDesc.Messages = xxx_A_ProtoFile_MessageDescs[0:1]
+	xxx_A_ProtoFile_MessageDescs[0].Enums = xxx_A_ProtoFile_EnumDescs[1:2]
+	xxx_A_ProtoFile_MessageDescs[0].Messages = xxx_A_ProtoFile_MessageDescs[1:2]
+	xxx_A_ProtoFile_MessageDescs[1].Enums = xxx_A_ProtoFile_EnumDescs[2:3]
+	xxx_A_ProtoFile_MessageDescs[0].Fields[0].MessageType = protoimpl.X.MessageTypeOf((*M2)(nil))
+	var err error
+	A_ProtoFile, err = prototype.NewFile(&xxx_A_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var A_ProtoFile protoreflect.FileDescriptor
+
+var xxx_A_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "import_public/sub/a.proto",
+	Package: "goproto.protoc.import_public.sub",
+	Imports: []protoreflect.FileImport{
+		{FileDescriptor: prototype.PlaceholderFile("import_public/sub/b.proto", "goproto.protoc.import_public.sub")},
+	},
+}
+var xxx_A_ProtoFile_EnumTypes = [3]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_A_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return E(n)
+		},
+	),
+	prototype.GoEnum(
+		xxx_A_ProtoFile_EnumDescs[1].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return M_Subenum(n)
+		},
+	),
+	prototype.GoEnum(
+		xxx_A_ProtoFile_EnumDescs[2].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return M_Submessage_Submessage_Subenum(n)
+		},
+	),
+}
+var xxx_A_ProtoFile_EnumDescs = [3]prototype.Enum{
+	{
+		Name: "E",
+		Values: []prototype.EnumValue{
+			{Name: "ZERO", Number: 0},
+		},
+	},
+	{
+		Name: "Subenum",
+		Values: []prototype.EnumValue{
+			{Name: "M_ZERO", Number: 0},
+		},
+	},
+	{
+		Name: "Submessage_Subenum",
+		Values: []prototype.EnumValue{
+			{Name: "M_SUBMESSAGE_ZERO", Number: 0},
+		},
+	},
+}
+var xxx_A_ProtoFile_MessageTypes = [2]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_A_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(M)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_A_ProtoFile_MessageDescs[1].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(M_Submessage)
+		},
+	)},
+}
+var xxx_A_ProtoFile_MessageDescs = [2]prototype.Message{
+	{
+		Name: "M",
+		Fields: []prototype.Field{
+			{
+				Name:        "m2",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "m2",
+			},
+			{
+				Name:        "s",
+				Number:      4,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "s",
+				Default:     protoreflect.ValueOf(string("default")),
+			},
+			{
+				Name:        "b",
+				Number:      5,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "b",
+				Default:     protoreflect.ValueOf(("default")),
+			},
+			{
+				Name:        "f",
+				Number:      6,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "f",
+				Default:     protoreflect.ValueOf(float64(math.NaN())),
+			},
+			{
+				Name:        "oneof_int32",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "oneofInt32",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_int64",
+				Number:      3,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "oneofInt64",
+				OneofName:   "oneof_field",
+			},
+		},
+		Oneofs: []prototype.Oneof{
+			{Name: "oneof_field"},
+		},
+		ExtensionRanges: [][2]protoreflect.FieldNumber{{100, 536870912}},
+	},
+	{
+		Name: "Submessage",
+		Fields: []prototype.Field{
+			{
+				Name:        "submessage_oneof_int32",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "submessageOneofInt32",
+				OneofName:   "submessage_oneof_field",
+			},
+			{
+				Name:        "submessage_oneof_int64",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "submessageOneofInt64",
+				OneofName:   "submessage_oneof_field",
+			},
+		},
+		Oneofs: []prototype.Oneof{
+			{Name: "submessage_oneof_field"},
+		},
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/import_public/sub/b.pb.go b/cmd/protoc-gen-go/testdata/import_public/sub/b.pb.go
index d0d43b4..09c349f 100644
--- a/cmd/protoc-gen-go/testdata/import_public/sub/b.pb.go
+++ b/cmd/protoc-gen-go/testdata/import_public/sub/b.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_M2 struct{ m *M2 }
+
+func (m *M2) ProtoReflect() protoreflect.Message {
+	return xxx_M2{m}
+}
+func (m xxx_M2) Type() protoreflect.MessageType {
+	return xxx_B_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_M2) KnownFields() protoreflect.KnownFields {
+	return xxx_B_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_M2) UnknownFields() protoreflect.UnknownFields {
+	return xxx_B_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_M2) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_M2) ProtoMutable() {}
+
 func (m *M2) Reset()         { *m = M2{} }
 func (m *M2) String() string { return proto.CompactTextString(m) }
 func (*M2) ProtoMessage()    {}
@@ -69,3 +91,35 @@
 	0x3e, 0x86, 0xed, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc7, 0x2d, 0x0b, 0x52, 0x91, 0x00, 0x00,
 	0x00,
 }
+
+func init() {
+	xxx_B_ProtoFile_FileDesc.Messages = xxx_B_ProtoFile_MessageDescs[0:1]
+	var err error
+	B_ProtoFile, err = prototype.NewFile(&xxx_B_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var B_ProtoFile protoreflect.FileDescriptor
+
+var xxx_B_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "import_public/sub/b.proto",
+	Package: "goproto.protoc.import_public.sub",
+}
+var xxx_B_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_B_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(M2)
+		},
+	)},
+}
+var xxx_B_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "M2",
+	},
+}
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 9f774fe..7b8803f 100644
--- a/cmd/protoc-gen-go/testdata/imports/fmt/m.pb.go
+++ b/cmd/protoc-gen-go/testdata/imports/fmt/m.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_M struct{ m *M }
+
+func (m *M) ProtoReflect() protoreflect.Message {
+	return xxx_M{m}
+}
+func (m xxx_M) Type() protoreflect.MessageType {
+	return xxx_M_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_M) KnownFields() protoreflect.KnownFields {
+	return xxx_M_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_M) UnknownFields() protoreflect.UnknownFields {
+	return xxx_M_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_M) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_M) ProtoMutable() {}
+
 func (m *M) Reset()         { *m = M{} }
 func (m *M) String() string { return proto.CompactTextString(m) }
 func (*M) ProtoMessage()    {}
@@ -67,3 +89,35 @@
 	0x52, 0x8b, 0x4b, 0x52, 0x12, 0x4b, 0x12, 0xf5, 0x91, 0x8c, 0x4c, 0x62, 0x03, 0xab, 0x31, 0x06,
 	0x04, 0x00, 0x00, 0xff, 0xff, 0xc4, 0xc9, 0xee, 0xbe, 0x68, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	xxx_M_ProtoFile_FileDesc.Messages = xxx_M_ProtoFile_MessageDescs[0:1]
+	var err error
+	M_ProtoFile, err = prototype.NewFile(&xxx_M_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var M_ProtoFile protoreflect.FileDescriptor
+
+var xxx_M_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "imports/fmt/m.proto",
+	Package: "fmt",
+}
+var xxx_M_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_M_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(M)
+		},
+	)},
+}
+var xxx_M_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "M",
+	},
+}
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 1cec006..34d67e5 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
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,18 @@
 	E1_E1_ZERO E1 = 0
 )
 
+type xxx_E1 E1
+
+func (e E1) ProtoReflect() protoreflect.Enum {
+	return (xxx_E1)(e)
+}
+func (e xxx_E1) Type() protoreflect.EnumType {
+	return xxx_M1_ProtoFile_EnumTypes[0]
+}
+func (e xxx_E1) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var E1_name = map[int32]string{
 	0: "E1_ZERO",
 }
@@ -48,6 +63,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_M1 struct{ m *M1 }
+
+func (m *M1) ProtoReflect() protoreflect.Message {
+	return xxx_M1{m}
+}
+func (m xxx_M1) Type() protoreflect.MessageType {
+	return xxx_M1_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_M1) KnownFields() protoreflect.KnownFields {
+	return xxx_M1_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_M1) UnknownFields() protoreflect.UnknownFields {
+	return xxx_M1_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_M1) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_M1) ProtoMutable() {}
+
 func (m *M1) Reset()         { *m = M1{} }
 func (m *M1) String() string { return proto.CompactTextString(m) }
 func (*M1) ProtoMessage()    {}
@@ -80,6 +114,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_M1_1 struct{ m *M1_1 }
+
+func (m *M1_1) ProtoReflect() protoreflect.Message {
+	return xxx_M1_1{m}
+}
+func (m xxx_M1_1) Type() protoreflect.MessageType {
+	return xxx_M1_ProtoFile_MessageTypes[1].Type
+}
+func (m xxx_M1_1) KnownFields() protoreflect.KnownFields {
+	return xxx_M1_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
+}
+func (m xxx_M1_1) UnknownFields() protoreflect.UnknownFields {
+	return xxx_M1_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
+}
+func (m xxx_M1_1) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_M1_1) ProtoMutable() {}
+
 func (m *M1_1) Reset()         { *m = M1_1{} }
 func (m *M1_1) String() string { return proto.CompactTextString(m) }
 func (*M1_1) ProtoMessage()    {}
@@ -134,3 +187,71 @@
 	0x47, 0x77, 0x53, 0x12, 0x1b, 0x58, 0xa1, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xae, 0xc9,
 	0xcd, 0xae, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	xxx_M1_ProtoFile_FileDesc.Enums = xxx_M1_ProtoFile_EnumDescs[0:1]
+	xxx_M1_ProtoFile_FileDesc.Messages = xxx_M1_ProtoFile_MessageDescs[0:2]
+	xxx_M1_ProtoFile_MessageDescs[1].Fields[0].MessageType = xxx_M1_ProtoFile_MessageTypes[0].Type
+	var err error
+	M1_ProtoFile, err = prototype.NewFile(&xxx_M1_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var M1_ProtoFile protoreflect.FileDescriptor
+
+var xxx_M1_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "imports/test_a_1/m1.proto",
+	Package: "test.a",
+}
+var xxx_M1_ProtoFile_EnumTypes = [1]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_M1_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return E1(n)
+		},
+	),
+}
+var xxx_M1_ProtoFile_EnumDescs = [1]prototype.Enum{
+	{
+		Name: "E1",
+		Values: []prototype.EnumValue{
+			{Name: "E1_ZERO", Number: 0},
+		},
+	},
+}
+var xxx_M1_ProtoFile_MessageTypes = [2]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_M1_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(M1)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_M1_ProtoFile_MessageDescs[1].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(M1_1)
+		},
+	)},
+}
+var xxx_M1_ProtoFile_MessageDescs = [2]prototype.Message{
+	{
+		Name: "M1",
+	},
+	{
+		Name: "M1_1",
+		Fields: []prototype.Field{
+			{
+				Name:        "m1",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "m1",
+			},
+		},
+	},
+}
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 0563d58..04927aa 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
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_M2 struct{ m *M2 }
+
+func (m *M2) ProtoReflect() protoreflect.Message {
+	return xxx_M2{m}
+}
+func (m xxx_M2) Type() protoreflect.MessageType {
+	return xxx_M2_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_M2) KnownFields() protoreflect.KnownFields {
+	return xxx_M2_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_M2) UnknownFields() protoreflect.UnknownFields {
+	return xxx_M2_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_M2) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_M2) ProtoMutable() {}
+
 func (m *M2) Reset()         { *m = M2{} }
 func (m *M2) String() string { return proto.CompactTextString(m) }
 func (*M2) ProtoMessage()    {}
@@ -68,3 +90,35 @@
 	0x62, 0x03, 0x2b, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xe3, 0xe0, 0x7e, 0xc0, 0x77, 0x00,
 	0x00, 0x00,
 }
+
+func init() {
+	xxx_M2_ProtoFile_FileDesc.Messages = xxx_M2_ProtoFile_MessageDescs[0:1]
+	var err error
+	M2_ProtoFile, err = prototype.NewFile(&xxx_M2_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var M2_ProtoFile protoreflect.FileDescriptor
+
+var xxx_M2_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "imports/test_a_1/m2.proto",
+	Package: "test.a",
+}
+var xxx_M2_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_M2_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(M2)
+		},
+	)},
+}
+var xxx_M2_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "M2",
+	},
+}
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 cbc8430..5da2716 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
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_M3 struct{ m *M3 }
+
+func (m *M3) ProtoReflect() protoreflect.Message {
+	return xxx_M3{m}
+}
+func (m xxx_M3) Type() protoreflect.MessageType {
+	return xxx_M3_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_M3) KnownFields() protoreflect.KnownFields {
+	return xxx_M3_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_M3) UnknownFields() protoreflect.UnknownFields {
+	return xxx_M3_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_M3) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_M3) ProtoMutable() {}
+
 func (m *M3) Reset()         { *m = M3{} }
 func (m *M3) String() string { return proto.CompactTextString(m) }
 func (*M3) ProtoMessage()    {}
@@ -68,3 +90,35 @@
 	0x62, 0x03, 0x2b, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x23, 0x86, 0x27, 0x47, 0x77, 0x00,
 	0x00, 0x00,
 }
+
+func init() {
+	xxx_M3_ProtoFile_FileDesc.Messages = xxx_M3_ProtoFile_MessageDescs[0:1]
+	var err error
+	M3_ProtoFile, err = prototype.NewFile(&xxx_M3_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var M3_ProtoFile protoreflect.FileDescriptor
+
+var xxx_M3_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "imports/test_a_2/m3.proto",
+	Package: "test.a",
+}
+var xxx_M3_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_M3_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(M3)
+		},
+	)},
+}
+var xxx_M3_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "M3",
+	},
+}
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 2771b83..e4f4c59 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
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_M4 struct{ m *M4 }
+
+func (m *M4) ProtoReflect() protoreflect.Message {
+	return xxx_M4{m}
+}
+func (m xxx_M4) Type() protoreflect.MessageType {
+	return xxx_M4_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_M4) KnownFields() protoreflect.KnownFields {
+	return xxx_M4_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_M4) UnknownFields() protoreflect.UnknownFields {
+	return xxx_M4_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_M4) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_M4) ProtoMutable() {}
+
 func (m *M4) Reset()         { *m = M4{} }
 func (m *M4) String() string { return proto.CompactTextString(m) }
 func (*M4) ProtoMessage()    {}
@@ -68,3 +90,35 @@
 	0x62, 0x03, 0x2b, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x58, 0xcb, 0x10, 0xc8, 0x77, 0x00,
 	0x00, 0x00,
 }
+
+func init() {
+	xxx_M4_ProtoFile_FileDesc.Messages = xxx_M4_ProtoFile_MessageDescs[0:1]
+	var err error
+	M4_ProtoFile, err = prototype.NewFile(&xxx_M4_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var M4_ProtoFile protoreflect.FileDescriptor
+
+var xxx_M4_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "imports/test_a_2/m4.proto",
+	Package: "test.a",
+}
+var xxx_M4_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_M4_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(M4)
+		},
+	)},
+}
+var xxx_M4_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "M4",
+	},
+}
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 51592e7..3d5a9b1 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
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_M1 struct{ m *M1 }
+
+func (m *M1) ProtoReflect() protoreflect.Message {
+	return xxx_M1{m}
+}
+func (m xxx_M1) Type() protoreflect.MessageType {
+	return xxx_M1_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_M1) KnownFields() protoreflect.KnownFields {
+	return xxx_M1_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_M1) UnknownFields() protoreflect.UnknownFields {
+	return xxx_M1_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_M1) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_M1) ProtoMutable() {}
+
 func (m *M1) Reset()         { *m = M1{} }
 func (m *M1) String() string { return proto.CompactTextString(m) }
 func (*M1) ProtoMessage()    {}
@@ -68,3 +90,35 @@
 	0x4b, 0x12, 0xf5, 0xd1, 0xad, 0xb0, 0x4e, 0x4a, 0x2d, 0x49, 0x4c, 0x62, 0x03, 0xab, 0x36, 0x06,
 	0x04, 0x00, 0x00, 0xff, 0xff, 0x4a, 0xf1, 0x3b, 0x7f, 0x82, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	xxx_M1_ProtoFile_FileDesc.Messages = xxx_M1_ProtoFile_MessageDescs[0:1]
+	var err error
+	M1_ProtoFile, err = prototype.NewFile(&xxx_M1_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var M1_ProtoFile protoreflect.FileDescriptor
+
+var xxx_M1_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "imports/test_b_1/m1.proto",
+	Package: "test.b.part1",
+}
+var xxx_M1_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_M1_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(M1)
+		},
+	)},
+}
+var xxx_M1_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "M1",
+	},
+}
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 f31fb0d..80283f1 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
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_M2 struct{ m *M2 }
+
+func (m *M2) ProtoReflect() protoreflect.Message {
+	return xxx_M2{m}
+}
+func (m xxx_M2) Type() protoreflect.MessageType {
+	return xxx_M2_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_M2) KnownFields() protoreflect.KnownFields {
+	return xxx_M2_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_M2) UnknownFields() protoreflect.UnknownFields {
+	return xxx_M2_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_M2) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_M2) ProtoMutable() {}
+
 func (m *M2) Reset()         { *m = M2{} }
 func (m *M2) String() string { return proto.CompactTextString(m) }
 func (*M2) ProtoMessage()    {}
@@ -68,3 +90,35 @@
 	0x4b, 0x12, 0xf5, 0xd1, 0xad, 0xb0, 0x4e, 0x4a, 0x2d, 0x49, 0x4c, 0x62, 0x03, 0xab, 0x36, 0x06,
 	0x04, 0x00, 0x00, 0xff, 0xff, 0x44, 0x29, 0xbe, 0x6d, 0x82, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	xxx_M2_ProtoFile_FileDesc.Messages = xxx_M2_ProtoFile_MessageDescs[0:1]
+	var err error
+	M2_ProtoFile, err = prototype.NewFile(&xxx_M2_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var M2_ProtoFile protoreflect.FileDescriptor
+
+var xxx_M2_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "imports/test_b_1/m2.proto",
+	Package: "test.b.part2",
+}
+var xxx_M2_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_M2_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(M2)
+		},
+	)},
+}
+var xxx_M2_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "M2",
+	},
+}
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 1fef9ea..a75708e 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
@@ -7,6 +7,9 @@
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
 	test_a_1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -28,6 +31,25 @@
 	XXX_sizecache        int32        `json:"-"`
 }
 
+type xxx_A1M1 struct{ m *A1M1 }
+
+func (m *A1M1) ProtoReflect() protoreflect.Message {
+	return xxx_A1M1{m}
+}
+func (m xxx_A1M1) Type() protoreflect.MessageType {
+	return xxx_TestImportA1M1_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_A1M1) KnownFields() protoreflect.KnownFields {
+	return xxx_TestImportA1M1_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_A1M1) UnknownFields() protoreflect.UnknownFields {
+	return xxx_TestImportA1M1_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_A1M1) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_A1M1) ProtoMutable() {}
+
 func (m *A1M1) Reset()         { *m = A1M1{} }
 func (m *A1M1) String() string { return proto.CompactTextString(m) }
 func (*A1M1) ProtoMessage()    {}
@@ -79,3 +101,48 @@
 	0x50, 0x0b, 0x93, 0xd8, 0xc0, 0xf2, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x84, 0x2f, 0x18,
 	0x23, 0xa8, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	xxx_TestImportA1M1_ProtoFile_FileDesc.Messages = xxx_TestImportA1M1_ProtoFile_MessageDescs[0:1]
+	xxx_TestImportA1M1_ProtoFile_MessageDescs[0].Fields[0].MessageType = protoimpl.X.MessageTypeOf((*test_a_1.M1)(nil))
+	var err error
+	TestImportA1M1_ProtoFile, err = prototype.NewFile(&xxx_TestImportA1M1_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var TestImportA1M1_ProtoFile protoreflect.FileDescriptor
+
+var xxx_TestImportA1M1_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "imports/test_import_a1m1.proto",
+	Package: "test",
+	Imports: []protoreflect.FileImport{
+		{FileDescriptor: prototype.PlaceholderFile("imports/test_a_1/m1.proto", "test.a")},
+	},
+}
+var xxx_TestImportA1M1_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_TestImportA1M1_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(A1M1)
+		},
+	)},
+}
+var xxx_TestImportA1M1_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "A1M1",
+		Fields: []prototype.Field{
+			{
+				Name:        "f",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "f",
+			},
+		},
+	},
+}
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 13d5dd6..58a0669 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
@@ -7,6 +7,9 @@
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
 	test_a_1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -28,6 +31,25 @@
 	XXX_sizecache        int32        `json:"-"`
 }
 
+type xxx_A1M2 struct{ m *A1M2 }
+
+func (m *A1M2) ProtoReflect() protoreflect.Message {
+	return xxx_A1M2{m}
+}
+func (m xxx_A1M2) Type() protoreflect.MessageType {
+	return xxx_TestImportA1M2_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_A1M2) KnownFields() protoreflect.KnownFields {
+	return xxx_TestImportA1M2_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_A1M2) UnknownFields() protoreflect.UnknownFields {
+	return xxx_TestImportA1M2_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_A1M2) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_A1M2) ProtoMutable() {}
+
 func (m *A1M2) Reset()         { *m = A1M2{} }
 func (m *A1M2) String() string { return proto.CompactTextString(m) }
 func (*A1M2) ProtoMessage()    {}
@@ -79,3 +101,48 @@
 	0x50, 0x0b, 0x93, 0xd8, 0xc0, 0xf2, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x88, 0xfb,
 	0xea, 0xa8, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	xxx_TestImportA1M2_ProtoFile_FileDesc.Messages = xxx_TestImportA1M2_ProtoFile_MessageDescs[0:1]
+	xxx_TestImportA1M2_ProtoFile_MessageDescs[0].Fields[0].MessageType = protoimpl.X.MessageTypeOf((*test_a_1.M2)(nil))
+	var err error
+	TestImportA1M2_ProtoFile, err = prototype.NewFile(&xxx_TestImportA1M2_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var TestImportA1M2_ProtoFile protoreflect.FileDescriptor
+
+var xxx_TestImportA1M2_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "imports/test_import_a1m2.proto",
+	Package: "test",
+	Imports: []protoreflect.FileImport{
+		{FileDescriptor: prototype.PlaceholderFile("imports/test_a_1/m2.proto", "test.a")},
+	},
+}
+var xxx_TestImportA1M2_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_TestImportA1M2_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(A1M2)
+		},
+	)},
+}
+var xxx_TestImportA1M2_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "A1M2",
+		Fields: []prototype.Field{
+			{
+				Name:        "f",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "f",
+			},
+		},
+	},
+}
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 60d613d..b7cf7ef 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
@@ -10,6 +10,9 @@
 	test_a_1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
 	_ "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_2"
 	test_b_1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_b_1"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -35,6 +38,25 @@
 	XXX_sizecache        int32        `json:"-"`
 }
 
+type xxx_All struct{ m *All }
+
+func (m *All) ProtoReflect() protoreflect.Message {
+	return xxx_All{m}
+}
+func (m xxx_All) Type() protoreflect.MessageType {
+	return xxx_TestImportAll_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_All) KnownFields() protoreflect.KnownFields {
+	return xxx_TestImportAll_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_All) UnknownFields() protoreflect.UnknownFields {
+	return xxx_TestImportAll_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_All) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_All) ProtoMutable() {}
+
 func (m *All) Reset()         { *m = All{} }
 func (m *All) String() string { return proto.CompactTextString(m) }
 func (*All) ProtoMessage()    {}
@@ -120,3 +142,86 @@
 	0xb9, 0xd8, 0x64, 0x5f, 0x7c, 0x05, 0x00, 0x00, 0xff, 0xff, 0x88, 0x0e, 0xe2, 0x9f, 0xc7, 0x01,
 	0x00, 0x00,
 }
+
+func init() {
+	xxx_TestImportAll_ProtoFile_FileDesc.Messages = xxx_TestImportAll_ProtoFile_MessageDescs[0:1]
+	xxx_TestImportAll_ProtoFile_MessageDescs[0].Fields[0].MessageType = protoimpl.X.MessageTypeOf((*test_a_1.M1)(nil))
+	xxx_TestImportAll_ProtoFile_MessageDescs[0].Fields[1].MessageType = protoimpl.X.MessageTypeOf((*test_a_1.M2)(nil))
+	xxx_TestImportAll_ProtoFile_MessageDescs[0].Fields[2].MessageType = protoimpl.X.MessageTypeOf((*test_b_1.M1)(nil))
+	xxx_TestImportAll_ProtoFile_MessageDescs[0].Fields[3].MessageType = protoimpl.X.MessageTypeOf((*test_b_1.M2)(nil))
+	xxx_TestImportAll_ProtoFile_MessageDescs[0].Fields[4].MessageType = protoimpl.X.MessageTypeOf((*fmt1.M)(nil))
+	var err error
+	TestImportAll_ProtoFile, err = prototype.NewFile(&xxx_TestImportAll_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var TestImportAll_ProtoFile protoreflect.FileDescriptor
+
+var xxx_TestImportAll_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "imports/test_import_all.proto",
+	Package: "test",
+	Imports: []protoreflect.FileImport{
+		{FileDescriptor: prototype.PlaceholderFile("imports/test_a_1/m1.proto", "test.a")},
+		{FileDescriptor: prototype.PlaceholderFile("imports/test_a_1/m2.proto", "test.a")},
+		{FileDescriptor: prototype.PlaceholderFile("imports/test_a_2/m3.proto", "test.a")},
+		{FileDescriptor: prototype.PlaceholderFile("imports/test_a_2/m4.proto", "test.a")},
+		{FileDescriptor: prototype.PlaceholderFile("imports/test_b_1/m1.proto", "test.b.part1")},
+		{FileDescriptor: prototype.PlaceholderFile("imports/test_b_1/m2.proto", "test.b.part2")},
+		{FileDescriptor: prototype.PlaceholderFile("imports/fmt/m.proto", "fmt")},
+	},
+}
+var xxx_TestImportAll_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_TestImportAll_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(All)
+		},
+	)},
+}
+var xxx_TestImportAll_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "All",
+		Fields: []prototype.Field{
+			{
+				Name:        "am1",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "am1",
+			},
+			{
+				Name:        "am2",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "am2",
+			},
+			{
+				Name:        "bm1",
+				Number:      5,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "bm1",
+			},
+			{
+				Name:        "bm2",
+				Number:      6,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "bm2",
+			},
+			{
+				Name:        "fmt",
+				Number:      7,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "fmt",
+			},
+		},
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/nopackage/nopackage.pb.go b/cmd/protoc-gen-go/testdata/nopackage/nopackage.pb.go
index bad4bff..84a54b0 100644
--- a/cmd/protoc-gen-go/testdata/nopackage/nopackage.pb.go
+++ b/cmd/protoc-gen-go/testdata/nopackage/nopackage.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,18 @@
 	Enum_ZERO Enum = 0
 )
 
+type xxx_Enum Enum
+
+func (e Enum) ProtoReflect() protoreflect.Enum {
+	return (xxx_Enum)(e)
+}
+func (e xxx_Enum) Type() protoreflect.EnumType {
+	return xxx_Nopackage_ProtoFile_EnumTypes[0]
+}
+func (e xxx_Enum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var Enum_name = map[int32]string{
 	0: "ZERO",
 }
@@ -65,6 +80,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Message struct{ m *Message }
+
+func (m *Message) ProtoReflect() protoreflect.Message {
+	return xxx_Message{m}
+}
+func (m xxx_Message) Type() protoreflect.MessageType {
+	return xxx_Nopackage_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_Message) KnownFields() protoreflect.KnownFields {
+	return xxx_Nopackage_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_Message) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Nopackage_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message) ProtoMutable() {}
+
 func (m *Message) Reset()         { *m = Message{} }
 func (m *Message) String() string { return proto.CompactTextString(m) }
 func (*Message) ProtoMessage()    {}
@@ -125,3 +159,70 @@
 	0x0b, 0x2c, 0x25, 0xc0, 0x00, 0x08, 0x00, 0x00, 0xff, 0xff, 0x31, 0x29, 0xe4, 0xb2, 0x87, 0x00,
 	0x00, 0x00,
 }
+
+func init() {
+	xxx_Nopackage_ProtoFile_FileDesc.Enums = xxx_Nopackage_ProtoFile_EnumDescs[0:1]
+	xxx_Nopackage_ProtoFile_FileDesc.Messages = xxx_Nopackage_ProtoFile_MessageDescs[0:1]
+	xxx_Nopackage_ProtoFile_MessageDescs[0].Fields[1].EnumType = xxx_Nopackage_ProtoFile_EnumTypes[0]
+	var err error
+	Nopackage_ProtoFile, err = prototype.NewFile(&xxx_Nopackage_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Nopackage_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Nopackage_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "nopackage/nopackage.proto",
+	Package: "",
+}
+var xxx_Nopackage_ProtoFile_EnumTypes = [1]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_Nopackage_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return Enum(n)
+		},
+	),
+}
+var xxx_Nopackage_ProtoFile_EnumDescs = [1]prototype.Enum{
+	{
+		Name: "Enum",
+		Values: []prototype.EnumValue{
+			{Name: "ZERO", Number: 0},
+		},
+	},
+}
+var xxx_Nopackage_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Nopackage_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message)
+		},
+	)},
+}
+var xxx_Nopackage_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "Message",
+		Fields: []prototype.Field{
+			{
+				Name:        "string_field",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "stringField",
+			},
+			{
+				Name:        "enum_field",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "enumField",
+				Default:     protoreflect.ValueOf(string("ZERO")),
+			},
+		},
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/proto2/enum.pb.go b/cmd/protoc-gen-go/testdata/proto2/enum.pb.go
index a4f394b..67c60a0 100644
--- a/cmd/protoc-gen-go/testdata/proto2/enum.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/enum.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -30,6 +33,18 @@
 	EnumType1_TWO EnumType1 = 2
 )
 
+type xxx_EnumType1 EnumType1
+
+func (e EnumType1) ProtoReflect() protoreflect.Enum {
+	return (xxx_EnumType1)(e)
+}
+func (e xxx_EnumType1) Type() protoreflect.EnumType {
+	return xxx_Enum_ProtoFile_EnumTypes[0]
+}
+func (e xxx_EnumType1) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var EnumType1_name = map[int32]string{
 	1: "ONE",
 	2: "TWO",
@@ -70,6 +85,18 @@
 	EnumType2_duplicate2 EnumType2 = 1
 )
 
+type xxx_EnumType2 EnumType2
+
+func (e EnumType2) ProtoReflect() protoreflect.Enum {
+	return (xxx_EnumType2)(e)
+}
+func (e xxx_EnumType2) Type() protoreflect.EnumType {
+	return xxx_Enum_ProtoFile_EnumTypes[1]
+}
+func (e xxx_EnumType2) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var EnumType2_name = map[int32]string{
 	1: "duplicate1",
 	// Duplicate value: 1: "duplicate2",
@@ -111,6 +138,18 @@
 	EnumContainerMessage1_NESTED_1A_VALUE EnumContainerMessage1_NestedEnumType1A = 0
 )
 
+type xxx_EnumContainerMessage1_NestedEnumType1A EnumContainerMessage1_NestedEnumType1A
+
+func (e EnumContainerMessage1_NestedEnumType1A) ProtoReflect() protoreflect.Enum {
+	return (xxx_EnumContainerMessage1_NestedEnumType1A)(e)
+}
+func (e xxx_EnumContainerMessage1_NestedEnumType1A) Type() protoreflect.EnumType {
+	return xxx_Enum_ProtoFile_EnumTypes[2]
+}
+func (e xxx_EnumContainerMessage1_NestedEnumType1A) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var EnumContainerMessage1_NestedEnumType1A_name = map[int32]string{
 	0: "NESTED_1A_VALUE",
 }
@@ -148,6 +187,18 @@
 	EnumContainerMessage1_NESTED_1B_VALUE EnumContainerMessage1_NestedEnumType1B = 0
 )
 
+type xxx_EnumContainerMessage1_NestedEnumType1B EnumContainerMessage1_NestedEnumType1B
+
+func (e EnumContainerMessage1_NestedEnumType1B) ProtoReflect() protoreflect.Enum {
+	return (xxx_EnumContainerMessage1_NestedEnumType1B)(e)
+}
+func (e xxx_EnumContainerMessage1_NestedEnumType1B) Type() protoreflect.EnumType {
+	return xxx_Enum_ProtoFile_EnumTypes[3]
+}
+func (e xxx_EnumContainerMessage1_NestedEnumType1B) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var EnumContainerMessage1_NestedEnumType1B_name = map[int32]string{
 	0: "NESTED_1B_VALUE",
 }
@@ -187,6 +238,18 @@
 	EnumContainerMessage1_EnumContainerMessage2_NESTED_2A_VALUE EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2A = 0
 )
 
+type xxx_EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2A EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2A
+
+func (e EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2A) ProtoReflect() protoreflect.Enum {
+	return (xxx_EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2A)(e)
+}
+func (e xxx_EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2A) Type() protoreflect.EnumType {
+	return xxx_Enum_ProtoFile_EnumTypes[4]
+}
+func (e xxx_EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2A) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2A_name = map[int32]string{
 	0: "NESTED_2A_VALUE",
 }
@@ -224,6 +287,18 @@
 	EnumContainerMessage1_EnumContainerMessage2_NESTED_2B_VALUE EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2B = 0
 )
 
+type xxx_EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2B EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2B
+
+func (e EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2B) ProtoReflect() protoreflect.Enum {
+	return (xxx_EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2B)(e)
+}
+func (e xxx_EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2B) Type() protoreflect.EnumType {
+	return xxx_Enum_ProtoFile_EnumTypes[5]
+}
+func (e xxx_EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2B) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2B_name = map[int32]string{
 	0: "NESTED_2B_VALUE",
 }
@@ -263,6 +338,25 @@
 	XXX_sizecache        int32      `json:"-"`
 }
 
+type xxx_EnumContainerMessage1 struct{ m *EnumContainerMessage1 }
+
+func (m *EnumContainerMessage1) ProtoReflect() protoreflect.Message {
+	return xxx_EnumContainerMessage1{m}
+}
+func (m xxx_EnumContainerMessage1) Type() protoreflect.MessageType {
+	return xxx_Enum_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_EnumContainerMessage1) KnownFields() protoreflect.KnownFields {
+	return xxx_Enum_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_EnumContainerMessage1) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Enum_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_EnumContainerMessage1) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_EnumContainerMessage1) ProtoMutable() {}
+
 func (m *EnumContainerMessage1) Reset()         { *m = EnumContainerMessage1{} }
 func (m *EnumContainerMessage1) String() string { return proto.CompactTextString(m) }
 func (*EnumContainerMessage1) ProtoMessage()    {}
@@ -311,6 +405,27 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_EnumContainerMessage1_EnumContainerMessage2 struct {
+	m *EnumContainerMessage1_EnumContainerMessage2
+}
+
+func (m *EnumContainerMessage1_EnumContainerMessage2) ProtoReflect() protoreflect.Message {
+	return xxx_EnumContainerMessage1_EnumContainerMessage2{m}
+}
+func (m xxx_EnumContainerMessage1_EnumContainerMessage2) Type() protoreflect.MessageType {
+	return xxx_Enum_ProtoFile_MessageTypes[1].Type
+}
+func (m xxx_EnumContainerMessage1_EnumContainerMessage2) KnownFields() protoreflect.KnownFields {
+	return xxx_Enum_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
+}
+func (m xxx_EnumContainerMessage1_EnumContainerMessage2) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Enum_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
+}
+func (m xxx_EnumContainerMessage1_EnumContainerMessage2) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_EnumContainerMessage1_EnumContainerMessage2) ProtoMutable() {}
+
 func (m *EnumContainerMessage1_EnumContainerMessage2) Reset() {
 	*m = EnumContainerMessage1_EnumContainerMessage2{}
 }
@@ -375,3 +490,146 @@
 	0x33, 0x65, 0x98, 0x95, 0x85, 0x8d, 0x85, 0x15, 0xd5, 0x18, 0x3e, 0x02, 0x00, 0x00, 0xff, 0xff,
 	0x26, 0xf5, 0x57, 0x52, 0x4e, 0x02, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Enum_ProtoFile_FileDesc.Enums = xxx_Enum_ProtoFile_EnumDescs[0:2]
+	xxx_Enum_ProtoFile_FileDesc.Messages = xxx_Enum_ProtoFile_MessageDescs[0:1]
+	xxx_Enum_ProtoFile_MessageDescs[0].Enums = xxx_Enum_ProtoFile_EnumDescs[2:4]
+	xxx_Enum_ProtoFile_MessageDescs[0].Messages = xxx_Enum_ProtoFile_MessageDescs[1:2]
+	xxx_Enum_ProtoFile_MessageDescs[1].Enums = xxx_Enum_ProtoFile_EnumDescs[4:6]
+	xxx_Enum_ProtoFile_MessageDescs[0].Fields[0].EnumType = xxx_Enum_ProtoFile_EnumTypes[1]
+	xxx_Enum_ProtoFile_MessageDescs[0].Fields[1].EnumType = xxx_Enum_ProtoFile_EnumTypes[1]
+	var err error
+	Enum_ProtoFile, err = prototype.NewFile(&xxx_Enum_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Enum_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Enum_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "proto2/enum.proto",
+	Package: "goproto.protoc.proto2",
+}
+var xxx_Enum_ProtoFile_EnumTypes = [6]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_Enum_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return EnumType1(n)
+		},
+	),
+	prototype.GoEnum(
+		xxx_Enum_ProtoFile_EnumDescs[1].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return EnumType2(n)
+		},
+	),
+	prototype.GoEnum(
+		xxx_Enum_ProtoFile_EnumDescs[2].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return EnumContainerMessage1_NestedEnumType1A(n)
+		},
+	),
+	prototype.GoEnum(
+		xxx_Enum_ProtoFile_EnumDescs[3].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return EnumContainerMessage1_NestedEnumType1B(n)
+		},
+	),
+	prototype.GoEnum(
+		xxx_Enum_ProtoFile_EnumDescs[4].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2A(n)
+		},
+	),
+	prototype.GoEnum(
+		xxx_Enum_ProtoFile_EnumDescs[5].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return EnumContainerMessage1_EnumContainerMessage2_NestedEnumType2B(n)
+		},
+	),
+}
+var xxx_Enum_ProtoFile_EnumDescs = [6]prototype.Enum{
+	{
+		Name: "EnumType1",
+		Values: []prototype.EnumValue{
+			{Name: "ONE", Number: 1},
+			{Name: "TWO", Number: 2},
+		},
+	},
+	{
+		Name: "EnumType2",
+		Values: []prototype.EnumValue{
+			{Name: "duplicate1", Number: 1},
+			{Name: "duplicate2", Number: 1},
+		},
+	},
+	{
+		Name: "NestedEnumType1A",
+		Values: []prototype.EnumValue{
+			{Name: "NESTED_1A_VALUE", Number: 0},
+		},
+	},
+	{
+		Name: "NestedEnumType1B",
+		Values: []prototype.EnumValue{
+			{Name: "NESTED_1B_VALUE", Number: 0},
+		},
+	},
+	{
+		Name: "NestedEnumType2A",
+		Values: []prototype.EnumValue{
+			{Name: "NESTED_2A_VALUE", Number: 0},
+		},
+	},
+	{
+		Name: "NestedEnumType2B",
+		Values: []prototype.EnumValue{
+			{Name: "NESTED_2B_VALUE", Number: 0},
+		},
+	},
+}
+var xxx_Enum_ProtoFile_MessageTypes = [2]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Enum_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(EnumContainerMessage1)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Enum_ProtoFile_MessageDescs[1].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(EnumContainerMessage1_EnumContainerMessage2)
+		},
+	)},
+}
+var xxx_Enum_ProtoFile_MessageDescs = [2]prototype.Message{
+	{
+		Name: "EnumContainerMessage1",
+		Fields: []prototype.Field{
+			{
+				Name:        "default_duplicate1",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "defaultDuplicate1",
+				Default:     protoreflect.ValueOf(string("duplicate1")),
+			},
+			{
+				Name:        "default_duplicate2",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "defaultDuplicate2",
+				Default:     protoreflect.ValueOf(string("duplicate2")),
+			},
+		},
+	},
+	{
+		Name: "EnumContainerMessage2",
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/proto2/fields.pb.go b/cmd/protoc-gen-go/testdata/proto2/fields.pb.go
index 268dfb5..8c382bf 100644
--- a/cmd/protoc-gen-go/testdata/proto2/fields.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/fields.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -27,6 +30,18 @@
 	FieldTestMessage_ONE  FieldTestMessage_Enum = 1
 )
 
+type xxx_FieldTestMessage_Enum FieldTestMessage_Enum
+
+func (e FieldTestMessage_Enum) ProtoReflect() protoreflect.Enum {
+	return (xxx_FieldTestMessage_Enum)(e)
+}
+func (e xxx_FieldTestMessage_Enum) Type() protoreflect.EnumType {
+	return xxx_Fields_ProtoFile_EnumTypes[0]
+}
+func (e xxx_FieldTestMessage_Enum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var FieldTestMessage_Enum_name = map[int32]string{
 	0: "ZERO",
 	1: "ONE",
@@ -172,6 +187,25 @@
 	XXX_sizecache        int32                       `json:"-"`
 }
 
+type xxx_FieldTestMessage struct{ m *FieldTestMessage }
+
+func (m *FieldTestMessage) ProtoReflect() protoreflect.Message {
+	return xxx_FieldTestMessage{m}
+}
+func (m xxx_FieldTestMessage) Type() protoreflect.MessageType {
+	return xxx_Fields_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_FieldTestMessage) KnownFields() protoreflect.KnownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_FieldTestMessage) ProtoMutable() {}
+
 func (m *FieldTestMessage) Reset()         { *m = FieldTestMessage{} }
 func (m *FieldTestMessage) String() string { return proto.CompactTextString(m) }
 func (*FieldTestMessage) ProtoMessage()    {}
@@ -1117,6 +1151,27 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_FieldTestMessage_OptionalGroup struct {
+	m *FieldTestMessage_OptionalGroup
+}
+
+func (m *FieldTestMessage_OptionalGroup) ProtoReflect() protoreflect.Message {
+	return xxx_FieldTestMessage_OptionalGroup{m}
+}
+func (m xxx_FieldTestMessage_OptionalGroup) Type() protoreflect.MessageType {
+	return xxx_Fields_ProtoFile_MessageTypes[1].Type
+}
+func (m xxx_FieldTestMessage_OptionalGroup) KnownFields() protoreflect.KnownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_OptionalGroup) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_OptionalGroup) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_FieldTestMessage_OptionalGroup) ProtoMutable() {}
+
 func (m *FieldTestMessage_OptionalGroup) Reset()         { *m = FieldTestMessage_OptionalGroup{} }
 func (m *FieldTestMessage_OptionalGroup) String() string { return proto.CompactTextString(m) }
 func (*FieldTestMessage_OptionalGroup) ProtoMessage()    {}
@@ -1156,6 +1211,27 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_FieldTestMessage_RequiredGroup struct {
+	m *FieldTestMessage_RequiredGroup
+}
+
+func (m *FieldTestMessage_RequiredGroup) ProtoReflect() protoreflect.Message {
+	return xxx_FieldTestMessage_RequiredGroup{m}
+}
+func (m xxx_FieldTestMessage_RequiredGroup) Type() protoreflect.MessageType {
+	return xxx_Fields_ProtoFile_MessageTypes[2].Type
+}
+func (m xxx_FieldTestMessage_RequiredGroup) KnownFields() protoreflect.KnownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[2].KnownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_RequiredGroup) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[2].UnknownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_RequiredGroup) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_FieldTestMessage_RequiredGroup) ProtoMutable() {}
+
 func (m *FieldTestMessage_RequiredGroup) Reset()         { *m = FieldTestMessage_RequiredGroup{} }
 func (m *FieldTestMessage_RequiredGroup) String() string { return proto.CompactTextString(m) }
 func (*FieldTestMessage_RequiredGroup) ProtoMessage()    {}
@@ -1195,6 +1271,27 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_FieldTestMessage_RepeatedGroup struct {
+	m *FieldTestMessage_RepeatedGroup
+}
+
+func (m *FieldTestMessage_RepeatedGroup) ProtoReflect() protoreflect.Message {
+	return xxx_FieldTestMessage_RepeatedGroup{m}
+}
+func (m xxx_FieldTestMessage_RepeatedGroup) Type() protoreflect.MessageType {
+	return xxx_Fields_ProtoFile_MessageTypes[3].Type
+}
+func (m xxx_FieldTestMessage_RepeatedGroup) KnownFields() protoreflect.KnownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[3].KnownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_RepeatedGroup) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[3].UnknownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_RepeatedGroup) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_FieldTestMessage_RepeatedGroup) ProtoMutable() {}
+
 func (m *FieldTestMessage_RepeatedGroup) Reset()         { *m = FieldTestMessage_RepeatedGroup{} }
 func (m *FieldTestMessage_RepeatedGroup) String() string { return proto.CompactTextString(m) }
 func (*FieldTestMessage_RepeatedGroup) ProtoMessage()    {}
@@ -1234,6 +1331,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_FieldTestMessage_OneofGroup struct{ m *FieldTestMessage_OneofGroup }
+
+func (m *FieldTestMessage_OneofGroup) ProtoReflect() protoreflect.Message {
+	return xxx_FieldTestMessage_OneofGroup{m}
+}
+func (m xxx_FieldTestMessage_OneofGroup) Type() protoreflect.MessageType {
+	return xxx_Fields_ProtoFile_MessageTypes[7].Type
+}
+func (m xxx_FieldTestMessage_OneofGroup) KnownFields() protoreflect.KnownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[7].KnownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_OneofGroup) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[7].UnknownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_OneofGroup) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_FieldTestMessage_OneofGroup) ProtoMutable() {}
+
 func (m *FieldTestMessage_OneofGroup) Reset()         { *m = FieldTestMessage_OneofGroup{} }
 func (m *FieldTestMessage_OneofGroup) String() string { return proto.CompactTextString(m) }
 func (*FieldTestMessage_OneofGroup) ProtoMessage()    {}
@@ -1272,6 +1388,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_FieldTestMessage_Message struct{ m *FieldTestMessage_Message }
+
+func (m *FieldTestMessage_Message) ProtoReflect() protoreflect.Message {
+	return xxx_FieldTestMessage_Message{m}
+}
+func (m xxx_FieldTestMessage_Message) Type() protoreflect.MessageType {
+	return xxx_Fields_ProtoFile_MessageTypes[8].Type
+}
+func (m xxx_FieldTestMessage_Message) KnownFields() protoreflect.KnownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[8].KnownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_Message) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[8].UnknownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_Message) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_FieldTestMessage_Message) ProtoMutable() {}
+
 func (m *FieldTestMessage_Message) Reset()         { *m = FieldTestMessage_Message{} }
 func (m *FieldTestMessage_Message) String() string { return proto.CompactTextString(m) }
 func (*FieldTestMessage_Message) ProtoMessage()    {}
@@ -1437,3 +1572,978 @@
 	0x99, 0xe4, 0x9d, 0x38, 0x8f, 0x31, 0xdc, 0x7a, 0x3d, 0x00, 0x00, 0xff, 0xff, 0x50, 0xd6, 0x5a,
 	0xc4, 0xe5, 0x16, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Fields_ProtoFile_FileDesc.Messages = xxx_Fields_ProtoFile_MessageDescs[0:1]
+	xxx_Fields_ProtoFile_MessageDescs[0].Enums = xxx_Fields_ProtoFile_EnumDescs[0:1]
+	xxx_Fields_ProtoFile_MessageDescs[0].Messages = xxx_Fields_ProtoFile_MessageDescs[1:9]
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[1].EnumType = xxx_Fields_ProtoFile_EnumTypes[0]
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[16].MessageType = xxx_Fields_ProtoFile_MessageTypes[8].Type
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[17].MessageType = xxx_Fields_ProtoFile_MessageTypes[1].Type
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[19].EnumType = xxx_Fields_ProtoFile_EnumTypes[0]
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[34].MessageType = xxx_Fields_ProtoFile_MessageTypes[8].Type
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[35].MessageType = xxx_Fields_ProtoFile_MessageTypes[2].Type
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[37].EnumType = xxx_Fields_ProtoFile_EnumTypes[0]
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[52].MessageType = xxx_Fields_ProtoFile_MessageTypes[8].Type
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[53].MessageType = xxx_Fields_ProtoFile_MessageTypes[3].Type
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[55].EnumType = xxx_Fields_ProtoFile_EnumTypes[0]
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[78].MessageType = xxx_Fields_ProtoFile_MessageDescs[4].Reference()
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[79].MessageType = xxx_Fields_ProtoFile_MessageDescs[5].Reference()
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[80].MessageType = xxx_Fields_ProtoFile_MessageDescs[6].Reference()
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[82].EnumType = xxx_Fields_ProtoFile_EnumTypes[0]
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[97].MessageType = xxx_Fields_ProtoFile_MessageTypes[8].Type
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[98].MessageType = xxx_Fields_ProtoFile_MessageTypes[7].Type
+	xxx_Fields_ProtoFile_MessageDescs[5].Fields[1].MessageType = xxx_Fields_ProtoFile_MessageTypes[8].Type
+	xxx_Fields_ProtoFile_MessageDescs[6].Fields[1].EnumType = xxx_Fields_ProtoFile_EnumTypes[0]
+	var err error
+	Fields_ProtoFile, err = prototype.NewFile(&xxx_Fields_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Fields_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Fields_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "proto2/fields.proto",
+	Package: "goproto.protoc.proto2",
+}
+var xxx_Fields_ProtoFile_EnumTypes = [1]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_Fields_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return FieldTestMessage_Enum(n)
+		},
+	),
+}
+var xxx_Fields_ProtoFile_EnumDescs = [1]prototype.Enum{
+	{
+		Name: "Enum",
+		Values: []prototype.EnumValue{
+			{Name: "ZERO", Number: 0},
+			{Name: "ONE", Number: 1},
+		},
+	},
+}
+var xxx_Fields_ProtoFile_MessageTypes = [9]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Fields_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(FieldTestMessage)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Fields_ProtoFile_MessageDescs[1].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(FieldTestMessage_OptionalGroup)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Fields_ProtoFile_MessageDescs[2].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(FieldTestMessage_RequiredGroup)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Fields_ProtoFile_MessageDescs[3].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(FieldTestMessage_RepeatedGroup)
+		},
+	)},
+	{ /* no message type for FieldTestMessage_MapInt32Int64Entry */ },
+	{ /* no message type for FieldTestMessage_MapStringMessageEntry */ },
+	{ /* no message type for FieldTestMessage_MapFixed64EnumEntry */ },
+	{Type: prototype.GoMessage(
+		xxx_Fields_ProtoFile_MessageDescs[7].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(FieldTestMessage_OneofGroup)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_Fields_ProtoFile_MessageDescs[8].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(FieldTestMessage_Message)
+		},
+	)},
+}
+var xxx_Fields_ProtoFile_MessageDescs = [9]prototype.Message{
+	{
+		Name: "FieldTestMessage",
+		Fields: []prototype.Field{
+			{
+				Name:        "optional_bool",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BoolKind,
+				JSONName:    "optionalBool",
+			},
+			{
+				Name:        "optional_enum",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "optionalEnum",
+			},
+			{
+				Name:        "optional_int32",
+				Number:      3,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "optionalInt32",
+			},
+			{
+				Name:        "optional_sint32",
+				Number:      4,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint32Kind,
+				JSONName:    "optionalSint32",
+			},
+			{
+				Name:        "optional_uint32",
+				Number:      5,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "optionalUint32",
+			},
+			{
+				Name:        "optional_int64",
+				Number:      6,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "optionalInt64",
+			},
+			{
+				Name:        "optional_sint64",
+				Number:      7,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint64Kind,
+				JSONName:    "optionalSint64",
+			},
+			{
+				Name:        "optional_uint64",
+				Number:      8,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "optionalUint64",
+			},
+			{
+				Name:        "optional_sfixed32",
+				Number:      9,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed32Kind,
+				JSONName:    "optionalSfixed32",
+			},
+			{
+				Name:        "optional_fixed32",
+				Number:      10,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed32Kind,
+				JSONName:    "optionalFixed32",
+			},
+			{
+				Name:        "optional_float",
+				Number:      11,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "optionalFloat",
+			},
+			{
+				Name:        "optional_sfixed64",
+				Number:      12,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed64Kind,
+				JSONName:    "optionalSfixed64",
+			},
+			{
+				Name:        "optional_fixed64",
+				Number:      13,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "optionalFixed64",
+			},
+			{
+				Name:        "optional_double",
+				Number:      14,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "optionalDouble",
+			},
+			{
+				Name:        "optional_string",
+				Number:      15,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "optionalString",
+			},
+			{
+				Name:        "optional_bytes",
+				Number:      16,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "optionalBytes",
+			},
+			{
+				Name:        "optional_Message",
+				Number:      17,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "optionalMessage",
+			},
+			{
+				Name:        "optionalgroup",
+				Number:      18,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.GroupKind,
+				JSONName:    "optionalgroup",
+			},
+			{
+				Name:        "required_bool",
+				Number:      101,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.BoolKind,
+				JSONName:    "requiredBool",
+			},
+			{
+				Name:        "required_enum",
+				Number:      102,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "requiredEnum",
+			},
+			{
+				Name:        "required_int32",
+				Number:      103,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "requiredInt32",
+			},
+			{
+				Name:        "required_sint32",
+				Number:      104,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.Sint32Kind,
+				JSONName:    "requiredSint32",
+			},
+			{
+				Name:        "required_uint32",
+				Number:      105,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "requiredUint32",
+			},
+			{
+				Name:        "required_int64",
+				Number:      106,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "requiredInt64",
+			},
+			{
+				Name:        "required_sint64",
+				Number:      107,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.Sint64Kind,
+				JSONName:    "requiredSint64",
+			},
+			{
+				Name:        "required_uint64",
+				Number:      108,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "requiredUint64",
+			},
+			{
+				Name:        "required_sfixed32",
+				Number:      109,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.Sfixed32Kind,
+				JSONName:    "requiredSfixed32",
+			},
+			{
+				Name:        "required_fixed32",
+				Number:      110,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.Fixed32Kind,
+				JSONName:    "requiredFixed32",
+			},
+			{
+				Name:        "required_float",
+				Number:      111,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "requiredFloat",
+			},
+			{
+				Name:        "required_sfixed64",
+				Number:      112,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.Sfixed64Kind,
+				JSONName:    "requiredSfixed64",
+			},
+			{
+				Name:        "required_fixed64",
+				Number:      113,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "requiredFixed64",
+			},
+			{
+				Name:        "required_double",
+				Number:      114,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "requiredDouble",
+			},
+			{
+				Name:        "required_string",
+				Number:      115,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "requiredString",
+			},
+			{
+				Name:        "required_bytes",
+				Number:      116,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "requiredBytes",
+			},
+			{
+				Name:        "required_Message",
+				Number:      117,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "requiredMessage",
+			},
+			{
+				Name:        "requiredgroup",
+				Number:      118,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.GroupKind,
+				JSONName:    "requiredgroup",
+			},
+			{
+				Name:        "repeated_bool",
+				Number:      201,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.BoolKind,
+				JSONName:    "repeatedBool",
+			},
+			{
+				Name:        "repeated_enum",
+				Number:      202,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "repeatedEnum",
+			},
+			{
+				Name:        "repeated_int32",
+				Number:      203,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "repeatedInt32",
+			},
+			{
+				Name:        "repeated_sint32",
+				Number:      204,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sint32Kind,
+				JSONName:    "repeatedSint32",
+			},
+			{
+				Name:        "repeated_uint32",
+				Number:      205,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "repeatedUint32",
+			},
+			{
+				Name:        "repeated_int64",
+				Number:      206,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "repeatedInt64",
+			},
+			{
+				Name:        "repeated_sint64",
+				Number:      207,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sint64Kind,
+				JSONName:    "repeatedSint64",
+			},
+			{
+				Name:        "repeated_uint64",
+				Number:      208,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "repeatedUint64",
+			},
+			{
+				Name:        "repeated_sfixed32",
+				Number:      209,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sfixed32Kind,
+				JSONName:    "repeatedSfixed32",
+			},
+			{
+				Name:        "repeated_fixed32",
+				Number:      210,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Fixed32Kind,
+				JSONName:    "repeatedFixed32",
+			},
+			{
+				Name:        "repeated_float",
+				Number:      211,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "repeatedFloat",
+			},
+			{
+				Name:        "repeated_sfixed64",
+				Number:      212,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sfixed64Kind,
+				JSONName:    "repeatedSfixed64",
+			},
+			{
+				Name:        "repeated_fixed64",
+				Number:      213,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "repeatedFixed64",
+			},
+			{
+				Name:        "repeated_double",
+				Number:      214,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "repeatedDouble",
+			},
+			{
+				Name:        "repeated_string",
+				Number:      215,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "repeatedString",
+			},
+			{
+				Name:        "repeated_bytes",
+				Number:      216,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "repeatedBytes",
+			},
+			{
+				Name:        "repeated_Message",
+				Number:      217,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "repeatedMessage",
+			},
+			{
+				Name:        "repeatedgroup",
+				Number:      218,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.GroupKind,
+				JSONName:    "repeatedgroup",
+			},
+			{
+				Name:        "default_bool",
+				Number:      301,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BoolKind,
+				JSONName:    "defaultBool",
+				Default:     protoreflect.ValueOf(bool(true)),
+			},
+			{
+				Name:        "default_enum",
+				Number:      302,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "defaultEnum",
+				Default:     protoreflect.ValueOf(string("ONE")),
+			},
+			{
+				Name:        "default_int32",
+				Number:      303,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "defaultInt32",
+				Default:     protoreflect.ValueOf(int32(1)),
+			},
+			{
+				Name:        "default_sint32",
+				Number:      304,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint32Kind,
+				JSONName:    "defaultSint32",
+				Default:     protoreflect.ValueOf(int32(1)),
+			},
+			{
+				Name:        "default_uint32",
+				Number:      305,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "defaultUint32",
+				Default:     protoreflect.ValueOf(uint32(1)),
+			},
+			{
+				Name:        "default_int64",
+				Number:      306,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "defaultInt64",
+				Default:     protoreflect.ValueOf(int64(1)),
+			},
+			{
+				Name:        "default_sint64",
+				Number:      307,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint64Kind,
+				JSONName:    "defaultSint64",
+				Default:     protoreflect.ValueOf(int64(1)),
+			},
+			{
+				Name:        "default_uint64",
+				Number:      308,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "defaultUint64",
+				Default:     protoreflect.ValueOf(uint64(1)),
+			},
+			{
+				Name:        "default_sfixed32",
+				Number:      309,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed32Kind,
+				JSONName:    "defaultSfixed32",
+				Default:     protoreflect.ValueOf(int32(1)),
+			},
+			{
+				Name:        "default_fixed32",
+				Number:      310,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed32Kind,
+				JSONName:    "defaultFixed32",
+				Default:     protoreflect.ValueOf(uint32(1)),
+			},
+			{
+				Name:        "default_float",
+				Number:      311,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "defaultFloat",
+				Default:     protoreflect.ValueOf(float32(3.14)),
+			},
+			{
+				Name:        "default_sfixed64",
+				Number:      312,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed64Kind,
+				JSONName:    "defaultSfixed64",
+				Default:     protoreflect.ValueOf(int64(1)),
+			},
+			{
+				Name:        "default_fixed64",
+				Number:      313,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "defaultFixed64",
+				Default:     protoreflect.ValueOf(uint64(1)),
+			},
+			{
+				Name:        "default_double",
+				Number:      314,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "defaultDouble",
+				Default:     protoreflect.ValueOf(float64(3.1415)),
+			},
+			{
+				Name:        "default_string",
+				Number:      315,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "defaultString",
+				Default:     protoreflect.ValueOf(string("hello,\"world!\"\n")),
+			},
+			{
+				Name:        "default_bytes",
+				Number:      316,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "defaultBytes",
+				Default:     protoreflect.ValueOf(("hello,ޭ\xbe\xef")),
+			},
+			{
+				Name:        "default_zero_string",
+				Number:      350,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "defaultZeroString",
+				Default:     protoreflect.ValueOf(string("")),
+			},
+			{
+				Name:        "default_zero_bytes",
+				Number:      351,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "defaultZeroBytes",
+				Default:     protoreflect.ValueOf(("")),
+			},
+			{
+				Name:        "default_float_neginf",
+				Number:      400,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "defaultFloatNeginf",
+				Default:     protoreflect.ValueOf(float32(math.Inf(-1))),
+			},
+			{
+				Name:        "default_float_posinf",
+				Number:      401,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "defaultFloatPosinf",
+				Default:     protoreflect.ValueOf(float32(math.Inf(+1))),
+			},
+			{
+				Name:        "default_float_nan",
+				Number:      402,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "defaultFloatNan",
+				Default:     protoreflect.ValueOf(float32(math.NaN())),
+			},
+			{
+				Name:        "default_double_neginf",
+				Number:      403,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "defaultDoubleNeginf",
+				Default:     protoreflect.ValueOf(float64(math.Inf(-1))),
+			},
+			{
+				Name:        "default_double_posinf",
+				Number:      404,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "defaultDoublePosinf",
+				Default:     protoreflect.ValueOf(float64(math.Inf(+1))),
+			},
+			{
+				Name:        "default_double_nan",
+				Number:      405,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "defaultDoubleNan",
+				Default:     protoreflect.ValueOf(float64(math.NaN())),
+			},
+			{
+				Name:        "map_int32_int64",
+				Number:      500,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapInt32Int64",
+			},
+			{
+				Name:        "map_string_message",
+				Number:      501,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapStringMessage",
+			},
+			{
+				Name:        "map_fixed64_enum",
+				Number:      502,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapFixed64Enum",
+			},
+			{
+				Name:        "oneof_bool",
+				Number:      601,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BoolKind,
+				JSONName:    "oneofBool",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_enum",
+				Number:      602,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "oneofEnum",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_int32",
+				Number:      603,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "oneofInt32",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_sint32",
+				Number:      604,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint32Kind,
+				JSONName:    "oneofSint32",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_uint32",
+				Number:      605,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "oneofUint32",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_int64",
+				Number:      606,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "oneofInt64",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_sint64",
+				Number:      607,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint64Kind,
+				JSONName:    "oneofSint64",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_uint64",
+				Number:      608,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "oneofUint64",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_sfixed32",
+				Number:      609,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed32Kind,
+				JSONName:    "oneofSfixed32",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_fixed32",
+				Number:      610,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed32Kind,
+				JSONName:    "oneofFixed32",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_float",
+				Number:      611,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "oneofFloat",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_sfixed64",
+				Number:      612,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed64Kind,
+				JSONName:    "oneofSfixed64",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_fixed64",
+				Number:      613,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "oneofFixed64",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_double",
+				Number:      614,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "oneofDouble",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_string",
+				Number:      615,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "oneofString",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_bytes",
+				Number:      616,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "oneofBytes",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_Message",
+				Number:      617,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "oneofMessage",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneofgroup",
+				Number:      618,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.GroupKind,
+				JSONName:    "oneofgroup",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_largest_tag",
+				Number:      536870911,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "oneofLargestTag",
+				OneofName:   "oneof_field",
+			},
+			{
+				Name:        "oneof_two_1",
+				Number:      700,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "oneofTwo1",
+				OneofName:   "oneof_two",
+			},
+			{
+				Name:        "oneof_two_2",
+				Number:      701,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "oneofTwo2",
+				OneofName:   "oneof_two",
+			},
+		},
+		Oneofs: []prototype.Oneof{
+			{Name: "oneof_field"},
+			{Name: "oneof_two"},
+		},
+	},
+	{
+		Name: "OptionalGroup",
+		Fields: []prototype.Field{
+			{
+				Name:        "optional_group",
+				Number:      19,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "optionalGroup",
+			},
+		},
+	},
+	{
+		Name: "RequiredGroup",
+		Fields: []prototype.Field{
+			{
+				Name:        "required_group",
+				Number:      119,
+				Cardinality: protoreflect.Required,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "requiredGroup",
+			},
+		},
+	},
+	{
+		Name: "RepeatedGroup",
+		Fields: []prototype.Field{
+			{
+				Name:        "repeated_group",
+				Number:      219,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "repeatedGroup",
+			},
+		},
+	},
+	{
+		Name: "MapInt32Int64Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "key",
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "value",
+			},
+		},
+	},
+	{
+		Name: "MapStringMessageEntry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "key",
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "value",
+			},
+		},
+	},
+	{
+		Name: "MapFixed64EnumEntry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "key",
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "value",
+			},
+		},
+	},
+	{
+		Name: "OneofGroup",
+		Fields: []prototype.Field{
+			{
+				Name:        "oneof_group_field",
+				Number:      619,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "oneofGroupField",
+			},
+		},
+	},
+	{
+		Name: "Message",
+	},
+}
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 7f6f395..4bc6666 100644
--- a/cmd/protoc-gen-go/testdata/proto2/nested_messages.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/nested_messages.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -28,6 +31,25 @@
 	XXX_sizecache        int32                 `json:"-"`
 }
 
+type xxx_Layer1 struct{ m *Layer1 }
+
+func (m *Layer1) ProtoReflect() protoreflect.Message {
+	return xxx_Layer1{m}
+}
+func (m xxx_Layer1) Type() protoreflect.MessageType {
+	return xxx_NestedMessages_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_Layer1) KnownFields() protoreflect.KnownFields {
+	return xxx_NestedMessages_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_Layer1) UnknownFields() protoreflect.UnknownFields {
+	return xxx_NestedMessages_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_Layer1) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Layer1) ProtoMutable() {}
+
 func (m *Layer1) Reset()         { *m = Layer1{} }
 func (m *Layer1) String() string { return proto.CompactTextString(m) }
 func (*Layer1) ProtoMessage()    {}
@@ -74,6 +96,25 @@
 	XXX_sizecache        int32                 `json:"-"`
 }
 
+type xxx_Layer1_Layer2 struct{ m *Layer1_Layer2 }
+
+func (m *Layer1_Layer2) ProtoReflect() protoreflect.Message {
+	return xxx_Layer1_Layer2{m}
+}
+func (m xxx_Layer1_Layer2) Type() protoreflect.MessageType {
+	return xxx_NestedMessages_ProtoFile_MessageTypes[1].Type
+}
+func (m xxx_Layer1_Layer2) KnownFields() protoreflect.KnownFields {
+	return xxx_NestedMessages_ProtoFile_MessageTypes[1].KnownFieldsOf(m.m)
+}
+func (m xxx_Layer1_Layer2) UnknownFields() protoreflect.UnknownFields {
+	return xxx_NestedMessages_ProtoFile_MessageTypes[1].UnknownFieldsOf(m.m)
+}
+func (m xxx_Layer1_Layer2) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Layer1_Layer2) ProtoMutable() {}
+
 func (m *Layer1_Layer2) Reset()         { *m = Layer1_Layer2{} }
 func (m *Layer1_Layer2) String() string { return proto.CompactTextString(m) }
 func (*Layer1_Layer2) ProtoMessage()    {}
@@ -112,6 +153,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Layer1_Layer2_Layer3 struct{ m *Layer1_Layer2_Layer3 }
+
+func (m *Layer1_Layer2_Layer3) ProtoReflect() protoreflect.Message {
+	return xxx_Layer1_Layer2_Layer3{m}
+}
+func (m xxx_Layer1_Layer2_Layer3) Type() protoreflect.MessageType {
+	return xxx_NestedMessages_ProtoFile_MessageTypes[2].Type
+}
+func (m xxx_Layer1_Layer2_Layer3) KnownFields() protoreflect.KnownFields {
+	return xxx_NestedMessages_ProtoFile_MessageTypes[2].KnownFieldsOf(m.m)
+}
+func (m xxx_Layer1_Layer2_Layer3) UnknownFields() protoreflect.UnknownFields {
+	return xxx_NestedMessages_ProtoFile_MessageTypes[2].UnknownFieldsOf(m.m)
+}
+func (m xxx_Layer1_Layer2_Layer3) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Layer1_Layer2_Layer3) ProtoMutable() {}
+
 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()    {}
@@ -160,3 +220,83 @@
 	0x79, 0xba, 0xe9, 0xf9, 0xfa, 0x25, 0xa9, 0xc5, 0x25, 0x29, 0x89, 0x25, 0x89, 0x10, 0x61, 0x23,
 	0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x11, 0x21, 0xb0, 0x06, 0x47, 0x01, 0x00, 0x00,
 }
+
+func init() {
+	xxx_NestedMessages_ProtoFile_FileDesc.Messages = xxx_NestedMessages_ProtoFile_MessageDescs[0:1]
+	xxx_NestedMessages_ProtoFile_MessageDescs[0].Messages = xxx_NestedMessages_ProtoFile_MessageDescs[1:2]
+	xxx_NestedMessages_ProtoFile_MessageDescs[1].Messages = xxx_NestedMessages_ProtoFile_MessageDescs[2:3]
+	xxx_NestedMessages_ProtoFile_MessageDescs[0].Fields[0].MessageType = xxx_NestedMessages_ProtoFile_MessageTypes[1].Type
+	xxx_NestedMessages_ProtoFile_MessageDescs[0].Fields[1].MessageType = xxx_NestedMessages_ProtoFile_MessageTypes[2].Type
+	xxx_NestedMessages_ProtoFile_MessageDescs[1].Fields[0].MessageType = xxx_NestedMessages_ProtoFile_MessageTypes[2].Type
+	var err error
+	NestedMessages_ProtoFile, err = prototype.NewFile(&xxx_NestedMessages_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var NestedMessages_ProtoFile protoreflect.FileDescriptor
+
+var xxx_NestedMessages_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "proto2/nested_messages.proto",
+	Package: "goproto.protoc.proto2",
+}
+var xxx_NestedMessages_ProtoFile_MessageTypes = [3]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_NestedMessages_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Layer1)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_NestedMessages_ProtoFile_MessageDescs[1].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Layer1_Layer2)
+		},
+	)},
+	{Type: prototype.GoMessage(
+		xxx_NestedMessages_ProtoFile_MessageDescs[2].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Layer1_Layer2_Layer3)
+		},
+	)},
+}
+var xxx_NestedMessages_ProtoFile_MessageDescs = [3]prototype.Message{
+	{
+		Name: "Layer1",
+		Fields: []prototype.Field{
+			{
+				Name:        "l2",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "l2",
+			},
+			{
+				Name:        "l3",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "l3",
+			},
+		},
+	},
+	{
+		Name: "Layer2",
+		Fields: []prototype.Field{
+			{
+				Name:        "l3",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "l3",
+			},
+		},
+	},
+	{
+		Name: "Layer3",
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go b/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go
index 869707d..e168402 100644
--- a/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto2/proto2.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -28,6 +31,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_Message struct{ m *Message }
+
+func (m *Message) ProtoReflect() protoreflect.Message {
+	return xxx_Message{m}
+}
+func (m xxx_Message) Type() protoreflect.MessageType {
+	return xxx_Proto2_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_Message) KnownFields() protoreflect.KnownFields {
+	return xxx_Proto2_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_Message) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Proto2_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_Message) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_Message) ProtoMutable() {}
+
 func (m *Message) Reset()         { *m = Message{} }
 func (m *Message) String() string { return proto.CompactTextString(m) }
 func (*Message) ProtoMessage()    {}
@@ -86,3 +108,52 @@
 	0x49, 0x6a, 0x71, 0x49, 0x4a, 0x62, 0x49, 0x22, 0xd4, 0xa9, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff,
 	0x85, 0x42, 0x0d, 0x5f, 0xba, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Proto2_ProtoFile_FileDesc.Messages = xxx_Proto2_ProtoFile_MessageDescs[0:1]
+	xxx_Proto2_ProtoFile_MessageDescs[0].Fields[1].MessageType = xxx_Proto2_ProtoFile_MessageTypes[0].Type
+	var err error
+	Proto2_ProtoFile, err = prototype.NewFile(&xxx_Proto2_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Proto2_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Proto2_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto2,
+	Path:    "proto2/proto2.proto",
+	Package: "goproto.protoc.proto2",
+}
+var xxx_Proto2_ProtoFile_MessageTypes = [1]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Proto2_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(Message)
+		},
+	)},
+}
+var xxx_Proto2_ProtoFile_MessageDescs = [1]prototype.Message{
+	{
+		Name: "Message",
+		Fields: []prototype.Field{
+			{
+				Name:        "i32",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "i32",
+			},
+			{
+				Name:        "m",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "m",
+			},
+		},
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/proto3/enum.pb.go b/cmd/protoc-gen-go/testdata/proto3/enum.pb.go
index cce047c..97ac497 100644
--- a/cmd/protoc-gen-go/testdata/proto3/enum.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto3/enum.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -28,6 +31,18 @@
 	Enum_TWO  Enum = 2
 )
 
+type xxx_Enum Enum
+
+func (e Enum) ProtoReflect() protoreflect.Enum {
+	return (xxx_Enum)(e)
+}
+func (e xxx_Enum) Type() protoreflect.EnumType {
+	return xxx_Enum_ProtoFile_EnumTypes[0]
+}
+func (e xxx_Enum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var Enum_name = map[int32]string{
 	0: "ZERO",
 	1: "ONE",
@@ -66,3 +81,40 @@
 	0x6e, 0x7a, 0xbe, 0x7e, 0x49, 0x6a, 0x71, 0x49, 0x4a, 0x62, 0x49, 0x22, 0x44, 0xd8, 0x38, 0x89,
 	0x0d, 0x42, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x96, 0x4a, 0x7d, 0xc7, 0x99, 0x00, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Enum_ProtoFile_FileDesc.Enums = xxx_Enum_ProtoFile_EnumDescs[0:1]
+	var err error
+	Enum_ProtoFile, err = prototype.NewFile(&xxx_Enum_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Enum_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Enum_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "proto3/enum.proto",
+	Package: "goproto.protoc.proto3",
+}
+var xxx_Enum_ProtoFile_EnumTypes = [1]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_Enum_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return Enum(n)
+		},
+	),
+}
+var xxx_Enum_ProtoFile_EnumDescs = [1]prototype.Enum{
+	{
+		Name: "Enum",
+		Values: []prototype.EnumValue{
+			{Name: "ZERO", Number: 0},
+			{Name: "ONE", Number: 1},
+			{Name: "TWO", Number: 2},
+		},
+	},
+}
diff --git a/cmd/protoc-gen-go/testdata/proto3/fields.pb.go b/cmd/protoc-gen-go/testdata/proto3/fields.pb.go
index 62b0d42..0acd32f 100644
--- a/cmd/protoc-gen-go/testdata/proto3/fields.pb.go
+++ b/cmd/protoc-gen-go/testdata/proto3/fields.pb.go
@@ -6,6 +6,9 @@
 import (
 	fmt "fmt"
 	proto "github.com/golang/protobuf/proto"
+	protoreflect "github.com/golang/protobuf/v2/reflect/protoreflect"
+	prototype "github.com/golang/protobuf/v2/reflect/prototype"
+	protoimpl "github.com/golang/protobuf/v2/runtime/protoimpl"
 	math "math"
 )
 
@@ -26,6 +29,18 @@
 	FieldTestMessage_ZERO FieldTestMessage_Enum = 0
 )
 
+type xxx_FieldTestMessage_Enum FieldTestMessage_Enum
+
+func (e FieldTestMessage_Enum) ProtoReflect() protoreflect.Enum {
+	return (xxx_FieldTestMessage_Enum)(e)
+}
+func (e xxx_FieldTestMessage_Enum) Type() protoreflect.EnumType {
+	return xxx_Fields_ProtoFile_EnumTypes[0]
+}
+func (e xxx_FieldTestMessage_Enum) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(e)
+}
+
 var FieldTestMessage_Enum_name = map[int32]string{
 	0: "ZERO",
 }
@@ -85,6 +100,25 @@
 	XXX_sizecache        int32                                `json:"-"`
 }
 
+type xxx_FieldTestMessage struct{ m *FieldTestMessage }
+
+func (m *FieldTestMessage) ProtoReflect() protoreflect.Message {
+	return xxx_FieldTestMessage{m}
+}
+func (m xxx_FieldTestMessage) Type() protoreflect.MessageType {
+	return xxx_Fields_ProtoFile_MessageTypes[0].Type
+}
+func (m xxx_FieldTestMessage) KnownFields() protoreflect.KnownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[0].KnownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[0].UnknownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_FieldTestMessage) ProtoMutable() {}
+
 func (m *FieldTestMessage) Reset()         { *m = FieldTestMessage{} }
 func (m *FieldTestMessage) String() string { return proto.CompactTextString(m) }
 func (*FieldTestMessage) ProtoMessage()    {}
@@ -375,6 +409,25 @@
 	XXX_sizecache        int32    `json:"-"`
 }
 
+type xxx_FieldTestMessage_Message struct{ m *FieldTestMessage_Message }
+
+func (m *FieldTestMessage_Message) ProtoReflect() protoreflect.Message {
+	return xxx_FieldTestMessage_Message{m}
+}
+func (m xxx_FieldTestMessage_Message) Type() protoreflect.MessageType {
+	return xxx_Fields_ProtoFile_MessageTypes[4].Type
+}
+func (m xxx_FieldTestMessage_Message) KnownFields() protoreflect.KnownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[4].KnownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_Message) UnknownFields() protoreflect.UnknownFields {
+	return xxx_Fields_ProtoFile_MessageTypes[4].UnknownFieldsOf(m.m)
+}
+func (m xxx_FieldTestMessage_Message) Interface() protoreflect.ProtoMessage {
+	return m.m
+}
+func (m xxx_FieldTestMessage_Message) ProtoMutable() {}
+
 func (m *FieldTestMessage_Message) Reset()         { *m = FieldTestMessage_Message{} }
 func (m *FieldTestMessage_Message) String() string { return proto.CompactTextString(m) }
 func (*FieldTestMessage_Message) ProtoMessage()    {}
@@ -466,3 +519,392 @@
 	0x3a, 0xb6, 0x7f, 0xe8, 0x04, 0xdd, 0xd0, 0x5e, 0x86, 0x13, 0x2b, 0xb4, 0x78, 0xb9, 0x3f, 0xaa,
 	0xf0, 0xeb, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbb, 0x1c, 0x0b, 0xbf, 0x4a, 0x09, 0x00, 0x00,
 }
+
+func init() {
+	xxx_Fields_ProtoFile_FileDesc.Messages = xxx_Fields_ProtoFile_MessageDescs[0:1]
+	xxx_Fields_ProtoFile_MessageDescs[0].Enums = xxx_Fields_ProtoFile_EnumDescs[0:1]
+	xxx_Fields_ProtoFile_MessageDescs[0].Messages = xxx_Fields_ProtoFile_MessageDescs[1:5]
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[1].EnumType = xxx_Fields_ProtoFile_EnumTypes[0]
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[16].MessageType = xxx_Fields_ProtoFile_MessageTypes[4].Type
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[18].EnumType = xxx_Fields_ProtoFile_EnumTypes[0]
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[33].MessageType = xxx_Fields_ProtoFile_MessageTypes[4].Type
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[34].MessageType = xxx_Fields_ProtoFile_MessageDescs[1].Reference()
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[35].MessageType = xxx_Fields_ProtoFile_MessageDescs[2].Reference()
+	xxx_Fields_ProtoFile_MessageDescs[0].Fields[36].MessageType = xxx_Fields_ProtoFile_MessageDescs[3].Reference()
+	xxx_Fields_ProtoFile_MessageDescs[2].Fields[1].MessageType = xxx_Fields_ProtoFile_MessageTypes[4].Type
+	xxx_Fields_ProtoFile_MessageDescs[3].Fields[1].EnumType = xxx_Fields_ProtoFile_EnumTypes[0]
+	var err error
+	Fields_ProtoFile, err = prototype.NewFile(&xxx_Fields_ProtoFile_FileDesc)
+	if err != nil {
+		panic(err)
+	}
+}
+
+const _ = protoimpl.EnforceVersion(protoimpl.Version - 0)
+
+var Fields_ProtoFile protoreflect.FileDescriptor
+
+var xxx_Fields_ProtoFile_FileDesc = prototype.File{
+	Syntax:  protoreflect.Proto3,
+	Path:    "proto3/fields.proto",
+	Package: "goproto.protoc.proto3",
+}
+var xxx_Fields_ProtoFile_EnumTypes = [1]protoreflect.EnumType{
+	prototype.GoEnum(
+		xxx_Fields_ProtoFile_EnumDescs[0].Reference(),
+		func(_ protoreflect.EnumType, n protoreflect.EnumNumber) protoreflect.ProtoEnum {
+			return FieldTestMessage_Enum(n)
+		},
+	),
+}
+var xxx_Fields_ProtoFile_EnumDescs = [1]prototype.Enum{
+	{
+		Name: "Enum",
+		Values: []prototype.EnumValue{
+			{Name: "ZERO", Number: 0},
+		},
+	},
+}
+var xxx_Fields_ProtoFile_MessageTypes = [5]protoimpl.MessageType{
+	{Type: prototype.GoMessage(
+		xxx_Fields_ProtoFile_MessageDescs[0].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(FieldTestMessage)
+		},
+	)},
+	{ /* no message type for FieldTestMessage_MapInt32Int64Entry */ },
+	{ /* no message type for FieldTestMessage_MapStringMessageEntry */ },
+	{ /* no message type for FieldTestMessage_MapFixed64EnumEntry */ },
+	{Type: prototype.GoMessage(
+		xxx_Fields_ProtoFile_MessageDescs[4].Reference(),
+		func(protoreflect.MessageType) protoreflect.ProtoMessage {
+			return new(FieldTestMessage_Message)
+		},
+	)},
+}
+var xxx_Fields_ProtoFile_MessageDescs = [5]prototype.Message{
+	{
+		Name: "FieldTestMessage",
+		Fields: []prototype.Field{
+			{
+				Name:        "optional_bool",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "optionalBool",
+			},
+			{
+				Name:        "optional_enum",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "optionalEnum",
+			},
+			{
+				Name:        "optional_int32",
+				Number:      3,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "optionalInt32",
+			},
+			{
+				Name:        "optional_sint32",
+				Number:      4,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint32Kind,
+				JSONName:    "optionalSint32",
+			},
+			{
+				Name:        "optional_uint32",
+				Number:      5,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "optionalUint32",
+			},
+			{
+				Name:        "optional_int64",
+				Number:      6,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "optionalInt64",
+			},
+			{
+				Name:        "optional_sint64",
+				Number:      7,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sint64Kind,
+				JSONName:    "optionalSint64",
+			},
+			{
+				Name:        "optional_uint64",
+				Number:      8,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "optionalUint64",
+			},
+			{
+				Name:        "optional_sfixed32",
+				Number:      9,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed32Kind,
+				JSONName:    "optionalSfixed32",
+			},
+			{
+				Name:        "optional_fixed32",
+				Number:      10,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed32Kind,
+				JSONName:    "optionalFixed32",
+			},
+			{
+				Name:        "optional_float",
+				Number:      11,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "optionalFloat",
+			},
+			{
+				Name:        "optional_sfixed64",
+				Number:      12,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Sfixed64Kind,
+				JSONName:    "optionalSfixed64",
+			},
+			{
+				Name:        "optional_fixed64",
+				Number:      13,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "optionalFixed64",
+			},
+			{
+				Name:        "optional_double",
+				Number:      14,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "optionalDouble",
+			},
+			{
+				Name:        "optional_string",
+				Number:      15,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "optionalString",
+			},
+			{
+				Name:        "optional_bytes",
+				Number:      16,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "optionalBytes",
+			},
+			{
+				Name:        "optional_Message",
+				Number:      17,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "optionalMessage",
+			},
+			{
+				Name:        "repeated_bool",
+				Number:      201,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.BoolKind,
+				JSONName:    "repeatedBool",
+			},
+			{
+				Name:        "repeated_enum",
+				Number:      202,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "repeatedEnum",
+			},
+			{
+				Name:        "repeated_int32",
+				Number:      203,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "repeatedInt32",
+			},
+			{
+				Name:        "repeated_sint32",
+				Number:      204,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sint32Kind,
+				JSONName:    "repeatedSint32",
+			},
+			{
+				Name:        "repeated_uint32",
+				Number:      205,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Uint32Kind,
+				JSONName:    "repeatedUint32",
+			},
+			{
+				Name:        "repeated_int64",
+				Number:      206,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "repeatedInt64",
+			},
+			{
+				Name:        "repeated_sint64",
+				Number:      207,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sint64Kind,
+				JSONName:    "repeatedSint64",
+			},
+			{
+				Name:        "repeated_uint64",
+				Number:      208,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Uint64Kind,
+				JSONName:    "repeatedUint64",
+			},
+			{
+				Name:        "repeated_sfixed32",
+				Number:      209,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sfixed32Kind,
+				JSONName:    "repeatedSfixed32",
+			},
+			{
+				Name:        "repeated_fixed32",
+				Number:      210,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Fixed32Kind,
+				JSONName:    "repeatedFixed32",
+			},
+			{
+				Name:        "repeated_float",
+				Number:      211,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.FloatKind,
+				JSONName:    "repeatedFloat",
+			},
+			{
+				Name:        "repeated_sfixed64",
+				Number:      212,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Sfixed64Kind,
+				JSONName:    "repeatedSfixed64",
+			},
+			{
+				Name:        "repeated_fixed64",
+				Number:      213,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "repeatedFixed64",
+			},
+			{
+				Name:        "repeated_double",
+				Number:      214,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.DoubleKind,
+				JSONName:    "repeatedDouble",
+			},
+			{
+				Name:        "repeated_string",
+				Number:      215,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "repeatedString",
+			},
+			{
+				Name:        "repeated_bytes",
+				Number:      216,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.BytesKind,
+				JSONName:    "repeatedBytes",
+			},
+			{
+				Name:        "repeated_Message",
+				Number:      217,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "repeatedMessage",
+			},
+			{
+				Name:        "map_int32_int64",
+				Number:      500,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapInt32Int64",
+			},
+			{
+				Name:        "map_string_message",
+				Number:      501,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapStringMessage",
+			},
+			{
+				Name:        "map_fixed64_enum",
+				Number:      502,
+				Cardinality: protoreflect.Repeated,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "mapFixed64Enum",
+			},
+		},
+	},
+	{
+		Name: "MapInt32Int64Entry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int32Kind,
+				JSONName:    "key",
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Int64Kind,
+				JSONName:    "value",
+			},
+		},
+	},
+	{
+		Name: "MapStringMessageEntry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.StringKind,
+				JSONName:    "key",
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.MessageKind,
+				JSONName:    "value",
+			},
+		},
+	},
+	{
+		Name: "MapFixed64EnumEntry",
+		Fields: []prototype.Field{
+			{
+				Name:        "key",
+				Number:      1,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.Fixed64Kind,
+				JSONName:    "key",
+			},
+			{
+				Name:        "value",
+				Number:      2,
+				Cardinality: protoreflect.Optional,
+				Kind:        protoreflect.EnumKind,
+				JSONName:    "value",
+			},
+		},
+	},
+	{
+		Name: "Message",
+	},
+}
diff --git a/protogen/names.go b/protogen/names.go
index d561a5f..dc4c86c 100644
--- a/protogen/names.go
+++ b/protogen/names.go
@@ -46,18 +46,36 @@
 // A GoPackageName is the name of a Go package. e.g., "protobuf".
 type GoPackageName string
 
-// cleanPacakgeName converts a string to a valid Go package name.
+// cleanPackageName converts a string to a valid Go package name.
 func cleanPackageName(name string) GoPackageName {
-	name = strings.Map(badToUnderscore, name)
-	// Identifier must not be keyword: insert _.
-	if token.Lookup(name).IsKeyword() {
-		name = "_" + name
+	return GoPackageName(cleanGoName(name, false))
+}
+
+// cleanGoName converts a string to a valid Go identifier.
+// If mustExport, then the returned identifier is exported if not already.
+func cleanGoName(name string, mustExport bool) string {
+	name = strings.Map(func(r rune) rune {
+		if unicode.IsLetter(r) || unicode.IsDigit(r) {
+			return r
+		}
+		return '_'
+	}, name)
+	prefix := "_"
+	if mustExport {
+		prefix = "X"
 	}
-	// Identifier must not begin with digit: insert _.
-	if r, _ := utf8.DecodeRuneInString(name); unicode.IsDigit(r) {
-		name = "_" + name
+	switch r, n := utf8.DecodeRuneInString(name); {
+	case token.Lookup(name).IsKeyword():
+		return prefix + name
+	case unicode.IsDigit(r):
+		return prefix + name
+	case mustExport && !unicode.IsUpper(r):
+		if unicode.IsLower(r) {
+			return string(unicode.ToUpper(r)) + name[n:]
+		}
+		return prefix + name
 	}
-	return GoPackageName(name)
+	return name
 }
 
 var isGoPredeclaredIdentifier = map[string]bool{
@@ -102,16 +120,6 @@
 	"uintptr":    true,
 }
 
-// badToUnderscore is the mapping function used to generate Go names from package names,
-// which can be dotted in the input .proto file.  It replaces non-identifier characters such as
-// dot or dash with underscore.
-func badToUnderscore(r rune) rune {
-	if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
-		return r
-	}
-	return '_'
-}
-
 // baseName returns the last path element of the name, with the last dotted suffix removed.
 func baseName(name string) string {
 	// First, find the last element
diff --git a/protogen/names_test.go b/protogen/names_test.go
index 3271954..e253429 100644
--- a/protogen/names_test.go
+++ b/protogen/names_test.go
@@ -25,6 +25,11 @@
 		{"_one._two", "XOne_XTwo"},
 		{"SCREAMING_SNAKE_CASE", "SCREAMING_SNAKE_CASE"},
 		{"double__underscore", "Double_Underscore"},
+		{"camelCase", "CamelCase"},
+		{"go2proto", "Go2Proto"},
+		{"世界", "世界"},
+		{"x世界", "X世界"},
+		{"foo_bar世界", "FooBar世界"},
 	}
 	for _, tc := range tests {
 		if got := camelCase(tc.in); got != tc.want {
@@ -32,3 +37,24 @@
 		}
 	}
 }
+
+func TestCleanGoName(t *testing.T) {
+	tests := []struct {
+		in, want, wantExported string
+	}{
+		{"", "", "X"},
+		{"hello", "hello", "Hello"},
+		{"hello-world!!", "hello_world__", "Hello_world__"},
+		{"hello-\xde\xad\xbe\xef\x00", "hello_____", "Hello_____"},
+		{"hello 世界", "hello_世界", "Hello_世界"},
+		{"世界", "世界", "X世界"},
+	}
+	for _, tc := range tests {
+		if got := cleanGoName(tc.in, false); got != tc.want {
+			t.Errorf("cleanGoName(%q, false) = %q, want %q", tc.in, got, tc.want)
+		}
+		if got := cleanGoName(tc.in, true); got != tc.wantExported {
+			t.Errorf("cleanGoName(%q, true) = %q, want %q", tc.in, got, tc.wantExported)
+		}
+	}
+}
diff --git a/protogen/protogen.go b/protogen/protogen.go
index 95a499f..cdfccce 100644
--- a/protogen/protogen.go
+++ b/protogen/protogen.go
@@ -379,13 +379,14 @@
 	Desc  protoreflect.FileDescriptor
 	Proto *descriptorpb.FileDescriptorProto
 
-	GoPackageName GoPackageName // name of this file's Go package
-	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
-	Services      []*Service    // top-level service declarations
-	Generate      bool          // true if we should generate code for this file
+	GoDescriptorIdent GoIdent       // name of Go variable for the file descriptor
+	GoPackageName     GoPackageName // name of this file's Go package
+	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
+	Services          []*Service    // top-level service declarations
+	Generate          bool          // true if we should generate code for this file
 
 	// GeneratedFilenamePrefix is used to construct filenames for generated
 	// files associated with this source file.
@@ -429,6 +430,10 @@
 			prefix = path.Join(string(importPath), path.Base(prefix))
 		}
 	}
+	f.GoDescriptorIdent = GoIdent{
+		GoName:       camelCase(cleanGoName(path.Base(prefix), true)) + "_ProtoFile",
+		GoImportPath: f.GoImportPath,
+	}
 	f.GeneratedFilenamePrefix = prefix
 
 	for _, loc := range p.GetSourceCodeInfo().GetLocation() {
diff --git a/reflect/protoreflect/proto.go b/reflect/protoreflect/proto.go
index 2c14a8f..6ef9e89 100644
--- a/reflect/protoreflect/proto.go
+++ b/reflect/protoreflect/proto.go
@@ -65,6 +65,8 @@
 		return false
 	}
 }
+
+// String returns s as a proto source identifier.
 func (s Syntax) String() string {
 	switch s {
 	case Proto2:
@@ -76,6 +78,18 @@
 	}
 }
 
+// GoString returns s as a Go source identifier.
+func (s Syntax) GoString() string {
+	switch s {
+	case Proto2:
+		return "Proto2"
+	case Proto3:
+		return "Proto3"
+	default:
+		return "<unknown>"
+	}
+}
+
 // Cardinality determines whether a field is optional, required, or repeated.
 type Cardinality cardinality
 
@@ -97,6 +111,8 @@
 		return false
 	}
 }
+
+// String returns c as a proto source identifier.
 func (c Cardinality) String() string {
 	switch c {
 	case Optional:
@@ -110,6 +126,20 @@
 	}
 }
 
+// GoString returns c as a Go source identifier.
+func (c Cardinality) GoString() string {
+	switch c {
+	case Optional:
+		return "Optional"
+	case Required:
+		return "Required"
+	case Repeated:
+		return "Repeated"
+	default:
+		return "<unknown>"
+	}
+}
+
 // Kind indicates the basic proto kind of a field.
 type Kind kind
 
@@ -151,6 +181,8 @@
 		return false
 	}
 }
+
+// String returns k as a proto source identifier.
 func (k Kind) String() string {
 	switch k {
 	case BoolKind:
@@ -194,6 +226,50 @@
 	}
 }
 
+// GoString returns k as a Go source identifier.
+func (k Kind) GoString() string {
+	switch k {
+	case BoolKind:
+		return "BoolKind"
+	case EnumKind:
+		return "EnumKind"
+	case Int32Kind:
+		return "Int32Kind"
+	case Sint32Kind:
+		return "Sint32Kind"
+	case Uint32Kind:
+		return "Uint32Kind"
+	case Int64Kind:
+		return "Int64Kind"
+	case Sint64Kind:
+		return "Sint64Kind"
+	case Uint64Kind:
+		return "Uint64Kind"
+	case Sfixed32Kind:
+		return "Sfixed32Kind"
+	case Fixed32Kind:
+		return "Fixed32Kind"
+	case FloatKind:
+		return "FloatKind"
+	case Sfixed64Kind:
+		return "Sfixed64Kind"
+	case Fixed64Kind:
+		return "Fixed64Kind"
+	case DoubleKind:
+		return "DoubleKind"
+	case StringKind:
+		return "StringKind"
+	case BytesKind:
+		return "BytesKind"
+	case MessageKind:
+		return "MessageKind"
+	case GroupKind:
+		return "GroupKind"
+	default:
+		return "<unknown>"
+	}
+}
+
 // FieldNumber is the field number in a message.
 type FieldNumber = wire.Number
 
diff --git a/reflect/protoreflect/type.go b/reflect/protoreflect/type.go
index b2c4813..b6bace1 100644
--- a/reflect/protoreflect/type.go
+++ b/reflect/protoreflect/type.go
@@ -182,23 +182,9 @@
 
 // FileImport is the declaration for a proto file import.
 type FileImport struct {
-	// TODO: For FileDescriptor to be resolved, we must assume that there is
-	// a way to obtain the FileDescriptor for some dependency.
-	// How does this work for old dependencies that have not been regenerated
-	// and lack a FileDescriptor in a variable we can reference?
-	//
-	// A similar problem exists for FieldDescriptor.MessageDescriptor and
-	// FieldDescriptor.EnumDescriptor where a reference to external types
-	// is only possible if we assume that the dependency has
-	// reflection support available.
-	//
-	// Is it reasonable to assume that your dependencies have to be regenerated
-	// to have proto reflection support before you can depend on them?
-	//
-	// The decision here also affects Descriptor.IsPlaceholder
-
 	// FileDescriptor is the file type for the given import.
-	// It is a placeholder type if IsWeak is set.
+	// It is a placeholder descriptor if IsWeak is set or if a dependency has
+	// not been regenerated to implement the new reflection APIs.
 	FileDescriptor
 
 	// IsPublic reports whether this is a public import, which causes this file