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
}
