github.com/jhump/protocompile@v0.0.0-20221021153901-4f6f732835e8/parser/result.go (about)

     1  package parser
     2  
     3  import (
     4  	"bytes"
     5  	"math"
     6  	"strings"
     7  	"unicode"
     8  
     9  	"google.golang.org/protobuf/proto"
    10  	"google.golang.org/protobuf/types/descriptorpb"
    11  
    12  	"github.com/jhump/protocompile/ast"
    13  	"github.com/jhump/protocompile/internal"
    14  	"github.com/jhump/protocompile/reporter"
    15  )
    16  
    17  type result struct {
    18  	file  *ast.FileNode
    19  	proto *descriptorpb.FileDescriptorProto
    20  
    21  	nodes map[proto.Message]ast.Node
    22  }
    23  
    24  // ResultWithoutAST returns a parse result that has no AST. All methods for
    25  // looking up AST nodes return a placeholder node that contains only the filename
    26  // in position information.
    27  func ResultWithoutAST(proto *descriptorpb.FileDescriptorProto) Result {
    28  	return &result{proto: proto}
    29  }
    30  
    31  // ResultFromAST constructs a descriptor proto from the given AST. The returned
    32  // result includes the descriptor proto and also contains an index that can be
    33  // used to lookup AST node information for elements in the descriptor proto
    34  // hierarchy.
    35  //
    36  // If validate is true, some basic validation is performed, to make sure the
    37  // resulting descriptor proto is valid per protobuf rules and semantics. Only
    38  // some language elements can be validated since some rules and semantics can
    39  // only be checked after all symbols are all resolved, which happens in the
    40  // linking step.
    41  //
    42  // The given handler is used to report any errors or warnings encountered. If any
    43  // errors are reported, this function returns a non-nil error.
    44  func ResultFromAST(file *ast.FileNode, validate bool, handler *reporter.Handler) (Result, error) {
    45  	filename := file.Name()
    46  	r := &result{file: file, nodes: map[proto.Message]ast.Node{}}
    47  	r.createFileDescriptor(filename, file, handler)
    48  	if validate {
    49  		validateBasic(r, handler)
    50  	}
    51  	return r, handler.Error()
    52  }
    53  
    54  func (r *result) AST() *ast.FileNode {
    55  	return r.file
    56  }
    57  
    58  func (r *result) Proto() *descriptorpb.FileDescriptorProto {
    59  	return r.proto
    60  }
    61  
    62  func (r *result) createFileDescriptor(filename string, file *ast.FileNode, handler *reporter.Handler) {
    63  	fd := &descriptorpb.FileDescriptorProto{Name: proto.String(filename)}
    64  	r.proto = fd
    65  
    66  	r.putFileNode(fd, file)
    67  
    68  	isProto3 := false
    69  	if file.Syntax != nil {
    70  		if file.Syntax.Syntax.AsString() == "proto3" {
    71  			isProto3 = true
    72  		} else if file.Syntax.Syntax.AsString() != "proto2" {
    73  			nodeInfo := file.NodeInfo(file.Syntax.Syntax)
    74  			if handler.HandleErrorf(nodeInfo.Start(), `syntax value must be "proto2" or "proto3"`) != nil {
    75  				return
    76  			}
    77  		}
    78  
    79  		// proto2 is the default, so no need to set unless proto3
    80  		if isProto3 {
    81  			fd.Syntax = proto.String(file.Syntax.Syntax.AsString())
    82  		}
    83  	} else {
    84  		nodeInfo := file.NodeInfo(file)
    85  		handler.HandleWarning(nodeInfo.Start(), ErrNoSyntax)
    86  	}
    87  
    88  	for _, decl := range file.Decls {
    89  		if handler.ReporterError() != nil {
    90  			return
    91  		}
    92  		switch decl := decl.(type) {
    93  		case *ast.EnumNode:
    94  			fd.EnumType = append(fd.EnumType, r.asEnumDescriptor(decl, handler))
    95  		case *ast.ExtendNode:
    96  			r.addExtensions(decl, &fd.Extension, &fd.MessageType, isProto3, handler)
    97  		case *ast.ImportNode:
    98  			index := len(fd.Dependency)
    99  			fd.Dependency = append(fd.Dependency, decl.Name.AsString())
   100  			if decl.Public != nil {
   101  				fd.PublicDependency = append(fd.PublicDependency, int32(index))
   102  			} else if decl.Weak != nil {
   103  				fd.WeakDependency = append(fd.WeakDependency, int32(index))
   104  			}
   105  		case *ast.MessageNode:
   106  			fd.MessageType = append(fd.MessageType, r.asMessageDescriptor(decl, isProto3, handler))
   107  		case *ast.OptionNode:
   108  			if fd.Options == nil {
   109  				fd.Options = &descriptorpb.FileOptions{}
   110  			}
   111  			fd.Options.UninterpretedOption = append(fd.Options.UninterpretedOption, r.asUninterpretedOption(decl))
   112  		case *ast.ServiceNode:
   113  			fd.Service = append(fd.Service, r.asServiceDescriptor(decl))
   114  		case *ast.PackageNode:
   115  			if fd.Package != nil {
   116  				nodeInfo := file.NodeInfo(decl)
   117  				if handler.HandleErrorf(nodeInfo.Start(), "files should have only one package declaration") != nil {
   118  					return
   119  				}
   120  			}
   121  			fd.Package = proto.String(string(decl.Name.AsIdentifier()))
   122  		}
   123  	}
   124  }
   125  
   126  func (r *result) asUninterpretedOptions(nodes []*ast.OptionNode) []*descriptorpb.UninterpretedOption {
   127  	if len(nodes) == 0 {
   128  		return nil
   129  	}
   130  	opts := make([]*descriptorpb.UninterpretedOption, len(nodes))
   131  	for i, n := range nodes {
   132  		opts[i] = r.asUninterpretedOption(n)
   133  	}
   134  	return opts
   135  }
   136  
   137  func (r *result) asUninterpretedOption(node *ast.OptionNode) *descriptorpb.UninterpretedOption {
   138  	opt := &descriptorpb.UninterpretedOption{Name: r.asUninterpretedOptionName(node.Name.Parts)}
   139  	r.putOptionNode(opt, node)
   140  
   141  	switch val := node.Val.Value().(type) {
   142  	case bool:
   143  		if val {
   144  			opt.IdentifierValue = proto.String("true")
   145  		} else {
   146  			opt.IdentifierValue = proto.String("false")
   147  		}
   148  	case int64:
   149  		opt.NegativeIntValue = proto.Int64(val)
   150  	case uint64:
   151  		opt.PositiveIntValue = proto.Uint64(val)
   152  	case float64:
   153  		opt.DoubleValue = proto.Float64(val)
   154  	case string:
   155  		opt.StringValue = []byte(val)
   156  	case ast.Identifier:
   157  		opt.IdentifierValue = proto.String(string(val))
   158  	default:
   159  		// the grammar does not allow arrays here, so the only possible case
   160  		// left should be []*ast.MessageFieldNode, which corresponds to an
   161  		// *ast.MessageLiteralNode
   162  		if n, ok := node.Val.(*ast.MessageLiteralNode); ok {
   163  			var buf bytes.Buffer
   164  			for i, el := range n.Elements {
   165  				flattenNode(r.file, el, &buf)
   166  				if len(n.Seps) > i && n.Seps[i] != nil {
   167  					buf.WriteRune(' ')
   168  					buf.WriteRune(n.Seps[i].Rune)
   169  				}
   170  			}
   171  			aggStr := buf.String()
   172  			opt.AggregateValue = proto.String(aggStr)
   173  		}
   174  		// TODO: else that reports an error or panics??
   175  	}
   176  	return opt
   177  }
   178  
   179  func flattenNode(f *ast.FileNode, n ast.Node, buf *bytes.Buffer) {
   180  	if cn, ok := n.(ast.CompositeNode); ok {
   181  		for _, ch := range cn.Children() {
   182  			flattenNode(f, ch, buf)
   183  		}
   184  		return
   185  	}
   186  
   187  	if buf.Len() > 0 {
   188  		buf.WriteRune(' ')
   189  	}
   190  	buf.WriteString(f.NodeInfo(n).RawText())
   191  }
   192  
   193  func (r *result) asUninterpretedOptionName(parts []*ast.FieldReferenceNode) []*descriptorpb.UninterpretedOption_NamePart {
   194  	ret := make([]*descriptorpb.UninterpretedOption_NamePart, len(parts))
   195  	for i, part := range parts {
   196  		np := &descriptorpb.UninterpretedOption_NamePart{
   197  			NamePart:    proto.String(string(part.Name.AsIdentifier())),
   198  			IsExtension: proto.Bool(part.IsExtension()),
   199  		}
   200  		r.putOptionNamePartNode(np, part)
   201  		ret[i] = np
   202  	}
   203  	return ret
   204  }
   205  
   206  func (r *result) addExtensions(ext *ast.ExtendNode, flds *[]*descriptorpb.FieldDescriptorProto, msgs *[]*descriptorpb.DescriptorProto, isProto3 bool, handler *reporter.Handler) {
   207  	extendee := string(ext.Extendee.AsIdentifier())
   208  	count := 0
   209  	for _, decl := range ext.Decls {
   210  		switch decl := decl.(type) {
   211  		case *ast.FieldNode:
   212  			count++
   213  			// use higher limit since we don't know yet whether extendee is messageset wire format
   214  			fd := r.asFieldDescriptor(decl, internal.MaxTag, isProto3, handler)
   215  			fd.Extendee = proto.String(extendee)
   216  			*flds = append(*flds, fd)
   217  		case *ast.GroupNode:
   218  			count++
   219  			// ditto: use higher limit right now
   220  			fd, md := r.asGroupDescriptors(decl, isProto3, internal.MaxTag, handler)
   221  			fd.Extendee = proto.String(extendee)
   222  			*flds = append(*flds, fd)
   223  			*msgs = append(*msgs, md)
   224  		}
   225  	}
   226  	if count == 0 {
   227  		nodeInfo := r.file.NodeInfo(ext)
   228  		_ = handler.HandleErrorf(nodeInfo.Start(), "extend sections must define at least one extension")
   229  	}
   230  }
   231  
   232  func asLabel(lbl *ast.FieldLabel) *descriptorpb.FieldDescriptorProto_Label {
   233  	if !lbl.IsPresent() {
   234  		return nil
   235  	}
   236  	switch {
   237  	case lbl.Repeated:
   238  		return descriptorpb.FieldDescriptorProto_LABEL_REPEATED.Enum()
   239  	case lbl.Required:
   240  		return descriptorpb.FieldDescriptorProto_LABEL_REQUIRED.Enum()
   241  	default:
   242  		return descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum()
   243  	}
   244  }
   245  
   246  func (r *result) asFieldDescriptor(node *ast.FieldNode, maxTag int32, isProto3 bool, handler *reporter.Handler) *descriptorpb.FieldDescriptorProto {
   247  	tag := node.Tag.Val
   248  	tagNodeInfo := r.file.NodeInfo(node.Tag)
   249  	if err := checkTag(tagNodeInfo.Start(), tag, maxTag); err != nil {
   250  		_ = handler.HandleError(err)
   251  	}
   252  	fd := newFieldDescriptor(node.Name.Val, string(node.FldType.AsIdentifier()), int32(tag), asLabel(&node.Label))
   253  	r.putFieldNode(fd, node)
   254  	if opts := node.Options.GetElements(); len(opts) > 0 {
   255  		fd.Options = &descriptorpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
   256  	}
   257  	if isProto3 && fd.Label != nil && fd.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL {
   258  		fd.Proto3Optional = proto.Bool(true)
   259  	}
   260  	return fd
   261  }
   262  
   263  var fieldTypes = map[string]descriptorpb.FieldDescriptorProto_Type{
   264  	"double":   descriptorpb.FieldDescriptorProto_TYPE_DOUBLE,
   265  	"float":    descriptorpb.FieldDescriptorProto_TYPE_FLOAT,
   266  	"int32":    descriptorpb.FieldDescriptorProto_TYPE_INT32,
   267  	"int64":    descriptorpb.FieldDescriptorProto_TYPE_INT64,
   268  	"uint32":   descriptorpb.FieldDescriptorProto_TYPE_UINT32,
   269  	"uint64":   descriptorpb.FieldDescriptorProto_TYPE_UINT64,
   270  	"sint32":   descriptorpb.FieldDescriptorProto_TYPE_SINT32,
   271  	"sint64":   descriptorpb.FieldDescriptorProto_TYPE_SINT64,
   272  	"fixed32":  descriptorpb.FieldDescriptorProto_TYPE_FIXED32,
   273  	"fixed64":  descriptorpb.FieldDescriptorProto_TYPE_FIXED64,
   274  	"sfixed32": descriptorpb.FieldDescriptorProto_TYPE_SFIXED32,
   275  	"sfixed64": descriptorpb.FieldDescriptorProto_TYPE_SFIXED64,
   276  	"bool":     descriptorpb.FieldDescriptorProto_TYPE_BOOL,
   277  	"string":   descriptorpb.FieldDescriptorProto_TYPE_STRING,
   278  	"bytes":    descriptorpb.FieldDescriptorProto_TYPE_BYTES,
   279  }
   280  
   281  func newFieldDescriptor(name string, fieldType string, tag int32, lbl *descriptorpb.FieldDescriptorProto_Label) *descriptorpb.FieldDescriptorProto {
   282  	fd := &descriptorpb.FieldDescriptorProto{
   283  		Name:     proto.String(name),
   284  		JsonName: proto.String(internal.JsonName(name)),
   285  		Number:   proto.Int32(tag),
   286  		Label:    lbl,
   287  	}
   288  	t, ok := fieldTypes[fieldType]
   289  	if ok {
   290  		fd.Type = t.Enum()
   291  	} else {
   292  		// NB: we don't have enough info to determine whether this is an enum
   293  		// or a message type, so we'll leave Type nil and set it later
   294  		// (during linking)
   295  		fd.TypeName = proto.String(fieldType)
   296  	}
   297  	return fd
   298  }
   299  
   300  func (r *result) asGroupDescriptors(group *ast.GroupNode, isProto3 bool, maxTag int32, handler *reporter.Handler) (*descriptorpb.FieldDescriptorProto, *descriptorpb.DescriptorProto) {
   301  	tag := group.Tag.Val
   302  	tagNodeInfo := r.file.NodeInfo(group.Tag)
   303  	if err := checkTag(tagNodeInfo.Start(), tag, maxTag); err != nil {
   304  		_ = handler.HandleError(err)
   305  	}
   306  	if !unicode.IsUpper(rune(group.Name.Val[0])) {
   307  		nameNodeInfo := r.file.NodeInfo(group.Name)
   308  		_ = handler.HandleErrorf(nameNodeInfo.Start(), "group %s should have a name that starts with a capital letter", group.Name.Val)
   309  	}
   310  	fieldName := strings.ToLower(group.Name.Val)
   311  	fd := &descriptorpb.FieldDescriptorProto{
   312  		Name:     proto.String(fieldName),
   313  		JsonName: proto.String(internal.JsonName(fieldName)),
   314  		Number:   proto.Int32(int32(tag)),
   315  		Label:    asLabel(&group.Label),
   316  		Type:     descriptorpb.FieldDescriptorProto_TYPE_GROUP.Enum(),
   317  		TypeName: proto.String(group.Name.Val),
   318  	}
   319  	r.putFieldNode(fd, group)
   320  	if opts := group.Options.GetElements(); len(opts) > 0 {
   321  		fd.Options = &descriptorpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
   322  	}
   323  	md := &descriptorpb.DescriptorProto{Name: proto.String(group.Name.Val)}
   324  	r.putMessageNode(md, group)
   325  	r.addMessageBody(md, &group.MessageBody, isProto3, handler)
   326  	return fd, md
   327  }
   328  
   329  func (r *result) asMapDescriptors(mapField *ast.MapFieldNode, isProto3 bool, maxTag int32, handler *reporter.Handler) (*descriptorpb.FieldDescriptorProto, *descriptorpb.DescriptorProto) {
   330  	tag := mapField.Tag.Val
   331  	tagNodeInfo := r.file.NodeInfo(mapField.Tag)
   332  	if err := checkTag(tagNodeInfo.Start(), tag, maxTag); err != nil {
   333  		_ = handler.HandleError(err)
   334  	}
   335  	var lbl *descriptorpb.FieldDescriptorProto_Label
   336  	if !isProto3 {
   337  		lbl = descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum()
   338  	}
   339  	keyFd := newFieldDescriptor("key", mapField.MapType.KeyType.Val, 1, lbl)
   340  	r.putFieldNode(keyFd, mapField.KeyField())
   341  	valFd := newFieldDescriptor("value", string(mapField.MapType.ValueType.AsIdentifier()), 2, lbl)
   342  	r.putFieldNode(valFd, mapField.ValueField())
   343  	entryName := internal.InitCap(internal.JsonName(mapField.Name.Val)) + "Entry"
   344  	fd := newFieldDescriptor(mapField.Name.Val, entryName, int32(tag), descriptorpb.FieldDescriptorProto_LABEL_REPEATED.Enum())
   345  	if opts := mapField.Options.GetElements(); len(opts) > 0 {
   346  		fd.Options = &descriptorpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
   347  	}
   348  	r.putFieldNode(fd, mapField)
   349  	md := &descriptorpb.DescriptorProto{
   350  		Name:    proto.String(entryName),
   351  		Options: &descriptorpb.MessageOptions{MapEntry: proto.Bool(true)},
   352  		Field:   []*descriptorpb.FieldDescriptorProto{keyFd, valFd},
   353  	}
   354  	r.putMessageNode(md, mapField)
   355  	return fd, md
   356  }
   357  
   358  func (r *result) asExtensionRanges(node *ast.ExtensionRangeNode, maxTag int32, handler *reporter.Handler) []*descriptorpb.DescriptorProto_ExtensionRange {
   359  	opts := r.asUninterpretedOptions(node.Options.GetElements())
   360  	ers := make([]*descriptorpb.DescriptorProto_ExtensionRange, len(node.Ranges))
   361  	for i, rng := range node.Ranges {
   362  		start, end := r.getRangeBounds(rng, 1, maxTag, handler)
   363  		er := &descriptorpb.DescriptorProto_ExtensionRange{
   364  			Start: proto.Int32(start),
   365  			End:   proto.Int32(end + 1),
   366  		}
   367  		if len(opts) > 0 {
   368  			er.Options = &descriptorpb.ExtensionRangeOptions{UninterpretedOption: opts}
   369  		}
   370  		r.putExtensionRangeNode(er, rng)
   371  		ers[i] = er
   372  	}
   373  	return ers
   374  }
   375  
   376  func (r *result) asEnumValue(ev *ast.EnumValueNode, handler *reporter.Handler) *descriptorpb.EnumValueDescriptorProto {
   377  	num, ok := ast.AsInt32(ev.Number, math.MinInt32, math.MaxInt32)
   378  	if !ok {
   379  		numberNodeInfo := r.file.NodeInfo(ev.Number)
   380  		_ = handler.HandleErrorf(numberNodeInfo.Start(), "value %d is out of range: should be between %d and %d", ev.Number.Value(), math.MinInt32, math.MaxInt32)
   381  	}
   382  	evd := &descriptorpb.EnumValueDescriptorProto{Name: proto.String(ev.Name.Val), Number: proto.Int32(num)}
   383  	r.putEnumValueNode(evd, ev)
   384  	if opts := ev.Options.GetElements(); len(opts) > 0 {
   385  		evd.Options = &descriptorpb.EnumValueOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
   386  	}
   387  	return evd
   388  }
   389  
   390  func (r *result) asMethodDescriptor(node *ast.RPCNode) *descriptorpb.MethodDescriptorProto {
   391  	md := &descriptorpb.MethodDescriptorProto{
   392  		Name:       proto.String(node.Name.Val),
   393  		InputType:  proto.String(string(node.Input.MessageType.AsIdentifier())),
   394  		OutputType: proto.String(string(node.Output.MessageType.AsIdentifier())),
   395  	}
   396  	r.putMethodNode(md, node)
   397  	if node.Input.Stream != nil {
   398  		md.ClientStreaming = proto.Bool(true)
   399  	}
   400  	if node.Output.Stream != nil {
   401  		md.ServerStreaming = proto.Bool(true)
   402  	}
   403  	// protoc always adds a MethodOptions if there are brackets
   404  	// We do the same to match protoc as closely as possible
   405  	// https://github.com/protocolbuffers/protobuf/blob/0c3f43a6190b77f1f68b7425d1b7e1a8257a8d0c/src/google/protobuf/compiler/parser.cc#L2152
   406  	if node.OpenBrace != nil {
   407  		md.Options = &descriptorpb.MethodOptions{}
   408  		for _, decl := range node.Decls {
   409  			switch decl := decl.(type) {
   410  			case *ast.OptionNode:
   411  				md.Options.UninterpretedOption = append(md.Options.UninterpretedOption, r.asUninterpretedOption(decl))
   412  			}
   413  		}
   414  	}
   415  	return md
   416  }
   417  
   418  func (r *result) asEnumDescriptor(en *ast.EnumNode, handler *reporter.Handler) *descriptorpb.EnumDescriptorProto {
   419  	ed := &descriptorpb.EnumDescriptorProto{Name: proto.String(en.Name.Val)}
   420  	r.putEnumNode(ed, en)
   421  	for _, decl := range en.Decls {
   422  		switch decl := decl.(type) {
   423  		case *ast.OptionNode:
   424  			if ed.Options == nil {
   425  				ed.Options = &descriptorpb.EnumOptions{}
   426  			}
   427  			ed.Options.UninterpretedOption = append(ed.Options.UninterpretedOption, r.asUninterpretedOption(decl))
   428  		case *ast.EnumValueNode:
   429  			ed.Value = append(ed.Value, r.asEnumValue(decl, handler))
   430  		case *ast.ReservedNode:
   431  			for _, n := range decl.Names {
   432  				ed.ReservedName = append(ed.ReservedName, n.AsString())
   433  			}
   434  			for _, rng := range decl.Ranges {
   435  				ed.ReservedRange = append(ed.ReservedRange, r.asEnumReservedRange(rng, handler))
   436  			}
   437  		}
   438  	}
   439  	return ed
   440  }
   441  
   442  func (r *result) asEnumReservedRange(rng *ast.RangeNode, handler *reporter.Handler) *descriptorpb.EnumDescriptorProto_EnumReservedRange {
   443  	start, end := r.getRangeBounds(rng, math.MinInt32, math.MaxInt32, handler)
   444  	rr := &descriptorpb.EnumDescriptorProto_EnumReservedRange{
   445  		Start: proto.Int32(start),
   446  		End:   proto.Int32(end),
   447  	}
   448  	r.putEnumReservedRangeNode(rr, rng)
   449  	return rr
   450  }
   451  
   452  func (r *result) asMessageDescriptor(node *ast.MessageNode, isProto3 bool, handler *reporter.Handler) *descriptorpb.DescriptorProto {
   453  	msgd := &descriptorpb.DescriptorProto{Name: proto.String(node.Name.Val)}
   454  	r.putMessageNode(msgd, node)
   455  	r.addMessageBody(msgd, &node.MessageBody, isProto3, handler)
   456  	return msgd
   457  }
   458  
   459  func (r *result) addMessageBody(msgd *descriptorpb.DescriptorProto, body *ast.MessageBody, isProto3 bool, handler *reporter.Handler) {
   460  	// first process any options
   461  	for _, decl := range body.Decls {
   462  		if opt, ok := decl.(*ast.OptionNode); ok {
   463  			if msgd.Options == nil {
   464  				msgd.Options = &descriptorpb.MessageOptions{}
   465  			}
   466  			msgd.Options.UninterpretedOption = append(msgd.Options.UninterpretedOption, r.asUninterpretedOption(opt))
   467  		}
   468  	}
   469  
   470  	// now that we have options, we can see if this uses messageset wire format, which
   471  	// impacts how we validate tag numbers in any fields in the message
   472  	maxTag := int32(internal.MaxNormalTag)
   473  	messageSetOpt, err := r.isMessageSetWireFormat("message "+msgd.GetName(), msgd, handler)
   474  	if err != nil {
   475  		return
   476  	} else if messageSetOpt != nil {
   477  		maxTag = internal.MaxTag // higher limit for messageset wire format
   478  	}
   479  
   480  	rsvdNames := map[string]int{}
   481  
   482  	// now we can process the rest
   483  	for _, decl := range body.Decls {
   484  		switch decl := decl.(type) {
   485  		case *ast.EnumNode:
   486  			msgd.EnumType = append(msgd.EnumType, r.asEnumDescriptor(decl, handler))
   487  		case *ast.ExtendNode:
   488  			r.addExtensions(decl, &msgd.Extension, &msgd.NestedType, isProto3, handler)
   489  		case *ast.ExtensionRangeNode:
   490  			msgd.ExtensionRange = append(msgd.ExtensionRange, r.asExtensionRanges(decl, maxTag, handler)...)
   491  		case *ast.FieldNode:
   492  			fd := r.asFieldDescriptor(decl, maxTag, isProto3, handler)
   493  			msgd.Field = append(msgd.Field, fd)
   494  		case *ast.MapFieldNode:
   495  			fd, md := r.asMapDescriptors(decl, isProto3, maxTag, handler)
   496  			msgd.Field = append(msgd.Field, fd)
   497  			msgd.NestedType = append(msgd.NestedType, md)
   498  		case *ast.GroupNode:
   499  			fd, md := r.asGroupDescriptors(decl, isProto3, maxTag, handler)
   500  			msgd.Field = append(msgd.Field, fd)
   501  			msgd.NestedType = append(msgd.NestedType, md)
   502  		case *ast.OneOfNode:
   503  			oodIndex := len(msgd.OneofDecl)
   504  			ood := &descriptorpb.OneofDescriptorProto{Name: proto.String(decl.Name.Val)}
   505  			r.putOneOfNode(ood, decl)
   506  			msgd.OneofDecl = append(msgd.OneofDecl, ood)
   507  			ooFields := 0
   508  			for _, oodecl := range decl.Decls {
   509  				switch oodecl := oodecl.(type) {
   510  				case *ast.OptionNode:
   511  					if ood.Options == nil {
   512  						ood.Options = &descriptorpb.OneofOptions{}
   513  					}
   514  					ood.Options.UninterpretedOption = append(ood.Options.UninterpretedOption, r.asUninterpretedOption(oodecl))
   515  				case *ast.FieldNode:
   516  					fd := r.asFieldDescriptor(oodecl, maxTag, isProto3, handler)
   517  					fd.OneofIndex = proto.Int32(int32(oodIndex))
   518  					msgd.Field = append(msgd.Field, fd)
   519  					ooFields++
   520  				case *ast.GroupNode:
   521  					fd, md := r.asGroupDescriptors(oodecl, isProto3, maxTag, handler)
   522  					fd.OneofIndex = proto.Int32(int32(oodIndex))
   523  					msgd.Field = append(msgd.Field, fd)
   524  					msgd.NestedType = append(msgd.NestedType, md)
   525  					ooFields++
   526  				}
   527  			}
   528  			if ooFields == 0 {
   529  				declNodeInfo := r.file.NodeInfo(decl)
   530  				_ = handler.HandleErrorf(declNodeInfo.Start(), "oneof must contain at least one field")
   531  			}
   532  		case *ast.MessageNode:
   533  			msgd.NestedType = append(msgd.NestedType, r.asMessageDescriptor(decl, isProto3, handler))
   534  		case *ast.ReservedNode:
   535  			for _, n := range decl.Names {
   536  				count := rsvdNames[n.AsString()]
   537  				if count == 1 { // already seen
   538  					nameNodeInfo := r.file.NodeInfo(n)
   539  					_ = handler.HandleErrorf(nameNodeInfo.Start(), "name %q is reserved multiple times", n.AsString())
   540  				}
   541  				rsvdNames[n.AsString()] = count + 1
   542  				msgd.ReservedName = append(msgd.ReservedName, n.AsString())
   543  			}
   544  			for _, rng := range decl.Ranges {
   545  				msgd.ReservedRange = append(msgd.ReservedRange, r.asMessageReservedRange(rng, maxTag, handler))
   546  			}
   547  		}
   548  	}
   549  
   550  	if messageSetOpt != nil {
   551  		if len(msgd.Field) > 0 {
   552  			node := r.FieldNode(msgd.Field[0])
   553  			nodeInfo := r.file.NodeInfo(node)
   554  			_ = handler.HandleErrorf(nodeInfo.Start(), "messages with message-set wire format cannot contain non-extension fields")
   555  		}
   556  		if len(msgd.ExtensionRange) == 0 {
   557  			node := r.OptionNode(messageSetOpt)
   558  			nodeInfo := r.file.NodeInfo(node)
   559  			_ = handler.HandleErrorf(nodeInfo.Start(), "messages with message-set wire format must contain at least one extension range")
   560  		}
   561  	}
   562  
   563  	// process any proto3_optional fields
   564  	if isProto3 {
   565  		r.processProto3OptionalFields(msgd)
   566  	}
   567  }
   568  
   569  func (r *result) isMessageSetWireFormat(scope string, md *descriptorpb.DescriptorProto, handler *reporter.Handler) (*descriptorpb.UninterpretedOption, error) {
   570  	uo := md.GetOptions().GetUninterpretedOption()
   571  	index, err := internal.FindOption(r, handler, scope, uo, "message_set_wire_format")
   572  	if err != nil {
   573  		return nil, err
   574  	}
   575  	if index == -1 {
   576  		// no such option
   577  		return nil, nil
   578  	}
   579  
   580  	opt := uo[index]
   581  
   582  	switch opt.GetIdentifierValue() {
   583  	case "true":
   584  		return opt, nil
   585  	case "false":
   586  		return nil, nil
   587  	default:
   588  		optNode := r.OptionNode(opt)
   589  		optNodeInfo := r.file.NodeInfo(optNode.GetValue())
   590  		return nil, handler.HandleErrorf(optNodeInfo.Start(), "%s: expecting bool value for message_set_wire_format option", scope)
   591  	}
   592  }
   593  
   594  func (r *result) asMessageReservedRange(rng *ast.RangeNode, maxTag int32, handler *reporter.Handler) *descriptorpb.DescriptorProto_ReservedRange {
   595  	start, end := r.getRangeBounds(rng, 1, maxTag, handler)
   596  	rr := &descriptorpb.DescriptorProto_ReservedRange{
   597  		Start: proto.Int32(start),
   598  		End:   proto.Int32(end + 1),
   599  	}
   600  	r.putMessageReservedRangeNode(rr, rng)
   601  	return rr
   602  }
   603  
   604  func (r *result) getRangeBounds(rng *ast.RangeNode, minVal, maxVal int32, handler *reporter.Handler) (int32, int32) {
   605  	checkOrder := true
   606  	start, ok := rng.StartValueAsInt32(minVal, maxVal)
   607  	if !ok {
   608  		checkOrder = false
   609  		startValNodeInfo := r.file.NodeInfo(rng.StartVal)
   610  		_ = handler.HandleErrorf(startValNodeInfo.Start(), "range start %d is out of range: should be between %d and %d", rng.StartValue(), minVal, maxVal)
   611  	}
   612  
   613  	end, ok := rng.EndValueAsInt32(minVal, maxVal)
   614  	if !ok {
   615  		checkOrder = false
   616  		if rng.EndVal != nil {
   617  			endValNodeInfo := r.file.NodeInfo(rng.EndVal)
   618  			_ = handler.HandleErrorf(endValNodeInfo.Start(), "range end %d is out of range: should be between %d and %d", rng.EndValue(), minVal, maxVal)
   619  		}
   620  	}
   621  
   622  	if checkOrder && start > end {
   623  		rangeStartNodeInfo := r.file.NodeInfo(rng.RangeStart())
   624  		_ = handler.HandleErrorf(rangeStartNodeInfo.Start(), "range, %d to %d, is invalid: start must be <= end", start, end)
   625  	}
   626  
   627  	return start, end
   628  }
   629  
   630  func (r *result) asServiceDescriptor(svc *ast.ServiceNode) *descriptorpb.ServiceDescriptorProto {
   631  	sd := &descriptorpb.ServiceDescriptorProto{Name: proto.String(svc.Name.Val)}
   632  	r.putServiceNode(sd, svc)
   633  	for _, decl := range svc.Decls {
   634  		switch decl := decl.(type) {
   635  		case *ast.OptionNode:
   636  			if sd.Options == nil {
   637  				sd.Options = &descriptorpb.ServiceOptions{}
   638  			}
   639  			sd.Options.UninterpretedOption = append(sd.Options.UninterpretedOption, r.asUninterpretedOption(decl))
   640  		case *ast.RPCNode:
   641  			sd.Method = append(sd.Method, r.asMethodDescriptor(decl))
   642  		}
   643  	}
   644  	return sd
   645  }
   646  
   647  func checkTag(pos ast.SourcePos, v uint64, maxTag int32) error {
   648  	if v < 1 {
   649  		return reporter.Errorf(pos, "tag number %d must be greater than zero", v)
   650  	} else if v > uint64(maxTag) {
   651  		return reporter.Errorf(pos, "tag number %d is higher than max allowed tag number (%d)", v, maxTag)
   652  	} else if v >= internal.SpecialReservedStart && v <= internal.SpecialReservedEnd {
   653  		return reporter.Errorf(pos, "tag number %d is in disallowed reserved range %d-%d", v, internal.SpecialReservedStart, internal.SpecialReservedEnd)
   654  	}
   655  	return nil
   656  }
   657  
   658  // processProto3OptionalFields adds synthetic oneofs to the given message descriptor
   659  // for each proto3 optional field. It also updates the fields to have the correct
   660  // oneof index reference.
   661  func (r *result) processProto3OptionalFields(msgd *descriptorpb.DescriptorProto) {
   662  	// add synthetic oneofs to the given message descriptor for each proto3
   663  	// optional field, and update each field to have correct oneof index
   664  	var allNames map[string]struct{}
   665  	for _, fd := range msgd.Field {
   666  		if fd.GetProto3Optional() {
   667  			// lazy init the set of all names
   668  			if allNames == nil {
   669  				allNames = map[string]struct{}{}
   670  				for _, fd := range msgd.Field {
   671  					allNames[fd.GetName()] = struct{}{}
   672  				}
   673  				for _, fd := range msgd.Extension {
   674  					allNames[fd.GetName()] = struct{}{}
   675  				}
   676  				for _, ed := range msgd.EnumType {
   677  					allNames[ed.GetName()] = struct{}{}
   678  					for _, evd := range ed.Value {
   679  						allNames[evd.GetName()] = struct{}{}
   680  					}
   681  				}
   682  				for _, fd := range msgd.NestedType {
   683  					allNames[fd.GetName()] = struct{}{}
   684  				}
   685  				for _, n := range msgd.ReservedName {
   686  					allNames[n] = struct{}{}
   687  				}
   688  			}
   689  
   690  			// Compute a name for the synthetic oneof. This uses the same
   691  			// algorithm as used in protoc:
   692  			//  https://github.com/protocolbuffers/protobuf/blob/74ad62759e0a9b5a21094f3fb9bb4ebfaa0d1ab8/src/google/protobuf/compiler/parser.cc#L785-L803
   693  			ooName := fd.GetName()
   694  			if !strings.HasPrefix(ooName, "_") {
   695  				ooName = "_" + ooName
   696  			}
   697  			for {
   698  				_, ok := allNames[ooName]
   699  				if !ok {
   700  					// found a unique name
   701  					allNames[ooName] = struct{}{}
   702  					break
   703  				}
   704  				ooName = "X" + ooName
   705  			}
   706  
   707  			fd.OneofIndex = proto.Int32(int32(len(msgd.OneofDecl)))
   708  			ood := &descriptorpb.OneofDescriptorProto{Name: proto.String(ooName)}
   709  			msgd.OneofDecl = append(msgd.OneofDecl, ood)
   710  			ooident := r.FieldNode(fd).FieldName().(*ast.IdentNode)
   711  			r.putOneOfNode(ood, ast.NewSyntheticOneOf(ooident))
   712  		}
   713  	}
   714  }
   715  
   716  func (r *result) Node(m proto.Message) ast.Node {
   717  	if r.nodes == nil {
   718  		return ast.NewNoSourceNode(r.proto.GetName())
   719  	}
   720  	return r.nodes[m]
   721  }
   722  
   723  func (r *result) FileNode() ast.FileDeclNode {
   724  	if r.nodes == nil {
   725  		return ast.NewNoSourceNode(r.proto.GetName())
   726  	}
   727  	return r.nodes[r.proto].(ast.FileDeclNode)
   728  }
   729  
   730  func (r *result) OptionNode(o *descriptorpb.UninterpretedOption) ast.OptionDeclNode {
   731  	if r.nodes == nil {
   732  		return ast.NewNoSourceNode(r.proto.GetName())
   733  	}
   734  	return r.nodes[o].(ast.OptionDeclNode)
   735  }
   736  
   737  func (r *result) OptionNamePartNode(o *descriptorpb.UninterpretedOption_NamePart) ast.Node {
   738  	if r.nodes == nil {
   739  		return ast.NewNoSourceNode(r.proto.GetName())
   740  	}
   741  	return r.nodes[o]
   742  }
   743  
   744  func (r *result) MessageNode(m *descriptorpb.DescriptorProto) ast.MessageDeclNode {
   745  	if r.nodes == nil {
   746  		return ast.NewNoSourceNode(r.proto.GetName())
   747  	}
   748  	return r.nodes[m].(ast.MessageDeclNode)
   749  }
   750  
   751  func (r *result) FieldNode(f *descriptorpb.FieldDescriptorProto) ast.FieldDeclNode {
   752  	if r.nodes == nil {
   753  		return ast.NewNoSourceNode(r.proto.GetName())
   754  	}
   755  	return r.nodes[f].(ast.FieldDeclNode)
   756  }
   757  
   758  func (r *result) OneOfNode(o *descriptorpb.OneofDescriptorProto) ast.Node {
   759  	if r.nodes == nil {
   760  		return ast.NewNoSourceNode(r.proto.GetName())
   761  	}
   762  	return r.nodes[o]
   763  }
   764  
   765  func (r *result) ExtensionRangeNode(e *descriptorpb.DescriptorProto_ExtensionRange) ast.RangeDeclNode {
   766  	if r.nodes == nil {
   767  		return ast.NewNoSourceNode(r.proto.GetName())
   768  	}
   769  	return r.nodes[e].(ast.RangeDeclNode)
   770  }
   771  
   772  func (r *result) MessageReservedRangeNode(rr *descriptorpb.DescriptorProto_ReservedRange) ast.RangeDeclNode {
   773  	if r.nodes == nil {
   774  		return ast.NewNoSourceNode(r.proto.GetName())
   775  	}
   776  	return r.nodes[rr].(ast.RangeDeclNode)
   777  }
   778  
   779  func (r *result) EnumNode(e *descriptorpb.EnumDescriptorProto) ast.Node {
   780  	if r.nodes == nil {
   781  		return ast.NewNoSourceNode(r.proto.GetName())
   782  	}
   783  	return r.nodes[e]
   784  }
   785  
   786  func (r *result) EnumValueNode(e *descriptorpb.EnumValueDescriptorProto) ast.EnumValueDeclNode {
   787  	if r.nodes == nil {
   788  		return ast.NewNoSourceNode(r.proto.GetName())
   789  	}
   790  	return r.nodes[e].(ast.EnumValueDeclNode)
   791  }
   792  
   793  func (r *result) EnumReservedRangeNode(rr *descriptorpb.EnumDescriptorProto_EnumReservedRange) ast.RangeDeclNode {
   794  	if r.nodes == nil {
   795  		return ast.NewNoSourceNode(r.proto.GetName())
   796  	}
   797  	return r.nodes[rr].(ast.RangeDeclNode)
   798  }
   799  
   800  func (r *result) ServiceNode(s *descriptorpb.ServiceDescriptorProto) ast.Node {
   801  	if r.nodes == nil {
   802  		return ast.NewNoSourceNode(r.proto.GetName())
   803  	}
   804  	return r.nodes[s]
   805  }
   806  
   807  func (r *result) MethodNode(m *descriptorpb.MethodDescriptorProto) ast.RPCDeclNode {
   808  	if r.nodes == nil {
   809  		return ast.NewNoSourceNode(r.proto.GetName())
   810  	}
   811  	return r.nodes[m].(ast.RPCDeclNode)
   812  }
   813  
   814  func (r *result) putFileNode(f *descriptorpb.FileDescriptorProto, n *ast.FileNode) {
   815  	r.nodes[f] = n
   816  }
   817  
   818  func (r *result) putOptionNode(o *descriptorpb.UninterpretedOption, n *ast.OptionNode) {
   819  	r.nodes[o] = n
   820  }
   821  
   822  func (r *result) putOptionNamePartNode(o *descriptorpb.UninterpretedOption_NamePart, n *ast.FieldReferenceNode) {
   823  	r.nodes[o] = n
   824  }
   825  
   826  func (r *result) putMessageNode(m *descriptorpb.DescriptorProto, n ast.MessageDeclNode) {
   827  	r.nodes[m] = n
   828  }
   829  
   830  func (r *result) putFieldNode(f *descriptorpb.FieldDescriptorProto, n ast.FieldDeclNode) {
   831  	r.nodes[f] = n
   832  }
   833  
   834  func (r *result) putOneOfNode(o *descriptorpb.OneofDescriptorProto, n ast.Node) {
   835  	r.nodes[o] = n
   836  }
   837  
   838  func (r *result) putExtensionRangeNode(e *descriptorpb.DescriptorProto_ExtensionRange, n *ast.RangeNode) {
   839  	r.nodes[e] = n
   840  }
   841  
   842  func (r *result) putMessageReservedRangeNode(rr *descriptorpb.DescriptorProto_ReservedRange, n *ast.RangeNode) {
   843  	r.nodes[rr] = n
   844  }
   845  
   846  func (r *result) putEnumNode(e *descriptorpb.EnumDescriptorProto, n *ast.EnumNode) {
   847  	r.nodes[e] = n
   848  }
   849  
   850  func (r *result) putEnumValueNode(e *descriptorpb.EnumValueDescriptorProto, n *ast.EnumValueNode) {
   851  	r.nodes[e] = n
   852  }
   853  
   854  func (r *result) putEnumReservedRangeNode(rr *descriptorpb.EnumDescriptorProto_EnumReservedRange, n *ast.RangeNode) {
   855  	r.nodes[rr] = n
   856  }
   857  
   858  func (r *result) putServiceNode(s *descriptorpb.ServiceDescriptorProto, n *ast.ServiceNode) {
   859  	r.nodes[s] = n
   860  }
   861  
   862  func (r *result) putMethodNode(m *descriptorpb.MethodDescriptorProto, n *ast.RPCNode) {
   863  	r.nodes[m] = n
   864  }