reflect/protoreflect: add HasJSONName, ReservedRanges, and ReservedNames

These properties of descriptors are currently missing and makes it impossible
to convert a FileDescriptorProto into one of the structured Go representations
and convert it back to a proto message without loss of information.

Furthermore, ReservedRanges and ReservedNames has semantic importance
to text serialization.

Change-Id: Ic33c30020ad51912b143156b95f47a4fb8da3503
Reviewed-on: https://go-review.googlesource.com/c/153019
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/cmd/protoc-gen-go/internal_gengo/reflect.go b/cmd/protoc-gen-go/internal_gengo/reflect.go
index 0b0e03c..9f06602 100644
--- a/cmd/protoc-gen-go/internal_gengo/reflect.go
+++ b/cmd/protoc-gen-go/internal_gengo/reflect.go
@@ -207,6 +207,22 @@
 				g.P("{Name: ", strconv.Quote(string(value.Desc.Name())), ", Number: ", value.Desc.Number(), "},")
 			}
 			g.P("},")
+			if resvNames := enum.Desc.ReservedNames(); resvNames.Len() > 0 {
+				var ss []string
+				for i := 0; i < resvNames.Len(); i++ {
+					s := resvNames.Get(i)
+					ss = append(ss, strconv.Quote(string(s)))
+				}
+				g.P("ReservedNames: []", protoreflectPackage.Ident("Name"), "{", strings.Join(ss, ","), "},")
+			}
+			if resvRanges := enum.Desc.ReservedRanges(); resvRanges.Len() > 0 {
+				var ss []string
+				for i := 0; i < resvRanges.Len(); i++ {
+					r := resvRanges.Get(i)
+					ss = append(ss, fmt.Sprintf("{%d,%d}", r[0], r[1]))
+				}
+				g.P("ReservedRanges: [][2]", protoreflectPackage.Ident("EnumNumber"), "{", strings.Join(ss, ","), "},")
+			}
 			g.P("},")
 		}
 		g.P("}")
@@ -245,8 +261,9 @@
 					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.HasJSONName() {
+						g.P("JSONName: ", strconv.Quote(field.JSONName()), ",")
+					}
 					if field.HasDefault() {
 						v := field.Default().Interface()
 						typeName := reflect.TypeOf(v).Name()
@@ -285,6 +302,22 @@
 				}
 				g.P("},")
 			}
+			if resvNames := message.Desc.ReservedNames(); resvNames.Len() > 0 {
+				var ss []string
+				for i := 0; i < resvNames.Len(); i++ {
+					s := resvNames.Get(i)
+					ss = append(ss, strconv.Quote(string(s)))
+				}
+				g.P("ReservedNames: []", protoreflectPackage.Ident("Name"), "{", strings.Join(ss, ","), "},")
+			}
+			if resvRanges := message.Desc.ReservedRanges(); resvRanges.Len() > 0 {
+				var ss []string
+				for i := 0; i < resvRanges.Len(); i++ {
+					r := resvRanges.Get(i)
+					ss = append(ss, fmt.Sprintf("{%d,%d}", r[0], r[1]))
+				}
+				g.P("ReservedRanges: [][2]", protoreflectPackage.Ident("FieldNumber"), "{", strings.Join(ss, ","), "},")
+			}
 			if extRanges := message.Desc.ExtensionRanges(); extRanges.Len() > 0 {
 				var ss []string
 				for i := 0; i < extRanges.Len(); i++ {