1package protoparse
2
3import (
4	"bytes"
5	"math"
6	"strings"
7	"unicode"
8
9	"github.com/golang/protobuf/proto"
10	dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
11
12	"github.com/jhump/protoreflect/desc/internal"
13	"github.com/jhump/protoreflect/desc/protoparse/ast"
14)
15
16func (r *parseResult) createFileDescriptor(filename string, file *ast.FileNode) {
17	fd := &dpb.FileDescriptorProto{Name: proto.String(filename)}
18	r.fd = fd
19	r.putFileNode(fd, file)
20
21	isProto3 := false
22	if file.Syntax != nil {
23		if file.Syntax.Syntax.AsString() == "proto3" {
24			isProto3 = true
25		} else if file.Syntax.Syntax.AsString() != "proto2" {
26			if r.errs.handleErrorWithPos(file.Syntax.Syntax.Start(), `syntax value must be "proto2" or "proto3"`) != nil {
27				return
28			}
29		}
30
31		// proto2 is the default, so no need to set unless proto3
32		if isProto3 {
33			fd.Syntax = proto.String(file.Syntax.Syntax.AsString())
34		}
35	} else {
36		r.errs.warn(file.Start(), ErrNoSyntax)
37	}
38
39	for _, decl := range file.Decls {
40		if r.errs.err != nil {
41			return
42		}
43		switch decl := decl.(type) {
44		case *ast.EnumNode:
45			fd.EnumType = append(fd.EnumType, r.asEnumDescriptor(decl))
46		case *ast.ExtendNode:
47			r.addExtensions(decl, &fd.Extension, &fd.MessageType, isProto3)
48		case *ast.ImportNode:
49			index := len(fd.Dependency)
50			fd.Dependency = append(fd.Dependency, decl.Name.AsString())
51			if decl.Public != nil {
52				fd.PublicDependency = append(fd.PublicDependency, int32(index))
53			} else if decl.Weak != nil {
54				fd.WeakDependency = append(fd.WeakDependency, int32(index))
55			}
56		case *ast.MessageNode:
57			fd.MessageType = append(fd.MessageType, r.asMessageDescriptor(decl, isProto3))
58		case *ast.OptionNode:
59			if fd.Options == nil {
60				fd.Options = &dpb.FileOptions{}
61			}
62			fd.Options.UninterpretedOption = append(fd.Options.UninterpretedOption, r.asUninterpretedOption(decl))
63		case *ast.ServiceNode:
64			fd.Service = append(fd.Service, r.asServiceDescriptor(decl))
65		case *ast.PackageNode:
66			if fd.Package != nil {
67				if r.errs.handleErrorWithPos(decl.Start(), "files should have only one package declaration") != nil {
68					return
69				}
70			}
71			fd.Package = proto.String(string(decl.Name.AsIdentifier()))
72		}
73	}
74}
75
76func (r *parseResult) asUninterpretedOptions(nodes []*ast.OptionNode) []*dpb.UninterpretedOption {
77	if len(nodes) == 0 {
78		return nil
79	}
80	opts := make([]*dpb.UninterpretedOption, len(nodes))
81	for i, n := range nodes {
82		opts[i] = r.asUninterpretedOption(n)
83	}
84	return opts
85}
86
87func (r *parseResult) asUninterpretedOption(node *ast.OptionNode) *dpb.UninterpretedOption {
88	opt := &dpb.UninterpretedOption{Name: r.asUninterpretedOptionName(node.Name.Parts)}
89	r.putOptionNode(opt, node)
90
91	switch val := node.Val.Value().(type) {
92	case bool:
93		if val {
94			opt.IdentifierValue = proto.String("true")
95		} else {
96			opt.IdentifierValue = proto.String("false")
97		}
98	case int64:
99		opt.NegativeIntValue = proto.Int64(val)
100	case uint64:
101		opt.PositiveIntValue = proto.Uint64(val)
102	case float64:
103		opt.DoubleValue = proto.Float64(val)
104	case string:
105		opt.StringValue = []byte(val)
106	case ast.Identifier:
107		opt.IdentifierValue = proto.String(string(val))
108	case []*ast.MessageFieldNode:
109		var buf bytes.Buffer
110		aggToString(val, &buf)
111		aggStr := buf.String()
112		opt.AggregateValue = proto.String(aggStr)
113		//the grammar does not allow arrays here, so no case for []ast.ValueNode
114	}
115	return opt
116}
117
118func (r *parseResult) asUninterpretedOptionName(parts []*ast.FieldReferenceNode) []*dpb.UninterpretedOption_NamePart {
119	ret := make([]*dpb.UninterpretedOption_NamePart, len(parts))
120	for i, part := range parts {
121		np := &dpb.UninterpretedOption_NamePart{
122			NamePart:    proto.String(string(part.Name.AsIdentifier())),
123			IsExtension: proto.Bool(part.IsExtension()),
124		}
125		r.putOptionNamePartNode(np, part)
126		ret[i] = np
127	}
128	return ret
129}
130
131func (r *parseResult) addExtensions(ext *ast.ExtendNode, flds *[]*dpb.FieldDescriptorProto, msgs *[]*dpb.DescriptorProto, isProto3 bool) {
132	extendee := string(ext.Extendee.AsIdentifier())
133	count := 0
134	for _, decl := range ext.Decls {
135		switch decl := decl.(type) {
136		case *ast.FieldNode:
137			count++
138			// use higher limit since we don't know yet whether extendee is messageset wire format
139			fd := r.asFieldDescriptor(decl, internal.MaxTag, isProto3)
140			fd.Extendee = proto.String(extendee)
141			*flds = append(*flds, fd)
142		case *ast.GroupNode:
143			count++
144			// ditto: use higher limit right now
145			fd, md := r.asGroupDescriptors(decl, isProto3, internal.MaxTag)
146			fd.Extendee = proto.String(extendee)
147			*flds = append(*flds, fd)
148			*msgs = append(*msgs, md)
149		}
150	}
151	if count == 0 {
152		_ = r.errs.handleErrorWithPos(ext.Start(), "extend sections must define at least one extension")
153	}
154}
155
156func asLabel(lbl *ast.FieldLabel) *dpb.FieldDescriptorProto_Label {
157	if !lbl.IsPresent() {
158		return nil
159	}
160	switch {
161	case lbl.Repeated:
162		return dpb.FieldDescriptorProto_LABEL_REPEATED.Enum()
163	case lbl.Required:
164		return dpb.FieldDescriptorProto_LABEL_REQUIRED.Enum()
165	default:
166		return dpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum()
167	}
168}
169
170func (r *parseResult) asFieldDescriptor(node *ast.FieldNode, maxTag int32, isProto3 bool) *dpb.FieldDescriptorProto {
171	tag := node.Tag.Val
172	if err := checkTag(node.Tag.Start(), tag, maxTag); err != nil {
173		_ = r.errs.handleError(err)
174	}
175	fd := newFieldDescriptor(node.Name.Val, string(node.FldType.AsIdentifier()), int32(tag), asLabel(&node.Label))
176	r.putFieldNode(fd, node)
177	if opts := node.Options.GetElements(); len(opts) > 0 {
178		fd.Options = &dpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
179	}
180	if isProto3 && fd.Label != nil && fd.GetLabel() == dpb.FieldDescriptorProto_LABEL_OPTIONAL {
181		internal.SetProto3Optional(fd)
182	}
183	return fd
184}
185
186var fieldTypes = map[string]dpb.FieldDescriptorProto_Type{
187	"double":   dpb.FieldDescriptorProto_TYPE_DOUBLE,
188	"float":    dpb.FieldDescriptorProto_TYPE_FLOAT,
189	"int32":    dpb.FieldDescriptorProto_TYPE_INT32,
190	"int64":    dpb.FieldDescriptorProto_TYPE_INT64,
191	"uint32":   dpb.FieldDescriptorProto_TYPE_UINT32,
192	"uint64":   dpb.FieldDescriptorProto_TYPE_UINT64,
193	"sint32":   dpb.FieldDescriptorProto_TYPE_SINT32,
194	"sint64":   dpb.FieldDescriptorProto_TYPE_SINT64,
195	"fixed32":  dpb.FieldDescriptorProto_TYPE_FIXED32,
196	"fixed64":  dpb.FieldDescriptorProto_TYPE_FIXED64,
197	"sfixed32": dpb.FieldDescriptorProto_TYPE_SFIXED32,
198	"sfixed64": dpb.FieldDescriptorProto_TYPE_SFIXED64,
199	"bool":     dpb.FieldDescriptorProto_TYPE_BOOL,
200	"string":   dpb.FieldDescriptorProto_TYPE_STRING,
201	"bytes":    dpb.FieldDescriptorProto_TYPE_BYTES,
202}
203
204func newFieldDescriptor(name string, fieldType string, tag int32, lbl *dpb.FieldDescriptorProto_Label) *dpb.FieldDescriptorProto {
205	fd := &dpb.FieldDescriptorProto{
206		Name:     proto.String(name),
207		JsonName: proto.String(internal.JsonName(name)),
208		Number:   proto.Int32(tag),
209		Label:    lbl,
210	}
211	t, ok := fieldTypes[fieldType]
212	if ok {
213		fd.Type = t.Enum()
214	} else {
215		// NB: we don't have enough info to determine whether this is an enum
216		// or a message type, so we'll leave Type nil and set it later
217		// (during linking)
218		fd.TypeName = proto.String(fieldType)
219	}
220	return fd
221}
222
223func (r *parseResult) asGroupDescriptors(group *ast.GroupNode, isProto3 bool, maxTag int32) (*dpb.FieldDescriptorProto, *dpb.DescriptorProto) {
224	tag := group.Tag.Val
225	if err := checkTag(group.Tag.Start(), tag, maxTag); err != nil {
226		_ = r.errs.handleError(err)
227	}
228	if !unicode.IsUpper(rune(group.Name.Val[0])) {
229		_ = r.errs.handleErrorWithPos(group.Name.Start(), "group %s should have a name that starts with a capital letter", group.Name.Val)
230	}
231	fieldName := strings.ToLower(group.Name.Val)
232	fd := &dpb.FieldDescriptorProto{
233		Name:     proto.String(fieldName),
234		JsonName: proto.String(internal.JsonName(fieldName)),
235		Number:   proto.Int32(int32(tag)),
236		Label:    asLabel(&group.Label),
237		Type:     dpb.FieldDescriptorProto_TYPE_GROUP.Enum(),
238		TypeName: proto.String(group.Name.Val),
239	}
240	r.putFieldNode(fd, group)
241	if opts := group.Options.GetElements(); len(opts) > 0 {
242		fd.Options = &dpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
243	}
244	md := &dpb.DescriptorProto{Name: proto.String(group.Name.Val)}
245	r.putMessageNode(md, group)
246	r.addMessageBody(md, &group.MessageBody, isProto3)
247	return fd, md
248}
249
250func (r *parseResult) asMapDescriptors(mapField *ast.MapFieldNode, isProto3 bool, maxTag int32) (*dpb.FieldDescriptorProto, *dpb.DescriptorProto) {
251	tag := mapField.Tag.Val
252	if err := checkTag(mapField.Tag.Start(), tag, maxTag); err != nil {
253		_ = r.errs.handleError(err)
254	}
255	var lbl *dpb.FieldDescriptorProto_Label
256	if !isProto3 {
257		lbl = dpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum()
258	}
259	keyFd := newFieldDescriptor("key", mapField.MapType.KeyType.Val, 1, lbl)
260	r.putFieldNode(keyFd, mapField.KeyField())
261	valFd := newFieldDescriptor("value", string(mapField.MapType.ValueType.AsIdentifier()), 2, lbl)
262	r.putFieldNode(valFd, mapField.ValueField())
263	entryName := internal.InitCap(internal.JsonName(mapField.Name.Val)) + "Entry"
264	fd := newFieldDescriptor(mapField.Name.Val, entryName, int32(tag), dpb.FieldDescriptorProto_LABEL_REPEATED.Enum())
265	if opts := mapField.Options.GetElements(); len(opts) > 0 {
266		fd.Options = &dpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
267	}
268	r.putFieldNode(fd, mapField)
269	md := &dpb.DescriptorProto{
270		Name:    proto.String(entryName),
271		Options: &dpb.MessageOptions{MapEntry: proto.Bool(true)},
272		Field:   []*dpb.FieldDescriptorProto{keyFd, valFd},
273	}
274	r.putMessageNode(md, mapField)
275	return fd, md
276}
277
278func (r *parseResult) asExtensionRanges(node *ast.ExtensionRangeNode, maxTag int32) []*dpb.DescriptorProto_ExtensionRange {
279	opts := r.asUninterpretedOptions(node.Options.GetElements())
280	ers := make([]*dpb.DescriptorProto_ExtensionRange, len(node.Ranges))
281	for i, rng := range node.Ranges {
282		start, end := getRangeBounds(r, rng, 0, maxTag)
283		er := &dpb.DescriptorProto_ExtensionRange{
284			Start: proto.Int32(start),
285			End:   proto.Int32(end + 1),
286		}
287		if len(opts) > 0 {
288			er.Options = &dpb.ExtensionRangeOptions{UninterpretedOption: opts}
289		}
290		r.putExtensionRangeNode(er, rng)
291		ers[i] = er
292	}
293	return ers
294}
295
296func (r *parseResult) asEnumValue(ev *ast.EnumValueNode) *dpb.EnumValueDescriptorProto {
297	num, ok := ast.AsInt32(ev.Number, math.MinInt32, math.MaxInt32)
298	if !ok {
299		_ = r.errs.handleErrorWithPos(ev.Number.Start(), "value %d is out of range: should be between %d and %d", ev.Number.Value(), math.MinInt32, math.MaxInt32)
300	}
301	evd := &dpb.EnumValueDescriptorProto{Name: proto.String(ev.Name.Val), Number: proto.Int32(num)}
302	r.putEnumValueNode(evd, ev)
303	if opts := ev.Options.GetElements(); len(opts) > 0 {
304		evd.Options = &dpb.EnumValueOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
305	}
306	return evd
307}
308
309func (r *parseResult) asMethodDescriptor(node *ast.RPCNode) *dpb.MethodDescriptorProto {
310	md := &dpb.MethodDescriptorProto{
311		Name:       proto.String(node.Name.Val),
312		InputType:  proto.String(string(node.Input.MessageType.AsIdentifier())),
313		OutputType: proto.String(string(node.Output.MessageType.AsIdentifier())),
314	}
315	r.putMethodNode(md, node)
316	if node.Input.Stream != nil {
317		md.ClientStreaming = proto.Bool(true)
318	}
319	if node.Output.Stream != nil {
320		md.ServerStreaming = proto.Bool(true)
321	}
322	// protoc always adds a MethodOptions if there are brackets
323	// We do the same to match protoc as closely as possible
324	// https://github.com/protocolbuffers/protobuf/blob/0c3f43a6190b77f1f68b7425d1b7e1a8257a8d0c/src/google/protobuf/compiler/parser.cc#L2152
325	if node.OpenBrace != nil {
326		md.Options = &dpb.MethodOptions{}
327		for _, decl := range node.Decls {
328			switch decl := decl.(type) {
329			case *ast.OptionNode:
330				md.Options.UninterpretedOption = append(md.Options.UninterpretedOption, r.asUninterpretedOption(decl))
331			}
332		}
333	}
334	return md
335}
336
337func (r *parseResult) asEnumDescriptor(en *ast.EnumNode) *dpb.EnumDescriptorProto {
338	ed := &dpb.EnumDescriptorProto{Name: proto.String(en.Name.Val)}
339	r.putEnumNode(ed, en)
340	for _, decl := range en.Decls {
341		switch decl := decl.(type) {
342		case *ast.OptionNode:
343			if ed.Options == nil {
344				ed.Options = &dpb.EnumOptions{}
345			}
346			ed.Options.UninterpretedOption = append(ed.Options.UninterpretedOption, r.asUninterpretedOption(decl))
347		case *ast.EnumValueNode:
348			ed.Value = append(ed.Value, r.asEnumValue(decl))
349		case *ast.ReservedNode:
350			for _, n := range decl.Names {
351				ed.ReservedName = append(ed.ReservedName, n.AsString())
352			}
353			for _, rng := range decl.Ranges {
354				ed.ReservedRange = append(ed.ReservedRange, r.asEnumReservedRange(rng))
355			}
356		}
357	}
358	return ed
359}
360
361func (r *parseResult) asEnumReservedRange(rng *ast.RangeNode) *dpb.EnumDescriptorProto_EnumReservedRange {
362	start, end := getRangeBounds(r, rng, math.MinInt32, math.MaxInt32)
363	rr := &dpb.EnumDescriptorProto_EnumReservedRange{
364		Start: proto.Int32(start),
365		End:   proto.Int32(end),
366	}
367	r.putEnumReservedRangeNode(rr, rng)
368	return rr
369}
370
371func (r *parseResult) asMessageDescriptor(node *ast.MessageNode, isProto3 bool) *dpb.DescriptorProto {
372	msgd := &dpb.DescriptorProto{Name: proto.String(node.Name.Val)}
373	r.putMessageNode(msgd, node)
374	r.addMessageBody(msgd, &node.MessageBody, isProto3)
375	return msgd
376}
377
378func (r *parseResult) addMessageBody(msgd *dpb.DescriptorProto, body *ast.MessageBody, isProto3 bool) {
379	// first process any options
380	for _, decl := range body.Decls {
381		if opt, ok := decl.(*ast.OptionNode); ok {
382			if msgd.Options == nil {
383				msgd.Options = &dpb.MessageOptions{}
384			}
385			msgd.Options.UninterpretedOption = append(msgd.Options.UninterpretedOption, r.asUninterpretedOption(opt))
386		}
387	}
388
389	// now that we have options, we can see if this uses messageset wire format, which
390	// impacts how we validate tag numbers in any fields in the message
391	maxTag := int32(internal.MaxNormalTag)
392	messageSetOpt, err := isMessageSetWireFormat(r, "message "+msgd.GetName(), msgd)
393	if err != nil {
394		return
395	} else if messageSetOpt != nil {
396		maxTag = internal.MaxTag // higher limit for messageset wire format
397	}
398
399	rsvdNames := map[string]int{}
400
401	// now we can process the rest
402	for _, decl := range body.Decls {
403		switch decl := decl.(type) {
404		case *ast.EnumNode:
405			msgd.EnumType = append(msgd.EnumType, r.asEnumDescriptor(decl))
406		case *ast.ExtendNode:
407			r.addExtensions(decl, &msgd.Extension, &msgd.NestedType, isProto3)
408		case *ast.ExtensionRangeNode:
409			msgd.ExtensionRange = append(msgd.ExtensionRange, r.asExtensionRanges(decl, maxTag)...)
410		case *ast.FieldNode:
411			fd := r.asFieldDescriptor(decl, maxTag, isProto3)
412			msgd.Field = append(msgd.Field, fd)
413		case *ast.MapFieldNode:
414			fd, md := r.asMapDescriptors(decl, isProto3, maxTag)
415			msgd.Field = append(msgd.Field, fd)
416			msgd.NestedType = append(msgd.NestedType, md)
417		case *ast.GroupNode:
418			fd, md := r.asGroupDescriptors(decl, isProto3, maxTag)
419			msgd.Field = append(msgd.Field, fd)
420			msgd.NestedType = append(msgd.NestedType, md)
421		case *ast.OneOfNode:
422			oodIndex := len(msgd.OneofDecl)
423			ood := &dpb.OneofDescriptorProto{Name: proto.String(decl.Name.Val)}
424			r.putOneOfNode(ood, decl)
425			msgd.OneofDecl = append(msgd.OneofDecl, ood)
426			ooFields := 0
427			for _, oodecl := range decl.Decls {
428				switch oodecl := oodecl.(type) {
429				case *ast.OptionNode:
430					if ood.Options == nil {
431						ood.Options = &dpb.OneofOptions{}
432					}
433					ood.Options.UninterpretedOption = append(ood.Options.UninterpretedOption, r.asUninterpretedOption(oodecl))
434				case *ast.FieldNode:
435					fd := r.asFieldDescriptor(oodecl, maxTag, isProto3)
436					fd.OneofIndex = proto.Int32(int32(oodIndex))
437					msgd.Field = append(msgd.Field, fd)
438					ooFields++
439				case *ast.GroupNode:
440					fd, md := r.asGroupDescriptors(oodecl, isProto3, maxTag)
441					fd.OneofIndex = proto.Int32(int32(oodIndex))
442					msgd.Field = append(msgd.Field, fd)
443					msgd.NestedType = append(msgd.NestedType, md)
444					ooFields++
445				}
446			}
447			if ooFields == 0 {
448				_ = r.errs.handleErrorWithPos(decl.Start(), "oneof must contain at least one field")
449			}
450		case *ast.MessageNode:
451			msgd.NestedType = append(msgd.NestedType, r.asMessageDescriptor(decl, isProto3))
452		case *ast.ReservedNode:
453			for _, n := range decl.Names {
454				count := rsvdNames[n.AsString()]
455				if count == 1 { // already seen
456					_ = r.errs.handleErrorWithPos(n.Start(), "name %q is reserved multiple times", n.AsString())
457				}
458				rsvdNames[n.AsString()] = count + 1
459				msgd.ReservedName = append(msgd.ReservedName, n.AsString())
460			}
461			for _, rng := range decl.Ranges {
462				msgd.ReservedRange = append(msgd.ReservedRange, r.asMessageReservedRange(rng, maxTag))
463			}
464		}
465	}
466
467	if messageSetOpt != nil {
468		if len(msgd.Field) > 0 {
469			node := r.getFieldNode(msgd.Field[0])
470			_ = r.errs.handleErrorWithPos(node.Start(), "messages with message-set wire format cannot contain non-extension fields")
471		}
472		if len(msgd.ExtensionRange) == 0 {
473			node := r.getOptionNode(messageSetOpt)
474			_ = r.errs.handleErrorWithPos(node.Start(), "messages with message-set wire format must contain at least one extension range")
475		}
476	}
477
478	// process any proto3_optional fields
479	if isProto3 {
480		internal.ProcessProto3OptionalFields(msgd)
481	}
482}
483
484func isMessageSetWireFormat(res *parseResult, scope string, md *dpb.DescriptorProto) (*dpb.UninterpretedOption, error) {
485	uo := md.GetOptions().GetUninterpretedOption()
486	index, err := findOption(res, scope, uo, "message_set_wire_format")
487	if err != nil {
488		return nil, err
489	}
490	if index == -1 {
491		// no such option
492		return nil, nil
493	}
494
495	opt := uo[index]
496
497	switch opt.GetIdentifierValue() {
498	case "true":
499		return opt, nil
500	case "false":
501		return nil, nil
502	default:
503		optNode := res.getOptionNode(opt)
504		return nil, res.errs.handleErrorWithPos(optNode.GetValue().Start(), "%s: expecting bool value for message_set_wire_format option", scope)
505	}
506}
507
508func (r *parseResult) asMessageReservedRange(rng *ast.RangeNode, maxTag int32) *dpb.DescriptorProto_ReservedRange {
509	start, end := getRangeBounds(r, rng, 0, maxTag)
510	rr := &dpb.DescriptorProto_ReservedRange{
511		Start: proto.Int32(start),
512		End:   proto.Int32(end + 1),
513	}
514	r.putMessageReservedRangeNode(rr, rng)
515	return rr
516}
517
518func getRangeBounds(res *parseResult, rng *ast.RangeNode, minVal, maxVal int32) (int32, int32) {
519	checkOrder := true
520	start, ok := rng.StartValueAsInt32(minVal, maxVal)
521	if !ok {
522		checkOrder = false
523		_ = res.errs.handleErrorWithPos(rng.StartVal.Start(), "range start %d is out of range: should be between %d and %d", rng.StartValue(), minVal, maxVal)
524	}
525
526	end, ok := rng.EndValueAsInt32(minVal, maxVal)
527	if !ok {
528		checkOrder = false
529		if rng.EndVal != nil {
530			_ = res.errs.handleErrorWithPos(rng.EndVal.Start(), "range end %d is out of range: should be between %d and %d", rng.EndValue(), minVal, maxVal)
531		}
532	}
533
534	if checkOrder && start > end {
535		_ = res.errs.handleErrorWithPos(rng.RangeStart().Start(), "range, %d to %d, is invalid: start must be <= end", start, end)
536	}
537
538	return start, end
539}
540
541func (r *parseResult) asServiceDescriptor(svc *ast.ServiceNode) *dpb.ServiceDescriptorProto {
542	sd := &dpb.ServiceDescriptorProto{Name: proto.String(svc.Name.Val)}
543	r.putServiceNode(sd, svc)
544	for _, decl := range svc.Decls {
545		switch decl := decl.(type) {
546		case *ast.OptionNode:
547			if sd.Options == nil {
548				sd.Options = &dpb.ServiceOptions{}
549			}
550			sd.Options.UninterpretedOption = append(sd.Options.UninterpretedOption, r.asUninterpretedOption(decl))
551		case *ast.RPCNode:
552			sd.Method = append(sd.Method, r.asMethodDescriptor(decl))
553		}
554	}
555	return sd
556}
557