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 }