protogen: include source comments in generated code

Add initial handling of location paths (arrays of integers identifying
an entity in a .proto source file).

Expose path info in protogen; each descriptor has a Path field containing
its location path.

Format comments in protoc-gen-go. This contains one change from
github.com/golang/protobuf: Package comments are now included before the
package statement (but not attached to it) and use // comment syntax
instead of /* */. e.g.,

Before:

	package test

	/*
	This package contains interesting messages.
	*/

After:

	// This package contains interesting messages.

	package test

Change-Id: Ieee13ae77b3584f7562183100554d3df732348aa
Reviewed-on: https://go-review.googlesource.com/133915
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/protogen/protogen.go b/protogen/protogen.go
index be5e503..967f000 100644
--- a/protogen/protogen.go
+++ b/protogen/protogen.go
@@ -349,7 +349,7 @@
 	f.GeneratedFilenamePrefix = prefix
 
 	for i, mdescs := 0, desc.Messages(); i < mdescs.Len(); i++ {
-		f.Messages = append(f.Messages, newMessage(gen, f, nil, mdescs.Get(i), i))
+		f.Messages = append(f.Messages, newMessage(gen, f, nil, mdescs.Get(i)))
 	}
 	return f, nil
 }
@@ -380,15 +380,23 @@
 
 	GoIdent  GoIdent    // name of the generated Go type
 	Messages []*Message // nested message declarations
+	Path     []int32    // location path of this message
 }
 
-func newMessage(gen *Plugin, f *File, parent *Message, desc protoreflect.MessageDescriptor, index int) *Message {
+func newMessage(gen *Plugin, f *File, parent *Message, desc protoreflect.MessageDescriptor) *Message {
+	var path []int32
+	if parent != nil {
+		path = pathAppend(parent.Path, messageMessageField, int32(desc.Index()))
+	} else {
+		path = []int32{fileMessageField, int32(desc.Index())}
+	}
 	m := &Message{
 		Desc:    desc,
 		GoIdent: newGoIdent(f, desc),
+		Path:    path,
 	}
 	for i, mdescs := 0, desc.Messages(); i < mdescs.Len(); i++ {
-		m.Messages = append(m.Messages, newMessage(gen, f, m, mdescs.Get(i), i))
+		m.Messages = append(m.Messages, newMessage(gen, f, m, mdescs.Get(i)))
 	}
 	return m
 }
@@ -501,3 +509,34 @@
 	pathTypeImport pathType = iota
 	pathTypeSourceRelative
 )
+
+// The SourceCodeInfo message describes the location of elements of a parsed
+// .proto file by way of a "path", which is a sequence of integers that
+// describe the route from a FileDescriptorProto to the relevant submessage.
+// The path alternates between a field number of a repeated field, and an index
+// into that repeated field. The constants below define the field numbers that
+// are used.
+//
+// See descriptor.proto for more information about this.
+const (
+	// field numbers in FileDescriptorProto
+	filePackageField = 2 // package
+	fileMessageField = 4 // message_type
+	fileenumField    = 5 // enum_type
+	// field numbers in DescriptorProto
+	messageFieldField   = 2 // field
+	messageMessageField = 3 // nested_type
+	messageEnumField    = 4 // enum_type
+	messageOneofField   = 8 // oneof_decl
+	// field numbers in EnumDescriptorProto
+	enumValueField = 2 // value
+)
+
+// pathAppend appends elements to a location path.
+// It does not alias the original path.
+func pathAppend(path []int32, a ...int32) []int32 {
+	var n []int32
+	n = append(n, path...)
+	n = append(n, a...)
+	return n
+}