internal/filedesc, internal/filetype: initial commit

The internal/fileinit package is split apart into two packages:
* internal/filedesc constructs descriptors from the raw proto.
It is very similar to the previous internal/fileinit package.
* internal/filetype wraps descriptors with Go type information

Overview:
* The internal/fileinit package will be deleted in a future CL.
It is kept around since the v1 repo currently depends on it.
* The internal/prototype package is deleted. All former usages of it
are now using internal/filedesc instead. Most significantly,
the reflect/protodesc package was almost entirely re-written.
* The internal/impl package drops support for messages that do not
have a Descriptor method (pre-2016). This removes a significant amount
of technical debt.
filedesc.Builder to parse raw descriptors.
* The internal/encoding/defval package now handles enum values by name.

Change-Id: I3957bcc8588a70470fd6c7de1122216b80615ab7
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/182360
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/cmd/pbdump/pbdump.go b/internal/cmd/pbdump/pbdump.go
index 7a7c3ce..8bc1753 100644
--- a/internal/cmd/pbdump/pbdump.go
+++ b/internal/cmd/pbdump/pbdump.go
@@ -19,8 +19,8 @@
 
 	"google.golang.org/protobuf/internal/encoding/pack"
 	"google.golang.org/protobuf/internal/encoding/wire"
-	"google.golang.org/protobuf/internal/prototype"
 	"google.golang.org/protobuf/internal/scalar"
+	"google.golang.org/protobuf/reflect/protodesc"
 	"google.golang.org/protobuf/reflect/protoreflect"
 
 	"google.golang.org/protobuf/types/descriptorpb"
@@ -202,41 +202,43 @@
 
 // Descriptor returns the field tree as a message descriptor.
 func (fs fields) Descriptor() (protoreflect.MessageDescriptor, error) {
-	ftyp, err := prototype.NewFile(&prototype.File{
-		Syntax:   protoreflect.Proto2,
-		Messages: []prototype.Message{fs.messageDescriptor("M")},
-	})
+	fd, err := protodesc.NewFile(&descriptorpb.FileDescriptorProto{
+		Name:        scalar.String("dump.proto"),
+		Syntax:      scalar.String("proto2"),
+		MessageType: []*descriptorpb.DescriptorProto{fs.messageDescriptor("M")},
+	}, nil)
 	if err != nil {
 		return nil, err
 	}
-	return ftyp.Messages().Get(0), nil
+	return fd.Messages().Get(0), nil
 }
-func (fs fields) messageDescriptor(name protoreflect.FullName) prototype.Message {
-	m := prototype.Message{Name: name.Name()}
+func (fs fields) messageDescriptor(name protoreflect.FullName) *descriptorpb.DescriptorProto {
+	m := &descriptorpb.DescriptorProto{Name: scalar.String(string(name.Name()))}
 	for _, n := range fs.sortedNums() {
-		f := prototype.Field{
-			Name:        protoreflect.Name(fmt.Sprintf("f%d", n)),
-			Number:      n,
-			Cardinality: protoreflect.Optional,
-			Kind:        fs[n].kind,
+		k := fs[n].kind
+		if !k.IsValid() {
+			k = protoreflect.MessageKind
 		}
-		if !f.Kind.IsValid() {
-			f.Kind = protoreflect.MessageKind
+		f := &descriptorpb.FieldDescriptorProto{
+			Name:   scalar.String(fmt.Sprintf("f%d", n)),
+			Number: scalar.Int32(int32(n)),
+			Label:  descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
+			Type:   descriptorpb.FieldDescriptorProto_Type(k).Enum(),
 		}
-		switch f.Kind {
+		switch k {
 		case protoreflect.BoolKind, protoreflect.EnumKind,
 			protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Uint32Kind,
 			protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Uint64Kind,
 			protoreflect.Sfixed32Kind, protoreflect.Fixed32Kind, protoreflect.FloatKind,
 			protoreflect.Sfixed64Kind, protoreflect.Fixed64Kind, protoreflect.DoubleKind:
-			f.Cardinality = protoreflect.Repeated
+			f.Label = descriptorpb.FieldDescriptorProto_LABEL_REPEATED.Enum()
 			f.Options = &descriptorpb.FieldOptions{Packed: scalar.Bool(true)}
 		case protoreflect.MessageKind, protoreflect.GroupKind:
 			s := name.Append(protoreflect.Name(fmt.Sprintf("M%d", n)))
-			f.MessageType = prototype.PlaceholderMessage(s)
-			m.Messages = append(m.Messages, fs[n].sub.messageDescriptor(s))
+			f.TypeName = scalar.String(string("." + s))
+			m.NestedType = append(m.NestedType, fs[n].sub.messageDescriptor(s))
 		}
-		m.Fields = append(m.Fields, f)
+		m.Field = append(m.Field, f)
 	}
 	return m
 }
diff --git a/internal/cmd/pbdump/pbdump_test.go b/internal/cmd/pbdump/pbdump_test.go
index 57ec1b5..a3f6998 100644
--- a/internal/cmd/pbdump/pbdump_test.go
+++ b/internal/cmd/pbdump/pbdump_test.go
@@ -9,13 +9,22 @@
 	"strings"
 	"testing"
 
-	"github.com/google/go-cmp/cmp"
-	"github.com/google/go-cmp/cmp/cmpopts"
-
-	ptype "google.golang.org/protobuf/internal/prototype"
+	"google.golang.org/protobuf/encoding/prototext"
+	"google.golang.org/protobuf/proto"
 	pref "google.golang.org/protobuf/reflect/protoreflect"
+
+	"google.golang.org/protobuf/types/descriptorpb"
 )
 
+func mustMakeMessage(s string) *descriptorpb.DescriptorProto {
+	s = fmt.Sprintf(`name:"test.proto" syntax:"proto2" message_type:[{%s}]`, s)
+	pb := new(descriptorpb.FileDescriptorProto)
+	if err := prototext.Unmarshal([]byte(s), pb); err != nil {
+		panic(err)
+	}
+	return pb.MessageType[0]
+}
+
 func TestFields(t *testing.T) {
 	type fieldsKind struct {
 		kind   pref.Kind
@@ -23,11 +32,11 @@
 	}
 	tests := []struct {
 		inFields []fieldsKind
-		wantMsg  ptype.Message
+		wantMsg  *descriptorpb.DescriptorProto
 		wantErr  string
 	}{{
 		inFields: []fieldsKind{{pref.MessageKind, ""}},
-		wantMsg:  ptype.Message{Name: "M"},
+		wantMsg:  mustMakeMessage(`name:"M"`),
 	}, {
 		inFields: []fieldsKind{{pref.MessageKind, "987654321"}},
 		wantErr:  "invalid field: 987654321",
@@ -52,44 +61,33 @@
 			{pref.MessageKind, "  10.20.30, 10.21   "},
 			{pref.GroupKind, "10"},
 		},
-		wantMsg: ptype.Message{
-			Name: "M",
-			Fields: []ptype.Field{
-				{Name: "f10", Number: 10, Cardinality: pref.Optional, Kind: pref.GroupKind, MessageType: ptype.PlaceholderMessage("M.M10")},
-			},
-			Messages: []ptype.Message{{
-				Name: "M10",
-				Fields: []ptype.Field{
-					{Name: "f20", Number: 20, Cardinality: pref.Optional, Kind: pref.MessageKind, MessageType: ptype.PlaceholderMessage("M.M10.M20")},
-					{Name: "f21", Number: 21, Cardinality: pref.Optional, Kind: pref.MessageKind, MessageType: ptype.PlaceholderMessage("M.M10.M21")},
-				},
-				Messages: []ptype.Message{{
-					Name: "M20",
-					Fields: []ptype.Field{
-						{Name: "f30", Number: 30, Cardinality: pref.Optional, Kind: pref.MessageKind, MessageType: ptype.PlaceholderMessage("M.M10.M20.M30")},
-						{Name: "f31", Number: 31, Cardinality: pref.Repeated, Kind: pref.Int32Kind},
-					},
-					Messages: []ptype.Message{{
-						Name: "M30",
-					}},
+		wantMsg: mustMakeMessage(`
+			name: "M"
+			field: [
+				{name:"f10" number:10 label:LABEL_OPTIONAL type:TYPE_GROUP type_name:".M.M10"}
+			]
+			nested_type: [{
+				name: "M10"
+				field: [
+					{name:"f20" number:20 label:LABEL_OPTIONAL type:TYPE_MESSAGE type_name:".M.M10.M20"},
+					{name:"f21" number:21 label:LABEL_OPTIONAL type:TYPE_MESSAGE type_name:".M.M10.M21"}
+				]
+				nested_type: [{
+					name: "M20"
+					field:[
+						{name:"f30" number:30 label:LABEL_OPTIONAL type:TYPE_MESSAGE, type_name:".M.M10.M20.M30"},
+						{name:"f31" number:31 label:LABEL_REPEATED type:TYPE_INT32 options:{packed:true}}
+					]
+					nested_type: [{
+						name: "M30"
+					}]
 				}, {
-					Name: "M21",
-				}},
-			}},
-		},
+					name: "M21"
+				}]
+			}]
+		`),
 	}}
 
-	opts := cmp.Options{
-		cmp.Comparer(func(x, y pref.Descriptor) bool {
-			if x == nil || y == nil {
-				return x == nil && y == nil
-			}
-			return x.FullName() == y.FullName()
-		}),
-		cmpopts.IgnoreFields(ptype.Field{}, "Default"),
-		cmpopts.IgnoreFields(ptype.Field{}, "Options"),
-		cmpopts.IgnoreUnexported(ptype.Message{}, ptype.Field{}),
-	}
 	for _, tt := range tests {
 		t.Run("", func(t *testing.T) {
 			var fields fields
@@ -106,8 +104,8 @@
 				t.Errorf("all Set calls succeeded, want %v error", tt.wantErr)
 			}
 			gotMsg := fields.messageDescriptor("M")
-			if diff := cmp.Diff(tt.wantMsg, gotMsg, opts); diff != "" {
-				t.Errorf("messageDescriptor() mismatch (-want +got):\n%v", diff)
+			if !proto.Equal(gotMsg, tt.wantMsg) {
+				t.Errorf("messageDescriptor() mismatch:\ngot  %v\nwant %v", gotMsg, tt.wantMsg)
 			}
 			if _, err := fields.Descriptor(); err != nil {
 				t.Errorf("Descriptor() = %v, want nil error", err)