diff --git a/vendor/github.com/jhump/protoreflect/desc/protoprint/doc.go b/vendor/github.com/jhump/protoreflect/desc/protoprint/doc.go
new file mode 100644
index 0000000..b56e8ac
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/protoprint/doc.go
@@ -0,0 +1,7 @@
+// Package protoprint provides a mechanism to generate protobuf source code
+// from descriptors.
+//
+// This can be useful to turn file descriptor sets (produced by protoc) back
+// into proto IDL code. Combined with the protoreflect/builder package, it can
+// also be used to perform code generation of proto source code.
+package protoprint
diff --git a/vendor/github.com/jhump/protoreflect/desc/protoprint/print.go b/vendor/github.com/jhump/protoreflect/desc/protoprint/print.go
new file mode 100644
index 0000000..d8f7f22
--- /dev/null
+++ b/vendor/github.com/jhump/protoreflect/desc/protoprint/print.go
@@ -0,0 +1,2288 @@
+package protoprint
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"math"
+	"os"
+	"path/filepath"
+	"reflect"
+	"sort"
+	"strings"
+
+	"github.com/golang/protobuf/proto"
+	"github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+	"github.com/jhump/protoreflect/desc"
+	"github.com/jhump/protoreflect/desc/internal"
+	"github.com/jhump/protoreflect/dynamic"
+)
+
+// Printer knows how to format file descriptors as proto source code. Its fields
+// provide some control over how the resulting source file is constructed and
+// formatted.
+type Printer struct {
+	// If true, comments are rendered using "/*" style comments. Otherwise, they
+	// are printed using "//" style line comments.
+	PreferMultiLineStyleComments bool
+
+	// If true, elements are sorted into a canonical order.
+	//
+	// The canonical order for elements in a file follows:
+	//  1. Syntax
+	//  2. Package
+	//  3. Imports (sorted lexically)
+	//  4. Options (sorted by name, standard options before custom options)
+	//  5. Messages (sorted by name)
+	//  6. Enums (sorted by name)
+	//  7. Services (sorted by name)
+	//  8. Extensions (grouped by extendee, sorted by extendee+tag)
+	//
+	// The canonical order of elements in a message follows:
+	//  1. Options (sorted by name, standard options before custom options)
+	//  2. Fields and One-Ofs (sorted by tag; one-ofs interleaved based on the
+	//     minimum tag therein)
+	//  3. Nested Messages (sorted by name)
+	//  4. Nested Enums (sorted by name)
+	//  5. Extension ranges (sorted by starting tag number)
+	//  6. Nested Extensions (grouped by extendee, sorted by extendee+tag)
+	//  7. Reserved ranges (sorted by starting tag number)
+	//  8. Reserved names (sorted lexically)
+	//
+	// Methods are sorted within a service by name and appear after any service
+	// options (which are sorted by name, standard options before custom ones).
+	// Enum values are sorted within an enum, first by numeric value then by
+	// name, and also appear after any enum options.
+	//
+	// Options for fields, enum values, and extension ranges are sorted by name,
+	// standard options before custom ones.
+	SortElements bool
+
+	// The indentation used. Any characters other than spaces or tabs will be
+	// replaced with spaces. If unset/empty, two spaces will be used.
+	Indent string
+
+	// If true, detached comments (between elements) will be ignored.
+	//
+	// Deprecated: Use OmitComments bitmask instead.
+	OmitDetachedComments bool
+
+	// A bitmask of comment types to omit. If unset, all comments will be
+	// included. Use CommentsAll to not print any comments.
+	OmitComments CommentType
+
+	// If true, trailing comments that typically appear on the same line as an
+	// element (option, field, enum value, method) will be printed on a separate
+	// line instead.
+	//
+	// So, with this set, you'll get output like so:
+	//
+	//    // leading comment for field
+	//    repeated string names = 1;
+	//    // trailing comment
+	//
+	// If left false, the printer will try to emit trailing comments on the same
+	// line instead:
+	//
+	//    // leading comment for field
+	//    repeated string names = 1; // trailing comment
+	//
+	// If the trailing comment has more than one line, it will automatically be
+	// forced to the next line. Also, elements that end with "}" instead of ";"
+	// will have trailing comments rendered on the subsequent line.
+	TrailingCommentsOnSeparateLine bool
+
+	// If true, the printed output will eschew any blank lines, which otherwise
+	// appear between descriptor elements and comment blocks. Note that this if
+	// detached comments are being printed, this will cause them to be merged
+	// into the subsequent leading comments. Similarly, any element trailing
+	// comments will be merged into the subsequent leading comments.
+	Compact bool
+
+	// If true, all references to messages, extensions, and enums (such as in
+	// options, field types, and method request and response types) will be
+	// fully-qualified. When left unset, the referenced elements will contain
+	// only as much qualifier as is required.
+	//
+	// For example, if a message is in the same package as the reference, the
+	// simple name can be used. If a message shares some context with the
+	// reference, only the unshared context needs to be included. For example:
+	//
+	//  message Foo {
+	//    message Bar {
+	//      enum Baz {
+	//        ZERO = 0;
+	//        ONE = 1;
+	//      }
+	//    }
+	//
+	//    // This field shares some context as the enum it references: they are
+	//    // both inside of the namespace Foo:
+	//    //    field is "Foo.my_baz"
+	//    //     enum is "Foo.Bar.Baz"
+	//    // So we only need to qualify the reference with the context that they
+	//    // do NOT have in common:
+	//    Bar.Baz my_baz = 1;
+	//  }
+	//
+	// When printing fully-qualified names, they will be preceded by a dot, to
+	// avoid any ambiguity that they might be relative vs. fully-qualified.
+	ForceFullyQualifiedNames bool
+}
+
+// CommentType is a kind of comments in a proto source file. This can be used
+// as a bitmask.
+type CommentType int
+
+const (
+	// CommentsDetached refers to comments that are not "attached" to any
+	// source element. They are attributed to the subsequent element in the
+	// file as "detached" comments.
+	CommentsDetached CommentType = 1 << iota
+	// CommentsTrailing refers to a comment block immediately following an
+	// element in the source file. If another element immediately follows
+	// the trailing comment, it is instead considered a leading comment for
+	// that subsequent element.
+	CommentsTrailing
+	// CommentsLeading refers to a comment block immediately preceding an
+	// element in the source file. For high-level elements (those that have
+	// their own descriptor), these are used as doc comments for that element.
+	CommentsLeading
+	// CommentsTokens refers to any comments (leading, trailing, or detached)
+	// on low-level elements in the file. "High-level" elements have their own
+	// descriptors, e.g. messages, enums, fields, services, and methods. But
+	// comments can appear anywhere (such as around identifiers and keywords,
+	// sprinkled inside the declarations of a high-level element). This class
+	// of comments are for those extra comments sprinkled into the file.
+	CommentsTokens
+
+	// CommentsNonDoc refers to comments that are *not* doc comments. This is a
+	// bitwise union of everything other than CommentsLeading. If you configure
+	// a printer to omit this, only doc comments on descriptor elements will be
+	// included in the printed output.
+	CommentsNonDoc = CommentsDetached | CommentsTrailing | CommentsTokens
+	// CommentsAll indicates all kinds of comments. If you configure a printer
+	// to omit this, no comments will appear in the printed output, even if the
+	// input descriptors had source info and comments.
+	CommentsAll = -1
+)
+
+// PrintProtoFiles prints all of the given file descriptors. The given open
+// function is given a file name and is responsible for creating the outputs and
+// returning the corresponding writer.
+func (p *Printer) PrintProtoFiles(fds []*desc.FileDescriptor, open func(name string) (io.WriteCloser, error)) error {
+	for _, fd := range fds {
+		w, err := open(fd.GetName())
+		if err != nil {
+			return fmt.Errorf("failed to open %s: %v", fd.GetName(), err)
+		}
+		err = func() error {
+			defer w.Close()
+			return p.PrintProtoFile(fd, w)
+		}()
+		if err != nil {
+			return fmt.Errorf("failed to write %s: %v", fd.GetName(), err)
+		}
+	}
+	return nil
+}
+
+// PrintProtosToFileSystem prints all of the given file descriptors to files in
+// the given directory. If file names in the given descriptors include path
+// information, they will be relative to the given root.
+func (p *Printer) PrintProtosToFileSystem(fds []*desc.FileDescriptor, rootDir string) error {
+	return p.PrintProtoFiles(fds, func(name string) (io.WriteCloser, error) {
+		fullPath := filepath.Join(rootDir, name)
+		dir := filepath.Dir(fullPath)
+		if err := os.MkdirAll(dir, os.ModePerm); err != nil {
+			return nil, err
+		}
+		return os.OpenFile(fullPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
+	})
+}
+
+// pkg represents a package name
+type pkg string
+
+// imp represents an imported file name
+type imp string
+
+// ident represents an identifier
+type ident string
+
+// option represents a resolved descriptor option
+type option struct {
+	name string
+	val  interface{}
+}
+
+// reservedRange represents a reserved range from a message or enum
+type reservedRange struct {
+	start, end int32
+}
+
+// PrintProtoFile prints the given single file descriptor to the given writer.
+func (p *Printer) PrintProtoFile(fd *desc.FileDescriptor, out io.Writer) error {
+	return p.printProto(fd, out)
+}
+
+// PrintProto prints the given descriptor and returns the resulting string. This
+// can be used to print proto files, but it can also be used to get the proto
+// "source form" for any kind of descriptor, which can be a more user-friendly
+// way to present descriptors that are intended for human consumption.
+func (p *Printer) PrintProtoToString(dsc desc.Descriptor) (string, error) {
+	var buf bytes.Buffer
+	if err := p.printProto(dsc, &buf); err != nil {
+		return "", err
+	}
+	return buf.String(), nil
+}
+
+func (p *Printer) printProto(dsc desc.Descriptor, out io.Writer) error {
+	w := newWriter(out)
+
+	if p.Indent == "" {
+		// default indent to two spaces
+		p.Indent = "  "
+	} else {
+		// indent must be all spaces or tabs, so convert other chars to spaces
+		ind := make([]rune, 0, len(p.Indent))
+		for _, r := range p.Indent {
+			if r == '\t' {
+				ind = append(ind, r)
+			} else {
+				ind = append(ind, ' ')
+			}
+		}
+		p.Indent = string(ind)
+	}
+	if p.OmitDetachedComments {
+		p.OmitComments |= CommentsDetached
+	}
+
+	er := dynamic.ExtensionRegistry{}
+	er.AddExtensionsFromFileRecursively(dsc.GetFile())
+	mf := dynamic.NewMessageFactoryWithExtensionRegistry(&er)
+	fdp := dsc.GetFile().AsFileDescriptorProto()
+	sourceInfo := internal.CreateSourceInfoMap(fdp)
+	extendOptionLocations(sourceInfo)
+
+	path := findElement(dsc)
+	switch d := dsc.(type) {
+	case *desc.FileDescriptor:
+		p.printFile(d, mf, w, sourceInfo)
+	case *desc.MessageDescriptor:
+		p.printMessage(d, mf, w, sourceInfo, path, 0)
+	case *desc.FieldDescriptor:
+		var scope string
+		if md, ok := d.GetParent().(*desc.MessageDescriptor); ok {
+			scope = md.GetFullyQualifiedName()
+		} else {
+			scope = d.GetFile().GetPackage()
+		}
+		if d.IsExtension() {
+			fmt.Fprint(w, "extend ")
+			extNameSi := sourceInfo.Get(append(path, internal.Field_extendeeTag))
+			p.printElementString(extNameSi, w, 0, p.qualifyName(d.GetFile().GetPackage(), scope, d.GetOwner().GetFullyQualifiedName()))
+			fmt.Fprintln(w, "{")
+
+			p.printField(d, mf, w, sourceInfo, path, scope, 1)
+
+			fmt.Fprintln(w, "}")
+		} else {
+			p.printField(d, mf, w, sourceInfo, path, scope, 0)
+		}
+	case *desc.OneOfDescriptor:
+		md := d.GetOwner()
+		elements := elementAddrs{dsc: md}
+		for i := range md.GetFields() {
+			elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Message_fieldsTag, elementIndex: i})
+		}
+		p.printOneOf(d, elements, 0, mf, w, sourceInfo, path[:len(path)-1], 0, path[len(path)-1])
+	case *desc.EnumDescriptor:
+		p.printEnum(d, mf, w, sourceInfo, path, 0)
+	case *desc.EnumValueDescriptor:
+		p.printEnumValue(d, mf, w, sourceInfo, path, 0)
+	case *desc.ServiceDescriptor:
+		p.printService(d, mf, w, sourceInfo, path, 0)
+	case *desc.MethodDescriptor:
+		p.printMethod(d, mf, w, sourceInfo, path, 0)
+	}
+
+	return w.err
+}
+
+func findElement(dsc desc.Descriptor) []int32 {
+	if dsc.GetParent() == nil {
+		return nil
+	}
+	path := findElement(dsc.GetParent())
+	switch d := dsc.(type) {
+	case *desc.MessageDescriptor:
+		if pm, ok := d.GetParent().(*desc.MessageDescriptor); ok {
+			return append(path, internal.Message_nestedMessagesTag, getMessageIndex(d, pm.GetNestedMessageTypes()))
+		}
+		return append(path, internal.File_messagesTag, getMessageIndex(d, d.GetFile().GetMessageTypes()))
+
+	case *desc.FieldDescriptor:
+		if d.IsExtension() {
+			if pm, ok := d.GetParent().(*desc.MessageDescriptor); ok {
+				return append(path, internal.Message_extensionsTag, getFieldIndex(d, pm.GetNestedExtensions()))
+			}
+			return append(path, internal.File_extensionsTag, getFieldIndex(d, d.GetFile().GetExtensions()))
+		}
+		return append(path, internal.Message_fieldsTag, getFieldIndex(d, d.GetOwner().GetFields()))
+
+	case *desc.OneOfDescriptor:
+		return append(path, internal.Message_oneOfsTag, getOneOfIndex(d, d.GetOwner().GetOneOfs()))
+
+	case *desc.EnumDescriptor:
+		if pm, ok := d.GetParent().(*desc.MessageDescriptor); ok {
+			return append(path, internal.Message_enumsTag, getEnumIndex(d, pm.GetNestedEnumTypes()))
+		}
+		return append(path, internal.File_enumsTag, getEnumIndex(d, d.GetFile().GetEnumTypes()))
+
+	case *desc.EnumValueDescriptor:
+		return append(path, internal.Enum_valuesTag, getEnumValueIndex(d, d.GetEnum().GetValues()))
+
+	case *desc.ServiceDescriptor:
+		return append(path, internal.File_servicesTag, getServiceIndex(d, d.GetFile().GetServices()))
+
+	case *desc.MethodDescriptor:
+		return append(path, internal.Service_methodsTag, getMethodIndex(d, d.GetService().GetMethods()))
+
+	default:
+		panic(fmt.Sprintf("unexpected descriptor type: %T", dsc))
+	}
+}
+
+func getMessageIndex(md *desc.MessageDescriptor, list []*desc.MessageDescriptor) int32 {
+	for i := range list {
+		if md == list[i] {
+			return int32(i)
+		}
+	}
+	panic(fmt.Sprintf("unable to determine index of message %s", md.GetFullyQualifiedName()))
+}
+
+func getFieldIndex(fd *desc.FieldDescriptor, list []*desc.FieldDescriptor) int32 {
+	for i := range list {
+		if fd == list[i] {
+			return int32(i)
+		}
+	}
+	panic(fmt.Sprintf("unable to determine index of field %s", fd.GetFullyQualifiedName()))
+}
+
+func getOneOfIndex(ood *desc.OneOfDescriptor, list []*desc.OneOfDescriptor) int32 {
+	for i := range list {
+		if ood == list[i] {
+			return int32(i)
+		}
+	}
+	panic(fmt.Sprintf("unable to determine index of oneof %s", ood.GetFullyQualifiedName()))
+}
+
+func getEnumIndex(ed *desc.EnumDescriptor, list []*desc.EnumDescriptor) int32 {
+	for i := range list {
+		if ed == list[i] {
+			return int32(i)
+		}
+	}
+	panic(fmt.Sprintf("unable to determine index of enum %s", ed.GetFullyQualifiedName()))
+}
+
+func getEnumValueIndex(evd *desc.EnumValueDescriptor, list []*desc.EnumValueDescriptor) int32 {
+	for i := range list {
+		if evd == list[i] {
+			return int32(i)
+		}
+	}
+	panic(fmt.Sprintf("unable to determine index of enum value %s", evd.GetFullyQualifiedName()))
+}
+
+func getServiceIndex(sd *desc.ServiceDescriptor, list []*desc.ServiceDescriptor) int32 {
+	for i := range list {
+		if sd == list[i] {
+			return int32(i)
+		}
+	}
+	panic(fmt.Sprintf("unable to determine index of service %s", sd.GetFullyQualifiedName()))
+}
+
+func getMethodIndex(mtd *desc.MethodDescriptor, list []*desc.MethodDescriptor) int32 {
+	for i := range list {
+		if mtd == list[i] {
+			return int32(i)
+		}
+	}
+	panic(fmt.Sprintf("unable to determine index of method %s", mtd.GetFullyQualifiedName()))
+}
+
+func (p *Printer) newLine(w io.Writer) {
+	if !p.Compact {
+		fmt.Fprintln(w)
+	}
+}
+
+func (p *Printer) printFile(fd *desc.FileDescriptor, mf *dynamic.MessageFactory, w *writer, sourceInfo internal.SourceInfoMap) {
+	opts, err := p.extractOptions(fd, fd.GetOptions(), mf)
+	if err != nil {
+		return
+	}
+
+	fdp := fd.AsFileDescriptorProto()
+	path := make([]int32, 1)
+
+	path[0] = internal.File_packageTag
+	sourceInfo.PutIfAbsent(append(path, 0), sourceInfo.Get(path))
+
+	path[0] = internal.File_syntaxTag
+	si := sourceInfo.Get(path)
+	p.printElement(false, si, w, 0, func(w *writer) {
+		syn := fdp.GetSyntax()
+		if syn == "" {
+			syn = "proto2"
+		}
+		fmt.Fprintf(w, "syntax = %q;", syn)
+	})
+	p.newLine(w)
+
+	elements := elementAddrs{dsc: fd, opts: opts}
+	if fdp.Package != nil {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.File_packageTag, elementIndex: 0, order: -3})
+	}
+	for i := range fd.AsFileDescriptorProto().GetDependency() {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.File_dependencyTag, elementIndex: i, order: -2})
+	}
+	elements.addrs = append(elements.addrs, optionsAsElementAddrs(internal.File_optionsTag, -1, opts)...)
+	for i := range fd.GetMessageTypes() {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.File_messagesTag, elementIndex: i})
+	}
+	for i := range fd.GetEnumTypes() {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.File_enumsTag, elementIndex: i})
+	}
+	for i := range fd.GetServices() {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.File_servicesTag, elementIndex: i})
+	}
+	for i := range fd.GetExtensions() {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.File_extensionsTag, elementIndex: i})
+	}
+
+	p.sort(elements, sourceInfo, nil)
+
+	pkgName := fd.GetPackage()
+
+	var ext *desc.FieldDescriptor
+	for i, el := range elements.addrs {
+		d := elements.at(el)
+		path = []int32{el.elementType, int32(el.elementIndex)}
+		if el.elementType == internal.File_extensionsTag {
+			fld := d.(*desc.FieldDescriptor)
+			if ext == nil || ext.GetOwner() != fld.GetOwner() {
+				// need to open a new extend block
+				if ext != nil {
+					// close preceding extend block
+					fmt.Fprintln(w, "}")
+				}
+				if i > 0 {
+					p.newLine(w)
+				}
+
+				ext = fld
+				fmt.Fprint(w, "extend ")
+				extNameSi := sourceInfo.Get(append(path, internal.Field_extendeeTag))
+				p.printElementString(extNameSi, w, 0, p.qualifyName(pkgName, pkgName, fld.GetOwner().GetFullyQualifiedName()))
+				fmt.Fprintln(w, "{")
+			} else {
+				p.newLine(w)
+			}
+			p.printField(fld, mf, w, sourceInfo, path, pkgName, 1)
+		} else {
+			if ext != nil {
+				// close preceding extend block
+				fmt.Fprintln(w, "}")
+				ext = nil
+			}
+
+			if i > 0 {
+				p.newLine(w)
+			}
+
+			switch d := d.(type) {
+			case pkg:
+				si := sourceInfo.Get(path)
+				p.printElement(false, si, w, 0, func(w *writer) {
+					fmt.Fprintf(w, "package %s;", d)
+				})
+			case imp:
+				si := sourceInfo.Get(path)
+				p.printElement(false, si, w, 0, func(w *writer) {
+					fmt.Fprintf(w, "import %q;", d)
+				})
+			case []option:
+				p.printOptionsLong(d, w, sourceInfo, path, 0)
+			case *desc.MessageDescriptor:
+				p.printMessage(d, mf, w, sourceInfo, path, 0)
+			case *desc.EnumDescriptor:
+				p.printEnum(d, mf, w, sourceInfo, path, 0)
+			case *desc.ServiceDescriptor:
+				p.printService(d, mf, w, sourceInfo, path, 0)
+			}
+		}
+	}
+
+	if ext != nil {
+		// close trailing extend block
+		fmt.Fprintln(w, "}")
+	}
+}
+
+func (p *Printer) sort(elements elementAddrs, sourceInfo internal.SourceInfoMap, path []int32) {
+	if p.SortElements {
+		// canonical sorted order
+		sort.Stable(elements)
+	} else {
+		// use source order (per location information in SourceCodeInfo); or
+		// if that isn't present use declaration order, but grouped by type
+		sort.Stable(elementSrcOrder{
+			elementAddrs: elements,
+			sourceInfo:   sourceInfo,
+			prefix:       path,
+		})
+	}
+}
+
+func (p *Printer) qualifyName(pkg, scope string, fqn string) string {
+	if p.ForceFullyQualifiedNames {
+		// forcing fully-qualified names; make sure to include preceding dot
+		if fqn[0] == '.' {
+			return fqn
+		}
+		return fmt.Sprintf(".%s", fqn)
+	}
+
+	// compute relative name (so no leading dot)
+	if fqn[0] == '.' {
+		fqn = fqn[1:]
+	}
+	if len(scope) > 0 && scope[len(scope)-1] != '.' {
+		scope = scope + "."
+	}
+	for scope != "" {
+		if strings.HasPrefix(fqn, scope) {
+			return fqn[len(scope):]
+		}
+		if scope == pkg+"." {
+			break
+		}
+		pos := strings.LastIndex(scope[:len(scope)-1], ".")
+		scope = scope[:pos+1]
+	}
+	return fqn
+}
+
+func (p *Printer) typeString(fld *desc.FieldDescriptor, scope string) string {
+	if fld.IsMap() {
+		return fmt.Sprintf("map<%s, %s>", p.typeString(fld.GetMapKeyType(), scope), p.typeString(fld.GetMapValueType(), scope))
+	}
+	switch fld.GetType() {
+	case descriptor.FieldDescriptorProto_TYPE_INT32:
+		return "int32"
+	case descriptor.FieldDescriptorProto_TYPE_INT64:
+		return "int64"
+	case descriptor.FieldDescriptorProto_TYPE_UINT32:
+		return "uint32"
+	case descriptor.FieldDescriptorProto_TYPE_UINT64:
+		return "uint64"
+	case descriptor.FieldDescriptorProto_TYPE_SINT32:
+		return "sint32"
+	case descriptor.FieldDescriptorProto_TYPE_SINT64:
+		return "sint64"
+	case descriptor.FieldDescriptorProto_TYPE_FIXED32:
+		return "fixed32"
+	case descriptor.FieldDescriptorProto_TYPE_FIXED64:
+		return "fixed64"
+	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
+		return "sfixed32"
+	case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
+		return "sfixed64"
+	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
+		return "float"
+	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
+		return "double"
+	case descriptor.FieldDescriptorProto_TYPE_BOOL:
+		return "bool"
+	case descriptor.FieldDescriptorProto_TYPE_STRING:
+		return "string"
+	case descriptor.FieldDescriptorProto_TYPE_BYTES:
+		return "bytes"
+	case descriptor.FieldDescriptorProto_TYPE_ENUM:
+		return p.qualifyName(fld.GetFile().GetPackage(), scope, fld.GetEnumType().GetFullyQualifiedName())
+	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
+		return p.qualifyName(fld.GetFile().GetPackage(), scope, fld.GetMessageType().GetFullyQualifiedName())
+	case descriptor.FieldDescriptorProto_TYPE_GROUP:
+		return fld.GetMessageType().GetName()
+	}
+	panic(fmt.Sprintf("invalid type: %v", fld.GetType()))
+}
+
+func (p *Printer) printMessage(md *desc.MessageDescriptor, mf *dynamic.MessageFactory, w *writer, sourceInfo internal.SourceInfoMap, path []int32, indent int) {
+	si := sourceInfo.Get(path)
+	p.printElement(true, si, w, indent, func(w *writer) {
+		p.indent(w, indent)
+
+		fmt.Fprint(w, "message ")
+		nameSi := sourceInfo.Get(append(path, internal.Message_nameTag))
+		p.printElementString(nameSi, w, indent, md.GetName())
+		fmt.Fprintln(w, "{")
+
+		p.printMessageBody(md, mf, w, sourceInfo, path, indent+1)
+		p.indent(w, indent)
+		fmt.Fprintln(w, "}")
+	})
+}
+
+func (p *Printer) printMessageBody(md *desc.MessageDescriptor, mf *dynamic.MessageFactory, w *writer, sourceInfo internal.SourceInfoMap, path []int32, indent int) {
+	opts, err := p.extractOptions(md, md.GetOptions(), mf)
+	if err != nil {
+		if w.err == nil {
+			w.err = err
+		}
+		return
+	}
+
+	skip := map[interface{}]bool{}
+
+	elements := elementAddrs{dsc: md, opts: opts}
+	elements.addrs = append(elements.addrs, optionsAsElementAddrs(internal.Message_optionsTag, -1, opts)...)
+	for i := range md.AsDescriptorProto().GetReservedRange() {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Message_reservedRangeTag, elementIndex: i})
+	}
+	for i := range md.AsDescriptorProto().GetReservedName() {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Message_reservedNameTag, elementIndex: i})
+	}
+	for i := range md.AsDescriptorProto().GetExtensionRange() {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Message_extensionRangeTag, elementIndex: i})
+	}
+	for i, fld := range md.GetFields() {
+		if fld.IsMap() || fld.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP {
+			// we don't emit nested messages for map types or groups since
+			// they get special treatment
+			skip[fld.GetMessageType()] = true
+		}
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Message_fieldsTag, elementIndex: i})
+	}
+	for i := range md.GetNestedMessageTypes() {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Message_nestedMessagesTag, elementIndex: i})
+	}
+	for i := range md.GetNestedEnumTypes() {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Message_enumsTag, elementIndex: i})
+	}
+	for i := range md.GetNestedExtensions() {
+		elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Message_extensionsTag, elementIndex: i})
+	}
+
+	p.sort(elements, sourceInfo, path)
+
+	pkg := md.GetFile().GetPackage()
+	scope := md.GetFullyQualifiedName()
+
+	var ext *desc.FieldDescriptor
+	for i, el := range elements.addrs {
+		d := elements.at(el)
+		// skip[d] will panic if d is a slice (which it could be for []option),
+		// so just ignore it since we don't try to skip options
+		if reflect.TypeOf(d).Kind() != reflect.Slice && skip[d] {
+			// skip this element
+			continue
+		}
+
+		childPath := append(path, el.elementType, int32(el.elementIndex))
+		if el.elementType == internal.Message_extensionsTag {
+			// extension
+			fld := d.(*desc.FieldDescriptor)
+			if ext == nil || ext.GetOwner() != fld.GetOwner() {
+				// need to open a new extend block
+				if ext != nil {
+					// close preceding extend block
+					p.indent(w, indent)
+					fmt.Fprintln(w, "}")
+				}
+				if i > 0 {
+					p.newLine(w)
+				}
+
+				ext = fld
+				p.indent(w, indent)
+				fmt.Fprint(w, "extend ")
+				extNameSi := sourceInfo.Get(append(childPath, internal.Field_extendeeTag))
+				p.printElementString(extNameSi, w, indent, p.qualifyName(pkg, scope, fld.GetOwner().GetFullyQualifiedName()))
+				fmt.Fprintln(w, "{")
+			} else {
+				p.newLine(w)
+			}
+			p.printField(fld, mf, w, sourceInfo, childPath, scope, indent+1)
+		} else {
+			if ext != nil {
+				// close preceding extend block
+				p.indent(w, indent)
+				fmt.Fprintln(w, "}")
+				ext = nil
+			}
+
+			if i > 0 {
+				p.newLine(w)
+			}
+
+			switch d := d.(type) {
+			case []option:
+				p.printOptionsLong(d, w, sourceInfo, childPath, indent)
+			case *desc.FieldDescriptor:
+				ood := d.GetOneOf()
+				if ood == nil {
+					p.printField(d, mf, w, sourceInfo, childPath, scope, indent)
+				} else if !skip[ood] {
+					// print the one-of, including all of its fields
+					p.printOneOf(ood, elements, i, mf, w, sourceInfo, path, indent, d.AsFieldDescriptorProto().GetOneofIndex())
+					skip[ood] = true
+				}
+			case *desc.MessageDescriptor:
+				p.printMessage(d, mf, w, sourceInfo, childPath, indent)
+			case *desc.EnumDescriptor:
+				p.printEnum(d, mf, w, sourceInfo, childPath, indent)
+			case *descriptor.DescriptorProto_ExtensionRange:
+				// collapse ranges into a single "extensions" block
+				ranges := []*descriptor.DescriptorProto_ExtensionRange{d}
+				addrs := []elementAddr{el}
+				for idx := i + 1; idx < len(elements.addrs); idx++ {
+					elnext := elements.addrs[idx]
+					if elnext.elementType != el.elementType {
+						break
+					}
+					extr := elements.at(elnext).(*descriptor.DescriptorProto_ExtensionRange)
+					if !areEqual(d.Options, extr.Options, mf) {
+						break
+					}
+					ranges = append(ranges, extr)
+					addrs = append(addrs, elnext)
+					skip[extr] = true
+				}
+				p.printExtensionRanges(md, ranges, addrs, mf, w, sourceInfo, path, indent)
+			case reservedRange:
+				// collapse reserved ranges into a single "reserved" block
+				ranges := []reservedRange{d}
+				addrs := []elementAddr{el}
+				for idx := i + 1; idx < len(elements.addrs); idx++ {
+					elnext := elements.addrs[idx]
+					if elnext.elementType != el.elementType {
+						break
+					}
+					rr := elements.at(elnext).(reservedRange)
+					ranges = append(ranges, rr)
+					addrs = append(addrs, elnext)
+					skip[rr] = true
+				}
+				p.printReservedRanges(ranges, false, addrs, w, sourceInfo, path, indent)
+			case string: // reserved name
+				// collapse reserved names into a single "reserved" block
+				names := []string{d}
+				addrs := []elementAddr{el}
+				for idx := i + 1; idx < len(elements.addrs); idx++ {
+					elnext := elements.addrs[idx]
+					if elnext.elementType != el.elementType {
+						break
+					}
+					rn := elements.at(elnext).(string)
+					names = append(names, rn)
+					addrs = append(addrs, elnext)
+					skip[rn] = true
+				}
+				p.printReservedNames(names, addrs, w, sourceInfo, path, indent)
+			}
+		}
+	}
+
+	if ext != nil {
+		// close trailing extend block
+		p.indent(w, indent)
+		fmt.Fprintln(w, "}")
+	}
+}
+
+func areEqual(a, b proto.Message, mf *dynamic.MessageFactory) bool {
+	// proto.Equal doesn't handle unknown extensions very well :(
+	// so we convert to a dynamic message (which should know about all extensions via
+	// extension registry) and then compare
+	return dynamic.MessagesEqual(asDynamicIfPossible(a, mf), asDynamicIfPossible(b, mf))
+}
+
+func asDynamicIfPossible(msg proto.Message, mf *dynamic.MessageFactory) proto.Message {
+	if dm, ok := msg.(*dynamic.Message); ok {
+		return dm
+	} else {
+		md, err := desc.LoadMessageDescriptorForMessage(msg)
+		if err == nil {
+			dm := mf.NewDynamicMessage(md)
+			if dm.ConvertFrom(msg) == nil {
+				return dm
+			}
+		}
+	}
+	return msg
+}
+
+func (p *Printer) printField(fld *desc.FieldDescriptor, mf *dynamic.MessageFactory, w *writer, sourceInfo internal.SourceInfoMap, path []int32, scope string, indent int) {
+	var groupPath []int32
+	var si *descriptor.SourceCodeInfo_Location
+	if isGroup(fld) {
+		// compute path to group message type
+		groupPath = make([]int32, len(path)-2)
+		copy(groupPath, path)
+		var groupMsgIndex int32
+		md := fld.GetParent().(*desc.MessageDescriptor)
+		for i, nmd := range md.GetNestedMessageTypes() {
+			if nmd == fld.GetMessageType() {
+				// found it
+				groupMsgIndex = int32(i)
+				break
+			}
+		}
+		groupPath = append(groupPath, internal.Message_nestedMessagesTag, groupMsgIndex)
+
+		// the group message is where the field's comments and position are stored
+		si = sourceInfo.Get(groupPath)
+	} else {
+		si = sourceInfo.Get(path)
+	}
+
+	p.printElement(true, si, w, indent, func(w *writer) {
+		p.indent(w, indent)
+		if shouldEmitLabel(fld) {
+			locSi := sourceInfo.Get(append(path, internal.Field_labelTag))
+			p.printElementString(locSi, w, indent, labelString(fld.GetLabel()))
+		}
+
+		if isGroup(fld) {
+			fmt.Fprint(w, "group ")
+
+			typeSi := sourceInfo.Get(append(path, internal.Field_typeTag))
+			p.printElementString(typeSi, w, indent, p.typeString(fld, scope))
+			fmt.Fprint(w, "= ")
+
+			numSi := sourceInfo.Get(append(path, internal.Field_numberTag))
+			p.printElementString(numSi, w, indent, fmt.Sprintf("%d", fld.GetNumber()))
+
+			fmt.Fprintln(w, "{")
+			p.printMessageBody(fld.GetMessageType(), mf, w, sourceInfo, groupPath, indent+1)
+
+			p.indent(w, indent)
+			fmt.Fprintln(w, "}")
+		} else {
+			typeSi := sourceInfo.Get(append(path, internal.Field_typeTag))
+			p.printElementString(typeSi, w, indent, p.typeString(fld, scope))
+
+			nameSi := sourceInfo.Get(append(path, internal.Field_nameTag))
+			p.printElementString(nameSi, w, indent, fld.GetName())
+			fmt.Fprint(w, "= ")
+
+			numSi := sourceInfo.Get(append(path, internal.Field_numberTag))
+			p.printElementString(numSi, w, indent, fmt.Sprintf("%d", fld.GetNumber()))
+
+			opts, err := p.extractOptions(fld, fld.GetOptions(), mf)
+			if err != nil {
+				if w.err == nil {
+					w.err = err
+				}
+				return
+			}
+
+			// we use negative values for "extras" keys so they can't collide
+			// with legit option tags
+
+			if !fld.GetFile().IsProto3() && fld.AsFieldDescriptorProto().DefaultValue != nil {
+				defVal := fld.GetDefaultValue()
+				if fld.GetEnumType() != nil {
+					defVal = fld.GetEnumType().FindValueByNumber(defVal.(int32))
+				}
+				opts[-internal.Field_defaultTag] = []option{{name: "default", val: defVal}}
+			}
+
+			jsn := fld.AsFieldDescriptorProto().GetJsonName()
+			if jsn != "" && jsn != internal.JsonName(fld.GetName()) {
+				opts[-internal.Field_jsonNameTag] = []option{{name: "json_name", val: jsn}}
+			}
+
+			elements := elementAddrs{dsc: fld, opts: opts}
+			elements.addrs = optionsAsElementAddrs(internal.Field_optionsTag, 0, opts)
+			p.sort(elements, sourceInfo, path)
+			p.printOptionElementsShort(elements, w, sourceInfo, path, indent)
+
+			fmt.Fprint(w, ";")
+		}
+	})
+}
+
+func shouldEmitLabel(fld *desc.FieldDescriptor) bool {
+	return !fld.IsMap() && fld.GetOneOf() == nil && (fld.GetLabel() != descriptor.FieldDescriptorProto_LABEL_OPTIONAL || !fld.GetFile().IsProto3())
+}
+
+func labelString(lbl descriptor.FieldDescriptorProto_Label) string {
+	switch lbl {
+	case descriptor.FieldDescriptorProto_LABEL_OPTIONAL:
+		return "optional"
+	case descriptor.FieldDescriptorProto_LABEL_REQUIRED:
+		return "required"
+	case descriptor.FieldDescriptorProto_LABEL_REPEATED:
+		return "repeated"
+	}
+	panic(fmt.Sprintf("invalid label: %v", lbl))
+}
+
+func isGroup(fld *desc.FieldDescriptor) bool {
+	return fld.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP
+}
+
+func (p *Printer) printOneOf(ood *desc.OneOfDescriptor, parentElements elementAddrs, startFieldIndex int, mf *dynamic.MessageFactory, w *writer, sourceInfo internal.SourceInfoMap, parentPath []int32, indent int, ooIndex int32) {
+	oopath := append(parentPath, internal.Message_oneOfsTag, ooIndex)
+	oosi := sourceInfo.Get(oopath)
+	p.printElement(true, oosi, w, indent, func(w *writer) {
+		p.indent(w, indent)
+		fmt.Fprint(w, "oneof ")
+		extNameSi := sourceInfo.Get(append(oopath, internal.OneOf_nameTag))
+		p.printElementString(extNameSi, w, indent, ood.GetName())
+		fmt.Fprintln(w, "{")
+
+		indent++
+		opts, err := p.extractOptions(ood, ood.GetOptions(), mf)
+		if err != nil {
+			if w.err == nil {
+				w.err = err
+			}
+			return
+		}
+
+		elements := elementAddrs{dsc: ood, opts: opts}
+		elements.addrs = append(elements.addrs, optionsAsElementAddrs(internal.OneOf_optionsTag, -1, opts)...)
+
+		count := len(ood.GetChoices())
+		for idx := startFieldIndex; count > 0 && idx < len(parentElements.addrs); idx++ {
+			el := parentElements.addrs[idx]
+			if el.elementType != internal.Message_fieldsTag {
+				continue
+			}
+			if parentElements.at(el).(*desc.FieldDescriptor).GetOneOf() == ood {
+				// negative tag indicates that this element is actually a sibling, not a child
+				elements.addrs = append(elements.addrs, elementAddr{elementType: -internal.Message_fieldsTag, elementIndex: el.elementIndex})
+				count--
+			}
+		}
+
+		p.sort(elements, sourceInfo, oopath)
+
+		scope := ood.GetOwner().GetFullyQualifiedName()
+
+		for i, el := range elements.addrs {
+			if i > 0 {
+				p.newLine(w)
+			}
+
+			switch d := elements.at(el).(type) {
+			case []option:
+				childPath := append(oopath, el.elementType, int32(el.elementIndex))
+				p.printOptionsLong(d, w, sourceInfo, childPath, indent)
+			case *desc.FieldDescriptor:
+				childPath := append(parentPath, -el.elementType, int32(el.elementIndex))
+				p.printField(d, mf, w, sourceInfo, childPath, scope, indent)
+			}
+		}
+
+		p.indent(w, indent-1)
+		fmt.Fprintln(w, "}")
+	})
+}
+
+func (p *Printer) printExtensionRanges(parent *desc.MessageDescriptor, ranges []*descriptor.DescriptorProto_ExtensionRange, addrs []elementAddr, mf *dynamic.MessageFactory, w *writer, sourceInfo internal.SourceInfoMap, parentPath []int32, indent int) {
+	p.indent(w, indent)
+	fmt.Fprint(w, "extensions ")
+
+	var opts *descriptor.ExtensionRangeOptions
+	var elPath []int32
+	first := true
+	for i, extr := range ranges {
+		if first {
+			first = false
+		} else {
+			fmt.Fprint(w, ", ")
+		}
+		opts = extr.Options
+		el := addrs[i]
+		elPath = append(parentPath, el.elementType, int32(el.elementIndex))
+		si := sourceInfo.Get(elPath)
+		p.printElement(true, si, w, inline(indent), func(w *writer) {
+			if extr.GetStart() == extr.GetEnd()-1 {
+				fmt.Fprintf(w, "%d ", extr.GetStart())
+			} else if extr.GetEnd()-1 == internal.MaxTag {
+				fmt.Fprintf(w, "%d to max ", extr.GetStart())
+			} else {
+				fmt.Fprintf(w, "%d to %d ", extr.GetStart(), extr.GetEnd()-1)
+			}
+		})
+	}
+	dsc := extensionRange{owner: parent, extRange: ranges[0]}
+	p.printOptionsShort(dsc, opts, mf, internal.ExtensionRange_optionsTag, w, sourceInfo, elPath, indent)
+
+	fmt.Fprintln(w, ";")
+}
+
+func (p *Printer) printReservedRanges(ranges []reservedRange, isEnum bool, addrs []elementAddr, w *writer, sourceInfo internal.SourceInfoMap, parentPath []int32, indent int) {
+	p.indent(w, indent)
+	fmt.Fprint(w, "reserved ")
+
+	first := true
+	for i, rr := range ranges {
+		if first {
+			first = false
+		} else {
+			fmt.Fprint(w, ", ")
+		}
+		el := addrs[i]
+		si := sourceInfo.Get(append(parentPath, el.elementType, int32(el.elementIndex)))
+		p.printElement(false, si, w, inline(indent), func(w *writer) {
+			if rr.start == rr.end {
+				fmt.Fprintf(w, "%d ", rr.start)
+			} else if (rr.end == internal.MaxTag && !isEnum) ||
+				(rr.end == math.MaxInt32 && isEnum) {
+				fmt.Fprintf(w, "%d to max ", rr.start)
+			} else {
+				fmt.Fprintf(w, "%d to %d ", rr.start, rr.end)
+			}
+		})
+	}
+
+	fmt.Fprintln(w, ";")
+}
+
+func (p *Printer) printReservedNames(names []string, addrs []elementAddr, w *writer, sourceInfo internal.SourceInfoMap, parentPath []int32, indent int) {
+	p.indent(w, indent)
+	fmt.Fprint(w, "reserved ")
+
+	first := true
+	for i, name := range names {
+		if first {
+			first = false
+		} else {
+			fmt.Fprint(w, ", ")
+		}
+		el := addrs[i]
+		si := sourceInfo.Get(append(parentPath, el.elementType, int32(el.elementIndex)))
+		p.printElementString(si, w, indent, quotedString(name))
+	}
+
+	fmt.Fprintln(w, ";")
+}
+
+func (p *Printer) printEnum(ed *desc.EnumDescriptor, mf *dynamic.MessageFactory, w *writer, sourceInfo internal.SourceInfoMap, path []int32, indent int) {
+	si := sourceInfo.Get(path)
+	p.printElement(true, si, w, indent, func(w *writer) {
+		p.indent(w, indent)
+
+		fmt.Fprint(w, "enum ")
+		nameSi := sourceInfo.Get(append(path, internal.Enum_nameTag))
+		p.printElementString(nameSi, w, indent, ed.GetName())
+		fmt.Fprintln(w, "{")
+
+		indent++
+		opts, err := p.extractOptions(ed, ed.GetOptions(), mf)
+		if err != nil {
+			if w.err == nil {
+				w.err = err
+			}
+			return
+		}
+
+		skip := map[interface{}]bool{}
+
+		elements := elementAddrs{dsc: ed, opts: opts}
+		elements.addrs = append(elements.addrs, optionsAsElementAddrs(internal.Enum_optionsTag, -1, opts)...)
+		for i := range ed.GetValues() {
+			elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Enum_valuesTag, elementIndex: i})
+		}
+		for i := range ed.AsEnumDescriptorProto().GetReservedRange() {
+			elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Enum_reservedRangeTag, elementIndex: i})
+		}
+		for i := range ed.AsEnumDescriptorProto().GetReservedName() {
+			elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Enum_reservedNameTag, elementIndex: i})
+		}
+
+		p.sort(elements, sourceInfo, path)
+
+		for i, el := range elements.addrs {
+			d := elements.at(el)
+
+			// skip[d] will panic if d is a slice (which it could be for []option),
+			// so just ignore it since we don't try to skip options
+			if reflect.TypeOf(d).Kind() != reflect.Slice && skip[d] {
+				// skip this element
+				continue
+			}
+
+			if i > 0 {
+				p.newLine(w)
+			}
+
+			childPath := append(path, el.elementType, int32(el.elementIndex))
+
+			switch d := d.(type) {
+			case []option:
+				p.printOptionsLong(d, w, sourceInfo, childPath, indent)
+			case *desc.EnumValueDescriptor:
+				p.printEnumValue(d, mf, w, sourceInfo, childPath, indent)
+			case reservedRange:
+				// collapse reserved ranges into a single "reserved" block
+				ranges := []reservedRange{d}
+				addrs := []elementAddr{el}
+				for idx := i + 1; idx < len(elements.addrs); idx++ {
+					elnext := elements.addrs[idx]
+					if elnext.elementType != el.elementType {
+						break
+					}
+					rr := elements.at(elnext).(reservedRange)
+					ranges = append(ranges, rr)
+					addrs = append(addrs, elnext)
+					skip[rr] = true
+				}
+				p.printReservedRanges(ranges, true, addrs, w, sourceInfo, path, indent)
+			case string: // reserved name
+				// collapse reserved names into a single "reserved" block
+				names := []string{d}
+				addrs := []elementAddr{el}
+				for idx := i + 1; idx < len(elements.addrs); idx++ {
+					elnext := elements.addrs[idx]
+					if elnext.elementType != el.elementType {
+						break
+					}
+					rn := elements.at(elnext).(string)
+					names = append(names, rn)
+					addrs = append(addrs, elnext)
+					skip[rn] = true
+				}
+				p.printReservedNames(names, addrs, w, sourceInfo, path, indent)
+			}
+		}
+
+		p.indent(w, indent-1)
+		fmt.Fprintln(w, "}")
+	})
+}
+
+func (p *Printer) printEnumValue(evd *desc.EnumValueDescriptor, mf *dynamic.MessageFactory, w *writer, sourceInfo internal.SourceInfoMap, path []int32, indent int) {
+	si := sourceInfo.Get(path)
+	p.printElement(true, si, w, indent, func(w *writer) {
+		p.indent(w, indent)
+
+		nameSi := sourceInfo.Get(append(path, internal.EnumVal_nameTag))
+		p.printElementString(nameSi, w, indent, evd.GetName())
+		fmt.Fprint(w, "= ")
+
+		numSi := sourceInfo.Get(append(path, internal.EnumVal_numberTag))
+		p.printElementString(numSi, w, indent, fmt.Sprintf("%d", evd.GetNumber()))
+
+		p.printOptionsShort(evd, evd.GetOptions(), mf, internal.EnumVal_optionsTag, w, sourceInfo, path, indent)
+
+		fmt.Fprint(w, ";")
+	})
+}
+
+func (p *Printer) printService(sd *desc.ServiceDescriptor, mf *dynamic.MessageFactory, w *writer, sourceInfo internal.SourceInfoMap, path []int32, indent int) {
+	si := sourceInfo.Get(path)
+	p.printElement(true, si, w, indent, func(w *writer) {
+		p.indent(w, indent)
+
+		fmt.Fprint(w, "service ")
+		nameSi := sourceInfo.Get(append(path, internal.Service_nameTag))
+		p.printElementString(nameSi, w, indent, sd.GetName())
+		fmt.Fprintln(w, "{")
+
+		indent++
+
+		opts, err := p.extractOptions(sd, sd.GetOptions(), mf)
+		if err != nil {
+			if w.err == nil {
+				w.err = err
+			}
+			return
+		}
+
+		elements := elementAddrs{dsc: sd, opts: opts}
+		elements.addrs = append(elements.addrs, optionsAsElementAddrs(internal.Service_optionsTag, -1, opts)...)
+		for i := range sd.GetMethods() {
+			elements.addrs = append(elements.addrs, elementAddr{elementType: internal.Service_methodsTag, elementIndex: i})
+		}
+
+		p.sort(elements, sourceInfo, path)
+
+		for i, el := range elements.addrs {
+			if i > 0 {
+				p.newLine(w)
+			}
+
+			childPath := append(path, el.elementType, int32(el.elementIndex))
+
+			switch d := elements.at(el).(type) {
+			case []option:
+				p.printOptionsLong(d, w, sourceInfo, childPath, indent)
+			case *desc.MethodDescriptor:
+				p.printMethod(d, mf, w, sourceInfo, childPath, indent)
+			}
+		}
+
+		p.indent(w, indent-1)
+		fmt.Fprintln(w, "}")
+	})
+}
+
+func (p *Printer) printMethod(mtd *desc.MethodDescriptor, mf *dynamic.MessageFactory, w *writer, sourceInfo internal.SourceInfoMap, path []int32, indent int) {
+	si := sourceInfo.Get(path)
+	pkg := mtd.GetFile().GetPackage()
+	p.printElement(true, si, w, indent, func(w *writer) {
+		p.indent(w, indent)
+
+		fmt.Fprint(w, "rpc ")
+		nameSi := sourceInfo.Get(append(path, internal.Method_nameTag))
+		p.printElementString(nameSi, w, indent, mtd.GetName())
+
+		fmt.Fprint(w, "( ")
+		inSi := sourceInfo.Get(append(path, internal.Method_inputTag))
+		inName := p.qualifyName(pkg, pkg, mtd.GetInputType().GetFullyQualifiedName())
+		if mtd.IsClientStreaming() {
+			inName = "stream " + inName
+		}
+		p.printElementString(inSi, w, indent, inName)
+
+		fmt.Fprint(w, ") returns ( ")
+
+		outSi := sourceInfo.Get(append(path, internal.Method_outputTag))
+		outName := p.qualifyName(pkg, pkg, mtd.GetOutputType().GetFullyQualifiedName())
+		if mtd.IsServerStreaming() {
+			outName = "stream " + outName
+		}
+		p.printElementString(outSi, w, indent, outName)
+		fmt.Fprint(w, ") ")
+
+		opts, err := p.extractOptions(mtd, mtd.GetOptions(), mf)
+		if err != nil {
+			if w.err == nil {
+				w.err = err
+			}
+			return
+		}
+
+		if len(opts) > 0 {
+			fmt.Fprintln(w, "{")
+			indent++
+
+			elements := elementAddrs{dsc: mtd, opts: opts}
+			elements.addrs = optionsAsElementAddrs(internal.Method_optionsTag, 0, opts)
+			p.sort(elements, sourceInfo, path)
+			path = append(path, internal.Method_optionsTag)
+
+			for i, addr := range elements.addrs {
+				if i > 0 {
+					p.newLine(w)
+				}
+				o := elements.at(addr).([]option)
+				p.printOptionsLong(o, w, sourceInfo, path, indent)
+			}
+
+			p.indent(w, indent-1)
+			fmt.Fprintln(w, "}")
+		} else {
+			fmt.Fprint(w, ";")
+		}
+	})
+}
+
+func (p *Printer) printOptionsLong(opts []option, w *writer, sourceInfo internal.SourceInfoMap, path []int32, indent int) {
+	p.printOptions(opts, w, indent,
+		func(i int32) *descriptor.SourceCodeInfo_Location {
+			return sourceInfo.Get(append(path, i))
+		},
+		func(w *writer, indent int, opt option) {
+			p.indent(w, indent)
+			fmt.Fprint(w, "option ")
+			p.printOption(opt.name, opt.val, w, indent)
+			fmt.Fprint(w, ";")
+		})
+}
+
+func (p *Printer) printOptionsShort(dsc interface{}, optsMsg proto.Message, mf *dynamic.MessageFactory, optsTag int32, w *writer, sourceInfo internal.SourceInfoMap, path []int32, indent int) {
+	d, ok := dsc.(desc.Descriptor)
+	if !ok {
+		d = dsc.(extensionRange).owner
+	}
+	opts, err := p.extractOptions(d, optsMsg, mf)
+	if err != nil {
+		if w.err == nil {
+			w.err = err
+		}
+		return
+	}
+
+	elements := elementAddrs{dsc: dsc, opts: opts}
+	elements.addrs = optionsAsElementAddrs(optsTag, 0, opts)
+	p.sort(elements, sourceInfo, path)
+	p.printOptionElementsShort(elements, w, sourceInfo, path, indent)
+}
+
+func (p *Printer) printOptionElementsShort(addrs elementAddrs, w *writer, sourceInfo internal.SourceInfoMap, path []int32, indent int) {
+	if len(addrs.addrs) == 0 {
+		return
+	}
+	first := true
+	fmt.Fprint(w, "[")
+	for _, addr := range addrs.addrs {
+		opts := addrs.at(addr).([]option)
+		var childPath []int32
+		if addr.elementIndex < 0 {
+			// pseudo-option
+			childPath = append(path, int32(-addr.elementIndex))
+		} else {
+			childPath = append(path, addr.elementType, int32(addr.elementIndex))
+		}
+		p.printOptions(opts, w, inline(indent),
+			func(i int32) *descriptor.SourceCodeInfo_Location {
+				p := childPath
+				if addr.elementIndex >= 0 {
+					p = append(p, i)
+				}
+				return sourceInfo.Get(p)
+			},
+			func(w *writer, indent int, opt option) {
+				if first {
+					first = false
+				} else {
+					fmt.Fprint(w, ", ")
+				}
+				p.printOption(opt.name, opt.val, w, indent)
+				fmt.Fprint(w, " ") // trailing space
+			})
+	}
+	fmt.Fprint(w, "]")
+}
+
+func (p *Printer) printOptions(opts []option, w *writer, indent int, siFetch func(i int32) *descriptor.SourceCodeInfo_Location, fn func(w *writer, indent int, opt option)) {
+	for i, opt := range opts {
+		si := siFetch(int32(i))
+		p.printElement(false, si, w, indent, func(w *writer) {
+			fn(w, indent, opt)
+		})
+	}
+}
+
+func inline(indent int) int {
+	if indent < 0 {
+		// already inlined
+		return indent
+	}
+	// negative indent means inline; indent 2 stops further in case value wraps
+	return -indent - 2
+}
+
+func sortKeys(m map[interface{}]interface{}) []interface{} {
+	res := make(sortedKeys, len(m))
+	i := 0
+	for k := range m {
+		res[i] = k
+		i++
+	}
+	sort.Sort(res)
+	return ([]interface{})(res)
+}
+
+type sortedKeys []interface{}
+
+func (k sortedKeys) Len() int {
+	return len(k)
+}
+
+func (k sortedKeys) Swap(i, j int) {
+	k[i], k[j] = k[j], k[i]
+}
+
+func (k sortedKeys) Less(i, j int) bool {
+	switch i := k[i].(type) {
+	case int32:
+		return i < k[j].(int32)
+	case uint32:
+		return i < k[j].(uint32)
+	case int64:
+		return i < k[j].(int64)
+	case uint64:
+		return i < k[j].(uint64)
+	case string:
+		return i < k[j].(string)
+	case bool:
+		return !i && k[j].(bool)
+	default:
+		panic(fmt.Sprintf("invalid type for map key: %T", i))
+	}
+}
+
+func (p *Printer) printOption(name string, optVal interface{}, w *writer, indent int) {
+	fmt.Fprintf(w, "%s = ", name)
+
+	switch optVal := optVal.(type) {
+	case int32, uint32, int64, uint64:
+		fmt.Fprintf(w, "%d", optVal)
+	case float32, float64:
+		fmt.Fprintf(w, "%f", optVal)
+	case string:
+		fmt.Fprintf(w, "%s", quotedString(optVal))
+	case []byte:
+		fmt.Fprintf(w, "%s", quotedString(string(optVal)))
+	case bool:
+		fmt.Fprintf(w, "%v", optVal)
+	case ident:
+		fmt.Fprintf(w, "%s", optVal)
+	case *desc.EnumValueDescriptor:
+		fmt.Fprintf(w, "%s", optVal.GetName())
+	case proto.Message:
+		// TODO: if value is too long, marshal to text format with indentation to
+		// make output prettier (also requires correctly indenting subsequent lines)
+
+		// TODO: alternate approach so we can apply p.ForceFullyQualifiedNames
+		// inside the resulting value?
+
+		fmt.Fprintf(w, "{ %s }", proto.CompactTextString(optVal))
+	default:
+		panic(fmt.Sprintf("unknown type of value %T for field %s", optVal, name))
+	}
+}
+
+type edgeKind int
+
+const (
+	edgeKindOption edgeKind = iota
+	edgeKindFile
+	edgeKindMessage
+	edgeKindField
+	edgeKindOneOf
+	edgeKindExtensionRange
+	edgeKindEnum
+	edgeKindEnumVal
+	edgeKindService
+	edgeKindMethod
+)
+
+// edges in simple state machine for matching options paths
+// whose prefix should be included in source info to handle
+// the way options are printed (which cannot always include
+// the full path from original source)
+var edges = map[edgeKind]map[int32]edgeKind{
+	edgeKindFile: {
+		internal.File_optionsTag:    edgeKindOption,
+		internal.File_messagesTag:   edgeKindMessage,
+		internal.File_enumsTag:      edgeKindEnum,
+		internal.File_extensionsTag: edgeKindField,
+		internal.File_servicesTag:   edgeKindService,
+	},
+	edgeKindMessage: {
+		internal.Message_optionsTag:        edgeKindOption,
+		internal.Message_fieldsTag:         edgeKindField,
+		internal.Message_oneOfsTag:         edgeKindOneOf,
+		internal.Message_nestedMessagesTag: edgeKindMessage,
+		internal.Message_enumsTag:          edgeKindEnum,
+		internal.Message_extensionsTag:     edgeKindField,
+		internal.Message_extensionRangeTag: edgeKindExtensionRange,
+		// TODO: reserved range tag
+	},
+	edgeKindField: {
+		internal.Field_optionsTag: edgeKindOption,
+	},
+	edgeKindOneOf: {
+		internal.OneOf_optionsTag: edgeKindOption,
+	},
+	edgeKindExtensionRange: {
+		internal.ExtensionRange_optionsTag: edgeKindOption,
+	},
+	edgeKindEnum: {
+		internal.Enum_optionsTag: edgeKindOption,
+		internal.Enum_valuesTag:  edgeKindEnumVal,
+	},
+	edgeKindEnumVal: {
+		internal.EnumVal_optionsTag: edgeKindOption,
+	},
+	edgeKindService: {
+		internal.Service_optionsTag: edgeKindOption,
+		internal.Service_methodsTag: edgeKindMethod,
+	},
+	edgeKindMethod: {
+		internal.Method_optionsTag: edgeKindOption,
+	},
+}
+
+func extendOptionLocations(sc internal.SourceInfoMap) {
+	for _, loc := range sc {
+		allowed := edges[edgeKindFile]
+		for i := 0; i+1 < len(loc.Path); i += 2 {
+			nextKind, ok := allowed[loc.Path[i]]
+			if !ok {
+				break
+			}
+			if nextKind == edgeKindOption {
+				// We've found an option entry. This could be arbitrarily
+				// deep (for options that nested messages) or it could end
+				// abruptly (for non-repeated fields). But we need a path
+				// that is exactly the path-so-far plus two: the option tag
+				// and an optional index for repeated option fields (zero
+				// for non-repeated option fields). This is used for
+				// querying source info when printing options.
+				// for sorting elements
+				newPath := make([]int32, i+3)
+				copy(newPath, loc.Path)
+				sc.PutIfAbsent(newPath, loc)
+				// we do another path of path-so-far plus two, but with
+				// explicit zero index -- just in case this actual path has
+				// an extra path element, but it's not an index (e.g the
+				// option field is not repeated, but the source info we are
+				// looking at indicates a tag of a nested field)
+				newPath[len(newPath)-1] = 0
+				sc.PutIfAbsent(newPath, loc)
+				// finally, we need the path-so-far plus one, just the option
+				// tag, for sorting option groups
+				newPath = newPath[:len(newPath)-1]
+				sc.PutIfAbsent(newPath, loc)
+
+				break
+			} else {
+				allowed = edges[nextKind]
+			}
+		}
+	}
+}
+
+func (p *Printer) extractOptions(dsc desc.Descriptor, opts proto.Message, mf *dynamic.MessageFactory) (map[int32][]option, error) {
+	md, err := desc.LoadMessageDescriptorForMessage(opts)
+	if err != nil {
+		return nil, err
+	}
+	dm := mf.NewDynamicMessage(md)
+	if err = dm.ConvertFrom(opts); err != nil {
+		return nil, fmt.Errorf("failed convert %s to dynamic message: %v", md.GetFullyQualifiedName(), err)
+	}
+
+	pkg := dsc.GetFile().GetPackage()
+	var scope string
+	if _, ok := dsc.(*desc.FileDescriptor); ok {
+		scope = pkg
+	} else {
+		scope = dsc.GetFullyQualifiedName()
+	}
+
+	options := map[int32][]option{}
+	var uninterpreted []interface{}
+	for _, fldset := range [][]*desc.FieldDescriptor{md.GetFields(), mf.GetExtensionRegistry().AllExtensionsForType(md.GetFullyQualifiedName())} {
+		for _, fld := range fldset {
+			if dm.HasField(fld) {
+				val := dm.GetField(fld)
+				var opts []option
+				var name string
+				if fld.IsExtension() {
+					name = fmt.Sprintf("(%s)", p.qualifyName(pkg, scope, fld.GetFullyQualifiedName()))
+				} else {
+					name = fld.GetName()
+				}
+				switch val := val.(type) {
+				case []interface{}:
+					if fld.GetNumber() == internal.UninterpretedOptionsTag {
+						// we handle uninterpreted options differently
+						uninterpreted = val
+						continue
+					}
+
+					for _, e := range val {
+						if fld.GetType() == descriptor.FieldDescriptorProto_TYPE_ENUM {
+							ev := fld.GetEnumType().FindValueByNumber(e.(int32))
+							if ev == nil {
+								// have to skip unknown enum values :(
+								continue
+							}
+							e = ev
+						}
+						var name string
+						if fld.IsExtension() {
+							name = fmt.Sprintf("(%s)", p.qualifyName(pkg, scope, fld.GetFullyQualifiedName()))
+						} else {
+							name = fld.GetName()
+						}
+						opts = append(opts, option{name: name, val: e})
+					}
+				case map[interface{}]interface{}:
+					for k := range sortKeys(val) {
+						v := val[k]
+						vf := fld.GetMapValueType()
+						if vf.GetType() == descriptor.FieldDescriptorProto_TYPE_ENUM {
+							ev := vf.GetEnumType().FindValueByNumber(v.(int32))
+							if ev == nil {
+								// have to skip unknown enum values :(
+								continue
+							}
+							v = ev
+						}
+						entry := mf.NewDynamicMessage(fld.GetMessageType())
+						entry.SetFieldByNumber(1, k)
+						entry.SetFieldByNumber(2, v)
+						opts = append(opts, option{name: name, val: entry})
+					}
+				default:
+					if fld.GetType() == descriptor.FieldDescriptorProto_TYPE_ENUM {
+						ev := fld.GetEnumType().FindValueByNumber(val.(int32))
+						if ev == nil {
+							// have to skip unknown enum values :(
+							continue
+						}
+						val = ev
+					}
+					opts = append(opts, option{name: name, val: val})
+				}
+				if len(opts) > 0 {
+					options[fld.GetNumber()] = opts
+				}
+			}
+		}
+	}
+
+	// if there are uninterpreted options, add those too
+	if len(uninterpreted) > 0 {
+		opts := make([]option, len(uninterpreted))
+		for i, u := range uninterpreted {
+			var unint *descriptor.UninterpretedOption
+			if un, ok := u.(*descriptor.UninterpretedOption); ok {
+				unint = un
+			} else {
+				dm := u.(*dynamic.Message)
+				unint = &descriptor.UninterpretedOption{}
+				if err := dm.ConvertTo(unint); err != nil {
+					return nil, err
+				}
+			}
+
+			var buf bytes.Buffer
+			for ni, n := range unint.Name {
+				if ni > 0 {
+					buf.WriteByte('.')
+				}
+				if n.GetIsExtension() {
+					fmt.Fprintf(&buf, "(%s)", n.GetNamePart())
+				} else {
+					buf.WriteString(n.GetNamePart())
+				}
+			}
+
+			var v interface{}
+			switch {
+			case unint.IdentifierValue != nil:
+				v = ident(unint.GetIdentifierValue())
+			case unint.StringValue != nil:
+				v = string(unint.GetStringValue())
+			case unint.DoubleValue != nil:
+				v = unint.GetDoubleValue()
+			case unint.PositiveIntValue != nil:
+				v = unint.GetPositiveIntValue()
+			case unint.NegativeIntValue != nil:
+				v = unint.GetNegativeIntValue()
+			case unint.AggregateValue != nil:
+				v = ident(unint.GetAggregateValue())
+			}
+
+			opts[i] = option{name: buf.String(), val: v}
+		}
+		options[internal.UninterpretedOptionsTag] = opts
+	}
+
+	return options, nil
+}
+
+func optionsAsElementAddrs(optionsTag int32, order int, opts map[int32][]option) []elementAddr {
+	var optAddrs []elementAddr
+	for tag := range opts {
+		optAddrs = append(optAddrs, elementAddr{elementType: optionsTag, elementIndex: int(tag), order: order})
+	}
+	sort.Sort(optionsByName{addrs: optAddrs, opts: opts})
+	return optAddrs
+}
+
+// quotedString implements the text format for string literals for protocol
+// buffers. This form is also acceptable for string literals in option values
+// by the protocol buffer compiler, protoc.
+func quotedString(s string) string {
+	var b bytes.Buffer
+	// use WriteByte here to get any needed indent
+	b.WriteByte('"')
+	// Loop over the bytes, not the runes.
+	for i := 0; i < len(s); i++ {
+		// Divergence from C++: we don't escape apostrophes.
+		// There's no need to escape them, and the C++ parser
+		// copes with a naked apostrophe.
+		switch c := s[i]; c {
+		case '\n':
+			b.WriteString("\\n")
+		case '\r':
+			b.WriteString("\\r")
+		case '\t':
+			b.WriteString("\\t")
+		case '"':
+			b.WriteString("\\")
+		case '\\':
+			b.WriteString("\\\\")
+		default:
+			if c >= 0x20 && c < 0x7f {
+				b.WriteByte(c)
+			} else {
+				fmt.Fprintf(&b, "\\%03o", c)
+			}
+		}
+	}
+	b.WriteByte('"')
+
+	return b.String()
+}
+
+type elementAddr struct {
+	elementType  int32
+	elementIndex int
+	order        int
+}
+
+type elementAddrs struct {
+	addrs []elementAddr
+	dsc   interface{}
+	opts  map[int32][]option
+}
+
+func (a elementAddrs) Len() int {
+	return len(a.addrs)
+}
+
+func (a elementAddrs) Less(i, j int) bool {
+	// explicit order is considered first
+	if a.addrs[i].order < a.addrs[j].order {
+		return true
+	} else if a.addrs[i].order > a.addrs[j].order {
+		return false
+	}
+	// if order is equal, sort by element type
+	if a.addrs[i].elementType < a.addrs[j].elementType {
+		return true
+	} else if a.addrs[i].elementType > a.addrs[j].elementType {
+		return false
+	}
+
+	di := a.at(a.addrs[i])
+	dj := a.at(a.addrs[j])
+
+	switch vi := di.(type) {
+	case *desc.FieldDescriptor:
+		// fields are ordered by tag number
+		vj := dj.(*desc.FieldDescriptor)
+		// regular fields before extensions; extensions grouped by extendee
+		if !vi.IsExtension() && vj.IsExtension() {
+			return true
+		} else if vi.IsExtension() && !vj.IsExtension() {
+			return false
+		} else if vi.IsExtension() && vj.IsExtension() {
+			if vi.GetOwner() != vj.GetOwner() {
+				return vi.GetOwner().GetFullyQualifiedName() < vj.GetOwner().GetFullyQualifiedName()
+			}
+		}
+		return vi.GetNumber() < vj.GetNumber()
+
+	case *desc.EnumValueDescriptor:
+		// enum values ordered by number then name
+		vj := dj.(*desc.EnumValueDescriptor)
+		if vi.GetNumber() == vj.GetNumber() {
+			return vi.GetName() < vj.GetName()
+		}
+		return vi.GetNumber() < vj.GetNumber()
+
+	case *descriptor.DescriptorProto_ExtensionRange:
+		// extension ranges ordered by tag
+		return vi.GetStart() < dj.(*descriptor.DescriptorProto_ExtensionRange).GetStart()
+
+	case reservedRange:
+		// reserved ranges ordered by tag, too
+		return vi.start < dj.(reservedRange).start
+
+	case string:
+		// reserved names lexically sorted
+		return vi < dj.(string)
+
+	case pkg:
+		// reserved names lexically sorted
+		return vi < dj.(pkg)
+
+	case imp:
+		// reserved names lexically sorted
+		return vi < dj.(imp)
+
+	case []option:
+		// options sorted by name, extensions last
+		return optionLess(vi, dj.([]option))
+
+	default:
+		// all other descriptors ordered by name
+		return di.(desc.Descriptor).GetName() < dj.(desc.Descriptor).GetName()
+	}
+}
+
+func (a elementAddrs) Swap(i, j int) {
+	a.addrs[i], a.addrs[j] = a.addrs[j], a.addrs[i]
+}
+
+func (a elementAddrs) at(addr elementAddr) interface{} {
+	switch dsc := a.dsc.(type) {
+	case *desc.FileDescriptor:
+		switch addr.elementType {
+		case internal.File_packageTag:
+			return pkg(dsc.GetPackage())
+		case internal.File_dependencyTag:
+			return imp(dsc.AsFileDescriptorProto().GetDependency()[addr.elementIndex])
+		case internal.File_optionsTag:
+			return a.opts[int32(addr.elementIndex)]
+		case internal.File_messagesTag:
+			return dsc.GetMessageTypes()[addr.elementIndex]
+		case internal.File_enumsTag:
+			return dsc.GetEnumTypes()[addr.elementIndex]
+		case internal.File_servicesTag:
+			return dsc.GetServices()[addr.elementIndex]
+		case internal.File_extensionsTag:
+			return dsc.GetExtensions()[addr.elementIndex]
+		}
+	case *desc.MessageDescriptor:
+		switch addr.elementType {
+		case internal.Message_optionsTag:
+			return a.opts[int32(addr.elementIndex)]
+		case internal.Message_fieldsTag:
+			return dsc.GetFields()[addr.elementIndex]
+		case internal.Message_nestedMessagesTag:
+			return dsc.GetNestedMessageTypes()[addr.elementIndex]
+		case internal.Message_enumsTag:
+			return dsc.GetNestedEnumTypes()[addr.elementIndex]
+		case internal.Message_extensionsTag:
+			return dsc.GetNestedExtensions()[addr.elementIndex]
+		case internal.Message_extensionRangeTag:
+			return dsc.AsDescriptorProto().GetExtensionRange()[addr.elementIndex]
+		case internal.Message_reservedRangeTag:
+			rng := dsc.AsDescriptorProto().GetReservedRange()[addr.elementIndex]
+			return reservedRange{start: rng.GetStart(), end: rng.GetEnd() - 1}
+		case internal.Message_reservedNameTag:
+			return dsc.AsDescriptorProto().GetReservedName()[addr.elementIndex]
+		}
+	case *desc.FieldDescriptor:
+		if addr.elementType == internal.Field_optionsTag {
+			return a.opts[int32(addr.elementIndex)]
+		}
+	case *desc.OneOfDescriptor:
+		switch addr.elementType {
+		case internal.OneOf_optionsTag:
+			return a.opts[int32(addr.elementIndex)]
+		case -internal.Message_fieldsTag:
+			return dsc.GetOwner().GetFields()[addr.elementIndex]
+		}
+	case *desc.EnumDescriptor:
+		switch addr.elementType {
+		case internal.Enum_optionsTag:
+			return a.opts[int32(addr.elementIndex)]
+		case internal.Enum_valuesTag:
+			return dsc.GetValues()[addr.elementIndex]
+		case internal.Enum_reservedRangeTag:
+			rng := dsc.AsEnumDescriptorProto().GetReservedRange()[addr.elementIndex]
+			return reservedRange{start: rng.GetStart(), end: rng.GetEnd()}
+		case internal.Enum_reservedNameTag:
+			return dsc.AsEnumDescriptorProto().GetReservedName()[addr.elementIndex]
+		}
+	case *desc.EnumValueDescriptor:
+		if addr.elementType == internal.EnumVal_optionsTag {
+			return a.opts[int32(addr.elementIndex)]
+		}
+	case *desc.ServiceDescriptor:
+		switch addr.elementType {
+		case internal.Service_optionsTag:
+			return a.opts[int32(addr.elementIndex)]
+		case internal.Service_methodsTag:
+			return dsc.GetMethods()[addr.elementIndex]
+		}
+	case *desc.MethodDescriptor:
+		if addr.elementType == internal.Method_optionsTag {
+			return a.opts[int32(addr.elementIndex)]
+		}
+	case extensionRange:
+		if addr.elementType == internal.ExtensionRange_optionsTag {
+			return a.opts[int32(addr.elementIndex)]
+		}
+	}
+
+	panic(fmt.Sprintf("location for unknown field %d of %T", addr.elementType, a.dsc))
+}
+
+type extensionRange struct {
+	owner    *desc.MessageDescriptor
+	extRange *descriptor.DescriptorProto_ExtensionRange
+}
+
+type elementSrcOrder struct {
+	elementAddrs
+	sourceInfo internal.SourceInfoMap
+	prefix     []int32
+}
+
+func (a elementSrcOrder) Less(i, j int) bool {
+	ti := a.addrs[i].elementType
+	ei := a.addrs[i].elementIndex
+
+	tj := a.addrs[j].elementType
+	ej := a.addrs[j].elementIndex
+
+	var si, sj *descriptor.SourceCodeInfo_Location
+	if ei < 0 {
+		si = a.sourceInfo.Get(append(a.prefix, -int32(ei)))
+	} else if ti < 0 {
+		p := make([]int32, len(a.prefix)-2)
+		copy(p, a.prefix)
+		si = a.sourceInfo.Get(append(p, ti, int32(ei)))
+	} else {
+		si = a.sourceInfo.Get(append(a.prefix, ti, int32(ei)))
+	}
+	if ej < 0 {
+		sj = a.sourceInfo.Get(append(a.prefix, -int32(ej)))
+	} else if tj < 0 {
+		p := make([]int32, len(a.prefix)-2)
+		copy(p, a.prefix)
+		sj = a.sourceInfo.Get(append(p, tj, int32(ej)))
+	} else {
+		sj = a.sourceInfo.Get(append(a.prefix, tj, int32(ej)))
+	}
+
+	if (si == nil) != (sj == nil) {
+		// generally, we put unknown elements after known ones;
+		// except package and option elements go first
+
+		// i will be unknown and j will be known
+		swapped := false
+		if si != nil {
+			si, sj = sj, si
+			// no need to swap ti and tj because we don't use tj anywhere below
+			ti = tj
+			swapped = true
+		}
+		switch a.dsc.(type) {
+		case *desc.FileDescriptor:
+			if ti == internal.File_packageTag || ti == internal.File_optionsTag {
+				return !swapped
+			}
+		case *desc.MessageDescriptor:
+			if ti == internal.Message_optionsTag {
+				return !swapped
+			}
+		case *desc.EnumDescriptor:
+			if ti == internal.Enum_optionsTag {
+				return !swapped
+			}
+		case *desc.ServiceDescriptor:
+			if ti == internal.Service_optionsTag {
+				return !swapped
+			}
+		}
+		return swapped
+
+	} else if si == nil || sj == nil {
+		// let stable sort keep unknown elements in same relative order
+		return false
+	}
+
+	for idx := 0; idx < len(sj.Span); idx++ {
+		if idx >= len(si.Span) {
+			return true
+		}
+		if si.Span[idx] < sj.Span[idx] {
+			return true
+		}
+		if si.Span[idx] > sj.Span[idx] {
+			return false
+		}
+	}
+	return false
+}
+
+type optionsByName struct {
+	addrs []elementAddr
+	opts  map[int32][]option
+}
+
+func (o optionsByName) Len() int {
+	return len(o.addrs)
+}
+
+func (o optionsByName) Less(i, j int) bool {
+	oi := o.opts[int32(o.addrs[i].elementIndex)]
+	oj := o.opts[int32(o.addrs[j].elementIndex)]
+	return optionLess(oi, oj)
+}
+
+func optionLess(i, j []option) bool {
+	ni := i[0].name
+	nj := j[0].name
+	if ni[0] != '(' && nj[0] == '(' {
+		return true
+	} else if ni[0] == '(' && nj[0] != '(' {
+		return false
+	}
+	return ni < nj
+}
+
+func (o optionsByName) Swap(i, j int) {
+	o.addrs[i], o.addrs[j] = o.addrs[j], o.addrs[i]
+}
+
+func (p *Printer) printElement(isDecriptor bool, si *descriptor.SourceCodeInfo_Location, w *writer, indent int, el func(*writer)) {
+	includeComments := isDecriptor || p.includeCommentType(CommentsTokens)
+
+	if includeComments && si != nil {
+		p.printLeadingComments(si, w, indent)
+	}
+	el(w)
+	if includeComments && si != nil {
+		p.printTrailingComments(si, w, indent)
+	}
+	if indent >= 0 && !w.newline {
+		// if we're not printing inline but element did not have trailing newline, add one now
+		fmt.Fprintln(w)
+	}
+}
+
+func (p *Printer) printElementString(si *descriptor.SourceCodeInfo_Location, w *writer, indent int, str string) {
+	p.printElement(false, si, w, inline(indent), func(w *writer) {
+		fmt.Fprintf(w, "%s ", str)
+	})
+}
+
+func (p *Printer) includeCommentType(c CommentType) bool {
+	return (p.OmitComments & c) == 0
+}
+
+func (p *Printer) printLeadingComments(si *descriptor.SourceCodeInfo_Location, w *writer, indent int) bool {
+	endsInNewLine := false
+
+	if p.includeCommentType(CommentsDetached) {
+		for _, c := range si.GetLeadingDetachedComments() {
+			if p.printComment(c, w, indent, true) {
+				// if comment ended in newline, add another newline to separate
+				// this comment from the next
+				p.newLine(w)
+				endsInNewLine = true
+			} else if indent < 0 {
+				// comment did not end in newline and we are trying to inline?
+				// just add a space to separate this comment from what follows
+				fmt.Fprint(w, " ")
+				endsInNewLine = false
+			} else {
+				// comment did not end in newline and we are *not* trying to inline?
+				// add newline to end of comment and add another to separate this
+				// comment from what follows
+				fmt.Fprintln(w) // needed to end comment, regardless of p.Compact
+				p.newLine(w)
+				endsInNewLine = true
+			}
+		}
+	}
+
+	if p.includeCommentType(CommentsLeading) && si.GetLeadingComments() != "" {
+		endsInNewLine = p.printComment(si.GetLeadingComments(), w, indent, true)
+		if !endsInNewLine {
+			if indent >= 0 {
+				// leading comment didn't end with newline but needs one
+				// (because we're *not* inlining)
+				fmt.Fprintln(w) // needed to end comment, regardless of p.Compact
+				endsInNewLine = true
+			} else {
+				// space between comment and following element when inlined
+				fmt.Fprint(w, " ")
+			}
+		}
+	}
+
+	return endsInNewLine
+}
+
+func (p *Printer) printTrailingComments(si *descriptor.SourceCodeInfo_Location, w *writer, indent int) {
+	if p.includeCommentType(CommentsTrailing) && si.GetTrailingComments() != "" {
+		if !p.printComment(si.GetTrailingComments(), w, indent, p.TrailingCommentsOnSeparateLine) && indent >= 0 {
+			// trailing comment didn't end with newline but needs one
+			// (because we're *not* inlining)
+			fmt.Fprintln(w) // needed to end comment, regardless of p.Compact
+		} else if indent < 0 {
+			fmt.Fprint(w, " ")
+		}
+	}
+}
+
+func (p *Printer) printComment(comments string, w *writer, indent int, forceNextLine bool) bool {
+	if comments == "" {
+		return false
+	}
+
+	var multiLine bool
+	if indent < 0 {
+		// use multi-line style when inlining
+		multiLine = true
+	} else {
+		multiLine = p.PreferMultiLineStyleComments
+	}
+	if multiLine && strings.Contains(comments, "*/") {
+		// can't emit '*/' in a multi-line style comment
+		multiLine = false
+	}
+
+	lines := strings.Split(comments, "\n")
+
+	// first, remove leading and trailing blank lines
+	if lines[0] == "" {
+		lines = lines[1:]
+	}
+	if lines[len(lines)-1] == "" {
+		lines = lines[:len(lines)-1]
+	}
+	if len(lines) == 0 {
+		return false
+	}
+
+	if indent >= 0 && !w.newline {
+		// last element did not have trailing newline, so we
+		// either need to tack on newline or, if comment is
+		// just one line, inline it on the end
+		if forceNextLine || len(lines) > 1 {
+			fmt.Fprintln(w)
+		} else {
+			if !w.space {
+				fmt.Fprint(w, " ")
+			}
+			indent = inline(indent)
+		}
+	}
+
+	if len(lines) == 1 && multiLine {
+		p.indent(w, indent)
+		line := lines[0]
+		if line[0] == ' ' && line[len(line)-1] != ' ' {
+			// add trailing space for symmetry
+			line += " "
+		}
+		fmt.Fprintf(w, "/*%s*/", line)
+		if indent >= 0 {
+			fmt.Fprintln(w)
+			return true
+		}
+		return false
+	}
+
+	if multiLine {
+		// multi-line style comments that actually span multiple lines
+		// get a blank line before and after so that comment renders nicely
+		lines = append(lines, "", "")
+		copy(lines[1:], lines)
+		lines[0] = ""
+	}
+
+	for i, l := range lines {
+		p.maybeIndent(w, indent, i > 0)
+		if multiLine {
+			if i == 0 {
+				// first line
+				fmt.Fprintf(w, "/*%s\n", strings.TrimRight(l, " \t"))
+			} else if i == len(lines)-1 {
+				// last line
+				if l == "" {
+					fmt.Fprint(w, " */")
+				} else {
+					fmt.Fprintf(w, " *%s*/", l)
+				}
+				if indent >= 0 {
+					fmt.Fprintln(w)
+				}
+			} else {
+				fmt.Fprintf(w, " *%s\n", strings.TrimRight(l, " \t"))
+			}
+		} else {
+			fmt.Fprintf(w, "//%s\n", strings.TrimRight(l, " \t"))
+		}
+	}
+
+	// single-line comments always end in newline; multi-line comments only
+	// end in newline for non-negative (e.g. non-inlined) indentation
+	return !multiLine || indent >= 0
+}
+
+func (p *Printer) indent(w io.Writer, indent int) {
+	for i := 0; i < indent; i++ {
+		fmt.Fprint(w, p.Indent)
+	}
+}
+
+func (p *Printer) maybeIndent(w io.Writer, indent int, requireIndent bool) {
+	if indent < 0 && requireIndent {
+		p.indent(w, -indent)
+	} else {
+		p.indent(w, indent)
+	}
+}
+
+type writer struct {
+	io.Writer
+	err     error
+	space   bool
+	newline bool
+}
+
+func newWriter(w io.Writer) *writer {
+	return &writer{Writer: w, newline: true}
+}
+
+func (w *writer) Write(p []byte) (int, error) {
+	if len(p) == 0 {
+		return 0, nil
+	}
+
+	w.newline = false
+
+	if w.space {
+		// skip any trailing space if the following
+		// character is semicolon, comma, or close bracket
+		if p[0] != ';' && p[0] != ',' && p[0] != ']' {
+			_, err := w.Writer.Write([]byte{' '})
+			if err != nil {
+				w.err = err
+				return 0, err
+			}
+		}
+		w.space = false
+	}
+
+	if p[len(p)-1] == ' ' {
+		w.space = true
+		p = p[:len(p)-1]
+	}
+	if len(p) > 0 && p[len(p)-1] == '\n' {
+		w.newline = true
+	}
+
+	num, err := w.Writer.Write(p)
+	if err != nil {
+		w.err = err
+	} else if w.space {
+		// pretend space was written
+		num++
+	}
+	return num, err
+}
