reflect/protoreflect: add Enum.Type and Message.Type

CL/174938 removed these methods in favor of a method that returned
only the descriptors. This CL adds back in the Type methods alongside
the Descriptor methods.

In a vast majority of protobuf usages, only the descriptor information
is needed. However, there is a small percentage that legitimately needs
the Go type information. We should provide both, but document that the
descriptor-only information is preferred.

Change-Id: Ia0a098997fb1bd009994940ae8ea5257ccd87cae
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/184578
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/encoding/protojson/encode.go b/encoding/protojson/encode.go
index f17d3bb..5128ce4 100644
--- a/encoding/protojson/encode.go
+++ b/encoding/protojson/encode.go
@@ -256,12 +256,11 @@
 		if !fd.IsExtension() {
 			return true
 		}
-		xt := fd.(pref.ExtensionType)
 
 		// If extended type is a MessageSet, set field name to be the message type name.
-		name := xt.Descriptor().FullName()
-		if isMessageSetExtension(xt) {
-			name = xt.Descriptor().Message().FullName()
+		name := fd.FullName()
+		if isMessageSetExtension(fd) {
+			name = fd.Message().FullName()
 		}
 
 		// Use [name] format for JSON field name.
@@ -294,18 +293,17 @@
 }
 
 // isMessageSetExtension reports whether extension extends a message set.
-func isMessageSetExtension(xt pref.ExtensionType) bool {
-	xd := xt.Descriptor()
-	if xd.Name() != "message_set_extension" {
+func isMessageSetExtension(fd pref.FieldDescriptor) bool {
+	if fd.Name() != "message_set_extension" {
 		return false
 	}
-	md := xd.Message()
+	md := fd.Message()
 	if md == nil {
 		return false
 	}
-	if xd.FullName().Parent() != md.FullName() {
+	if fd.FullName().Parent() != md.FullName() {
 		return false
 	}
-	xmd, ok := xd.ContainingMessage().(interface{ IsMessageSet() bool })
+	xmd, ok := fd.ContainingMessage().(interface{ IsMessageSet() bool })
 	return ok && xmd.IsMessageSet()
 }
diff --git a/encoding/protojson/well_known_types.go b/encoding/protojson/well_known_types.go
index 77833d8..e744536 100644
--- a/encoding/protojson/well_known_types.go
+++ b/encoding/protojson/well_known_types.go
@@ -189,7 +189,7 @@
 	// If type of value has custom JSON encoding, marshal out a field "value"
 	// with corresponding custom JSON encoding of the embedded message as a
 	// field.
-	if isCustomType(emt.Descriptor().FullName()) {
+	if isCustomType(emt.FullName()) {
 		o.encoder.WriteName("value")
 		return o.marshalCustomType(em)
 	}
@@ -235,7 +235,7 @@
 
 	// Create new message for the embedded message type and unmarshal into it.
 	em := emt.New()
-	if isCustomType(emt.Descriptor().FullName()) {
+	if isCustomType(emt.FullName()) {
 		// If embedded message is a custom type, unmarshal the JSON "value" field
 		// into it.
 		if err := o.unmarshalAnyValue(em); err != nil {
diff --git a/encoding/prototext/encode.go b/encoding/prototext/encode.go
index 4d73041..7d244a9 100644
--- a/encoding/prototext/encode.go
+++ b/encoding/prototext/encode.go
@@ -252,17 +252,16 @@
 		if !fd.IsExtension() {
 			return true
 		}
-		xt := fd.(pref.ExtensionType)
 
 		// If extended type is a MessageSet, set field name to be the message type name.
-		name := xt.Descriptor().FullName()
-		if isMessageSetExtension(xt) {
-			name = xt.Descriptor().Message().FullName()
+		name := fd.FullName()
+		if isMessageSetExtension(fd) {
+			name = fd.Message().FullName()
 		}
 
 		// Use string type to produce [name] format.
 		tname := text.ValueOf(string(name))
-		entries, err = o.appendField(entries, tname, v, xt)
+		entries, err = o.appendField(entries, tname, v, fd)
 		if err != nil {
 			return false
 		}
@@ -281,19 +280,18 @@
 }
 
 // isMessageSetExtension reports whether extension extends a message set.
-func isMessageSetExtension(xt pref.ExtensionType) bool {
-	xd := xt.Descriptor()
-	if xd.Name() != "message_set_extension" {
+func isMessageSetExtension(fd pref.FieldDescriptor) bool {
+	if fd.Name() != "message_set_extension" {
 		return false
 	}
-	md := xd.Message()
+	md := fd.Message()
 	if md == nil {
 		return false
 	}
-	if xd.FullName().Parent() != md.FullName() {
+	if fd.FullName().Parent() != md.FullName() {
 		return false
 	}
-	xmd, ok := xd.ContainingMessage().(interface{ IsMessageSet() bool })
+	xmd, ok := fd.ContainingMessage().(interface{ IsMessageSet() bool })
 	return ok && xmd.IsMessageSet()
 }
 
diff --git a/encoding/testprotos/pb2/test.pb.go b/encoding/testprotos/pb2/test.pb.go
index a9c102a..a9231e8 100644
--- a/encoding/testprotos/pb2/test.pb.go
+++ b/encoding/testprotos/pb2/test.pb.go
@@ -59,6 +59,10 @@
 	return file_pb2_test_proto_enumTypes[0].EnumDescriptor
 }
 
+func (Enum) Type() protoreflect.EnumType {
+	return &file_pb2_test_proto_enumTypes[0]
+}
+
 func (x Enum) Number() protoreflect.EnumNumber {
 	return protoreflect.EnumNumber(x)
 }
@@ -112,6 +116,10 @@
 	return file_pb2_test_proto_enumTypes[1].EnumDescriptor
 }
 
+func (Enums_NestedEnum) Type() protoreflect.EnumType {
+	return &file_pb2_test_proto_enumTypes[1]
+}
+
 func (x Enums_NestedEnum) Number() protoreflect.EnumNumber {
 	return protoreflect.EnumNumber(x)
 }
diff --git a/encoding/testprotos/pb3/test.pb.go b/encoding/testprotos/pb3/test.pb.go
index aaa20e0..56e5e4a 100644
--- a/encoding/testprotos/pb3/test.pb.go
+++ b/encoding/testprotos/pb3/test.pb.go
@@ -54,6 +54,10 @@
 	return file_pb3_test_proto_enumTypes[0].EnumDescriptor
 }
 
+func (Enum) Type() protoreflect.EnumType {
+	return &file_pb3_test_proto_enumTypes[0]
+}
+
 func (x Enum) Number() protoreflect.EnumNumber {
 	return protoreflect.EnumNumber(x)
 }
@@ -100,6 +104,10 @@
 	return file_pb3_test_proto_enumTypes[1].EnumDescriptor
 }
 
+func (Enums_NestedEnum) Type() protoreflect.EnumType {
+	return &file_pb3_test_proto_enumTypes[1]
+}
+
 func (x Enums_NestedEnum) Number() protoreflect.EnumNumber {
 	return protoreflect.EnumNumber(x)
 }