github.com/jhump/protocompile@v0.0.0-20221021153901-4f6f732835e8/options/options.go (about) 1 // Package options contains the logic for interpreting options. The parse step 2 // of compilation stores the options in uninterpreted form, which contains raw 3 // identifiers and literal values. 4 // 5 // The process of interpreting an option is to resolve identifiers, by examining 6 // descriptors for the Options types and their available extensions (custom 7 // options). As field names are resolved, the values can be type-checked against 8 // the types indicated in field descriptors. 9 // 10 // On success, the various fields and extensions of the options message are 11 // populated and the field holding the uninterpreted form is cleared. 12 package options 13 14 import ( 15 "bytes" 16 "fmt" 17 "math" 18 "sort" 19 "strings" 20 21 "google.golang.org/protobuf/proto" 22 "google.golang.org/protobuf/reflect/protoreflect" 23 "google.golang.org/protobuf/types/descriptorpb" 24 "google.golang.org/protobuf/types/dynamicpb" 25 26 "github.com/jhump/protocompile/ast" 27 "github.com/jhump/protocompile/internal" 28 "github.com/jhump/protocompile/linker" 29 "github.com/jhump/protocompile/parser" 30 "github.com/jhump/protocompile/reporter" 31 ) 32 33 // Index is a mapping of AST nodes that define options to a corresponding path 34 // into the containing file descriptor. The path is a sequence of field tags 35 // and indexes that define a traversal path from the root (the file descriptor) 36 // to the resolved option field. 37 type Index map[*ast.OptionNode][]int32 38 39 type interpreter struct { 40 file file 41 resolver linker.Resolver 42 lenient bool 43 reporter *reporter.Handler 44 index Index 45 } 46 47 type file interface { 48 parser.Result 49 ResolveEnumType(protoreflect.FullName) protoreflect.EnumDescriptor 50 ResolveMessageType(protoreflect.FullName) protoreflect.MessageDescriptor 51 ResolveExtension(protoreflect.FullName) protoreflect.ExtensionTypeDescriptor 52 } 53 54 type noResolveFile struct { 55 parser.Result 56 } 57 58 func (n noResolveFile) ResolveEnumType(name protoreflect.FullName) protoreflect.EnumDescriptor { 59 return nil 60 } 61 62 func (n noResolveFile) ResolveMessageType(name protoreflect.FullName) protoreflect.MessageDescriptor { 63 return nil 64 } 65 66 func (n noResolveFile) ResolveExtension(name protoreflect.FullName) protoreflect.ExtensionTypeDescriptor { 67 return nil 68 } 69 70 // InterpretOptions interprets options in the given linked result, returning 71 // an index that can be used to generate source code info. This step mutates 72 // the linked result's underlying proto to move option elements out of the 73 // "uninterpreted_option" fields and into proper option fields and extensions. 74 // 75 // The given handler is used to report errors and warnings. If any errors are 76 // reported, this function returns a non-nil error. 77 func InterpretOptions(linked linker.Result, handler *reporter.Handler) (Index, error) { 78 return interpretOptions(false, linked, handler) 79 } 80 81 // InterpretOptionsLenient interprets options in a lenient/best-effort way in 82 // the given linked result, returning an index that can be used to generate 83 // source code info. This step mutates the linked result's underlying proto to 84 // move option elements out of the "uninterpreted_option" fields and into proper 85 // option fields and extensions. 86 // 87 // In lenient more, errors resolving option names and type errors are ignored. 88 // Any options that are uninterpretable (due to such errors) will remain in the 89 // "uninterpreted_option" fields. 90 func InterpretOptionsLenient(linked linker.Result) (Index, error) { 91 return interpretOptions(true, linked, reporter.NewHandler(nil)) 92 } 93 94 // InterpretUnlinkedOptions does a best-effort attempt to interpret options in 95 // the given parsed result, returning an index that can be used to generate 96 // source code info. This step mutates the parsed result's underlying proto to 97 // move option elements out of the "uninterpreted_option" fields and into proper 98 // option fields and extensions. 99 // 100 // This is the same as InterpretOptionsLenient except that it accepts an 101 // unlinked result. Because the file is unlinked, custom options cannot be 102 // interpreted. Other errors resolving option names or type errors will be 103 // effectively ignored. Any options that are uninterpretable (due to such 104 // errors) will remain in the "uninterpreted_option" fields. 105 func InterpretUnlinkedOptions(parsed parser.Result) (Index, error) { 106 return interpretOptions(true, noResolveFile{parsed}, reporter.NewHandler(nil)) 107 } 108 109 func interpretOptions(lenient bool, file file, handler *reporter.Handler) (Index, error) { 110 interp := interpreter{ 111 file: file, 112 lenient: lenient, 113 reporter: handler, 114 index: Index{}, 115 } 116 if f, ok := file.(linker.File); ok { 117 interp.resolver = linker.ResolverFromFile(f) 118 } 119 120 fd := file.Proto() 121 prefix := fd.GetPackage() 122 if prefix != "" { 123 prefix += "." 124 } 125 opts := fd.GetOptions() 126 if opts != nil { 127 if len(opts.UninterpretedOption) > 0 { 128 if remain, err := interp.interpretOptions(fd.GetName(), fd, opts, opts.UninterpretedOption); err != nil { 129 return nil, err 130 } else { 131 opts.UninterpretedOption = remain 132 } 133 } 134 } 135 for _, md := range fd.GetMessageType() { 136 fqn := prefix + md.GetName() 137 if err := interp.interpretMessageOptions(fqn, md); err != nil { 138 return nil, err 139 } 140 } 141 for _, fld := range fd.GetExtension() { 142 fqn := prefix + fld.GetName() 143 if err := interp.interpretFieldOptions(fqn, fld); err != nil { 144 return nil, err 145 } 146 } 147 for _, ed := range fd.GetEnumType() { 148 fqn := prefix + ed.GetName() 149 if err := interp.interpretEnumOptions(fqn, ed); err != nil { 150 return nil, err 151 } 152 } 153 for _, sd := range fd.GetService() { 154 fqn := prefix + sd.GetName() 155 opts := sd.GetOptions() 156 if len(opts.GetUninterpretedOption()) > 0 { 157 if remain, err := interp.interpretOptions(fqn, sd, opts, opts.UninterpretedOption); err != nil { 158 return nil, err 159 } else { 160 opts.UninterpretedOption = remain 161 } 162 } 163 for _, mtd := range sd.GetMethod() { 164 mtdFqn := fqn + "." + mtd.GetName() 165 opts := mtd.GetOptions() 166 if len(opts.GetUninterpretedOption()) > 0 { 167 if remain, err := interp.interpretOptions(mtdFqn, mtd, opts, opts.UninterpretedOption); err != nil { 168 return nil, err 169 } else { 170 opts.UninterpretedOption = remain 171 } 172 } 173 } 174 } 175 return interp.index, nil 176 } 177 178 func (interp *interpreter) nodeInfo(n ast.Node) ast.NodeInfo { 179 return interp.file.FileNode().NodeInfo(n) 180 } 181 182 func (interp *interpreter) interpretMessageOptions(fqn string, md *descriptorpb.DescriptorProto) error { 183 opts := md.GetOptions() 184 if opts != nil { 185 if len(opts.UninterpretedOption) > 0 { 186 if remain, err := interp.interpretOptions(fqn, md, opts, opts.UninterpretedOption); err != nil { 187 return err 188 } else { 189 opts.UninterpretedOption = remain 190 } 191 } 192 } 193 for _, fld := range md.GetField() { 194 fldFqn := fqn + "." + fld.GetName() 195 if err := interp.interpretFieldOptions(fldFqn, fld); err != nil { 196 return err 197 } 198 } 199 for _, ood := range md.GetOneofDecl() { 200 oodFqn := fqn + "." + ood.GetName() 201 opts := ood.GetOptions() 202 if len(opts.GetUninterpretedOption()) > 0 { 203 if remain, err := interp.interpretOptions(oodFqn, ood, opts, opts.UninterpretedOption); err != nil { 204 return err 205 } else { 206 opts.UninterpretedOption = remain 207 } 208 } 209 } 210 for _, fld := range md.GetExtension() { 211 fldFqn := fqn + "." + fld.GetName() 212 if err := interp.interpretFieldOptions(fldFqn, fld); err != nil { 213 return err 214 } 215 } 216 for _, er := range md.GetExtensionRange() { 217 erFqn := fmt.Sprintf("%s.%d-%d", fqn, er.GetStart(), er.GetEnd()) 218 opts := er.GetOptions() 219 if len(opts.GetUninterpretedOption()) > 0 { 220 if remain, err := interp.interpretOptions(erFqn, er, opts, opts.UninterpretedOption); err != nil { 221 return err 222 } else { 223 opts.UninterpretedOption = remain 224 } 225 } 226 } 227 for _, nmd := range md.GetNestedType() { 228 nmdFqn := fqn + "." + nmd.GetName() 229 if err := interp.interpretMessageOptions(nmdFqn, nmd); err != nil { 230 return err 231 } 232 } 233 for _, ed := range md.GetEnumType() { 234 edFqn := fqn + "." + ed.GetName() 235 if err := interp.interpretEnumOptions(edFqn, ed); err != nil { 236 return err 237 } 238 } 239 return nil 240 } 241 242 func (interp *interpreter) interpretFieldOptions(fqn string, fld *descriptorpb.FieldDescriptorProto) error { 243 opts := fld.GetOptions() 244 if len(opts.GetUninterpretedOption()) > 0 { 245 uo := opts.UninterpretedOption 246 scope := fmt.Sprintf("field %s", fqn) 247 248 // process json_name pseudo-option 249 if index, err := internal.FindOption(interp.file, interp.reporter, scope, uo, "json_name"); err != nil && !interp.lenient { 250 return err 251 } else if index >= 0 { 252 opt := uo[index] 253 optNode := interp.file.OptionNode(opt) 254 255 // attribute source code info 256 if on, ok := optNode.(*ast.OptionNode); ok { 257 interp.index[on] = []int32{-1, internal.Field_jsonNameTag} 258 } 259 uo = internal.RemoveOption(uo, index) 260 if opt.StringValue == nil { 261 if err := interp.reporter.HandleErrorf(interp.nodeInfo(optNode.GetValue()).Start(), "%s: expecting string value for json_name option", scope); err != nil { 262 return err 263 } 264 } else { 265 fld.JsonName = proto.String(string(opt.StringValue)) 266 } 267 } 268 269 // and process default pseudo-option 270 if index, err := interp.processDefaultOption(scope, fqn, fld, uo); err != nil && !interp.lenient { 271 return err 272 } else if index >= 0 { 273 // attribute source code info 274 optNode := interp.file.OptionNode(uo[index]) 275 if on, ok := optNode.(*ast.OptionNode); ok { 276 interp.index[on] = []int32{-1, internal.Field_defaultTag} 277 } 278 uo = internal.RemoveOption(uo, index) 279 } 280 281 if len(uo) == 0 { 282 // no real options, only pseudo-options above? clear out options 283 fld.Options = nil 284 } else if remain, err := interp.interpretOptions(fqn, fld, opts, uo); err != nil { 285 return err 286 } else { 287 opts.UninterpretedOption = remain 288 } 289 } 290 return nil 291 } 292 293 func (interp *interpreter) processDefaultOption(scope string, fqn string, fld *descriptorpb.FieldDescriptorProto, uos []*descriptorpb.UninterpretedOption) (defaultIndex int, err error) { 294 found, err := internal.FindOption(interp.file, interp.reporter, scope, uos, "default") 295 if err != nil || found == -1 { 296 return -1, err 297 } 298 opt := uos[found] 299 optNode := interp.file.OptionNode(opt) 300 if fld.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_REPEATED { 301 return -1, interp.reporter.HandleErrorf(interp.nodeInfo(optNode.GetName()).Start(), "%s: default value cannot be set because field is repeated", scope) 302 } 303 if fld.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP || fld.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE { 304 return -1, interp.reporter.HandleErrorf(interp.nodeInfo(optNode.GetName()).Start(), "%s: default value cannot be set because field is a message", scope) 305 } 306 val := optNode.GetValue() 307 if _, ok := val.(*ast.MessageLiteralNode); ok { 308 return -1, interp.reporter.HandleErrorf(interp.nodeInfo(val).Start(), "%s: default value cannot be a message", scope) 309 } 310 mc := &messageContext{ 311 res: interp.file, 312 file: interp.file.Proto(), 313 elementName: fqn, 314 elementType: descriptorType(fld), 315 option: opt, 316 } 317 var v interface{} 318 if fld.GetType() == descriptorpb.FieldDescriptorProto_TYPE_ENUM { 319 ed := interp.file.ResolveEnumType(protoreflect.FullName(fld.GetTypeName())) 320 ev, err := interp.enumFieldValue(mc, ed, val) 321 if err != nil { 322 return -1, interp.reporter.HandleError(err) 323 } 324 v = string(ev.Name()) 325 } else { 326 v, err = interp.scalarFieldValue(mc, fld.GetType(), val) 327 if err != nil { 328 return -1, interp.reporter.HandleError(err) 329 } 330 } 331 if str, ok := v.(string); ok { 332 fld.DefaultValue = proto.String(str) 333 } else if b, ok := v.([]byte); ok { 334 fld.DefaultValue = proto.String(encodeDefaultBytes(b)) 335 } else { 336 var flt float64 337 var ok bool 338 if flt, ok = v.(float64); !ok { 339 var flt32 float32 340 if flt32, ok = v.(float32); ok { 341 flt = float64(flt32) 342 } 343 } 344 if ok { 345 if math.IsInf(flt, 1) { 346 fld.DefaultValue = proto.String("inf") 347 } else if ok && math.IsInf(flt, -1) { 348 fld.DefaultValue = proto.String("-inf") 349 } else if ok && math.IsNaN(flt) { 350 fld.DefaultValue = proto.String("nan") 351 } else { 352 fld.DefaultValue = proto.String(fmt.Sprintf("%v", v)) 353 } 354 } else { 355 fld.DefaultValue = proto.String(fmt.Sprintf("%v", v)) 356 } 357 } 358 return found, nil 359 } 360 361 func encodeDefaultBytes(b []byte) string { 362 var buf bytes.Buffer 363 internal.WriteEscapedBytes(&buf, b) 364 return buf.String() 365 } 366 367 func (interp *interpreter) interpretEnumOptions(fqn string, ed *descriptorpb.EnumDescriptorProto) error { 368 opts := ed.GetOptions() 369 if opts != nil { 370 if len(opts.UninterpretedOption) > 0 { 371 if remain, err := interp.interpretOptions(fqn, ed, opts, opts.UninterpretedOption); err != nil { 372 return err 373 } else { 374 opts.UninterpretedOption = remain 375 } 376 } 377 } 378 for _, evd := range ed.GetValue() { 379 evdFqn := fqn + "." + evd.GetName() 380 opts := evd.GetOptions() 381 if len(opts.GetUninterpretedOption()) > 0 { 382 if remain, err := interp.interpretOptions(evdFqn, evd, opts, opts.UninterpretedOption); err != nil { 383 return err 384 } else { 385 opts.UninterpretedOption = remain 386 } 387 } 388 } 389 return nil 390 } 391 392 func (interp *interpreter) interpretOptions(fqn string, element, opts proto.Message, uninterpreted []*descriptorpb.UninterpretedOption) ([]*descriptorpb.UninterpretedOption, error) { 393 optsFqn := string(opts.ProtoReflect().Descriptor().FullName()) 394 var msg protoreflect.Message 395 // see if the parse included an override copy for these options 396 if md := interp.file.ResolveMessageType(protoreflect.FullName(optsFqn)); md != nil { 397 dm := newDynamic(md) 398 if err := cloneInto(dm, opts, nil); err != nil { 399 node := interp.file.Node(element) 400 return nil, interp.reporter.HandleError(reporter.Error(interp.nodeInfo(node).Start(), err)) 401 } 402 msg = dm 403 } else { 404 msg = proto.Clone(opts).ProtoReflect() 405 } 406 407 mc := &messageContext{res: interp.file, file: interp.file.Proto(), elementName: fqn, elementType: descriptorType(element)} 408 var remain []*descriptorpb.UninterpretedOption 409 for _, uo := range uninterpreted { 410 node := interp.file.OptionNode(uo) 411 if !uo.Name[0].GetIsExtension() && uo.Name[0].GetNamePart() == "uninterpreted_option" { 412 if interp.lenient { 413 remain = append(remain, uo) 414 continue 415 } 416 // uninterpreted_option might be found reflectively, but is not actually valid for use 417 if err := interp.reporter.HandleErrorf(interp.nodeInfo(node.GetName()).Start(), "%vinvalid option 'uninterpreted_option'", mc); err != nil { 418 return nil, err 419 } 420 } 421 mc.option = uo 422 path, err := interp.interpretField(mc, element, msg, uo, 0, nil) 423 if err != nil { 424 if interp.lenient { 425 remain = append(remain, uo) 426 continue 427 } 428 return nil, err 429 } 430 if optn, ok := node.(*ast.OptionNode); ok { 431 interp.index[optn] = path 432 } 433 } 434 435 if interp.lenient { 436 // If we're lenient, then we don't want to clobber the passed in message 437 // and leave it partially populated. So we convert into a copy first 438 optsClone := opts.ProtoReflect().New().Interface() 439 if err := cloneInto(optsClone, msg.Interface(), interp.resolver); err != nil { 440 // TODO: do this in a more granular way, so we can convert individual 441 // fields and leave bad ones uninterpreted instead of skipping all of 442 // the work we've done so far. 443 return uninterpreted, nil 444 } 445 // conversion from dynamic message above worked, so now 446 // it is safe to overwrite the passed in message 447 proto.Reset(opts) 448 proto.Merge(opts, optsClone) 449 450 return remain, nil 451 } 452 453 if err := validateRecursive(msg, ""); err != nil { 454 node := interp.file.Node(element) 455 if err := interp.reporter.HandleErrorf(interp.nodeInfo(node).Start(), "error in %s options: %v", descriptorType(element), err); err != nil { 456 return nil, err 457 } 458 } 459 460 // now try to convert into the passed in message and fail if not successful 461 if err := cloneInto(opts, msg.Interface(), interp.resolver); err != nil { 462 node := interp.file.Node(element) 463 return nil, interp.reporter.HandleError(reporter.Error(interp.nodeInfo(node).Start(), err)) 464 } 465 466 return nil, nil 467 } 468 469 func cloneInto(dest proto.Message, src proto.Message, res linker.Resolver) error { 470 if dest.ProtoReflect().Descriptor() == src.ProtoReflect().Descriptor() { 471 proto.Reset(dest) 472 proto.Merge(dest, src) 473 if err := proto.CheckInitialized(dest); err != nil { 474 return err 475 } 476 return nil 477 } 478 479 // If descriptors are not the same, we could have field descriptors in src that 480 // don't match the ones in dest. There's no easy/sane way to handle that. So we 481 // just marshal to bytes and back to do this 482 data, err := proto.Marshal(src) 483 if err != nil { 484 return err 485 } 486 return proto.UnmarshalOptions{Resolver: res}.Unmarshal(data, dest) 487 } 488 489 func newDynamic(md protoreflect.MessageDescriptor) *deterministicDynamic { 490 return &deterministicDynamic{Message: dynamicpb.NewMessage(md)} 491 } 492 493 type deterministicDynamic struct { 494 *dynamicpb.Message 495 } 496 497 // ProtoReflect implements the protoreflect.ProtoMessage interface. 498 func (d *deterministicDynamic) ProtoReflect() protoreflect.Message { 499 return d 500 } 501 502 func (d *deterministicDynamic) Interface() protoreflect.ProtoMessage { 503 return d 504 } 505 506 func (d *deterministicDynamic) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { 507 var fields []protoreflect.FieldDescriptor 508 d.Message.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool { 509 fields = append(fields, fd) 510 return true 511 }) 512 // simple sort for deterministic marshaling 513 sort.Slice(fields, func(i, j int) bool { 514 return fields[i].Number() < fields[j].Number() 515 }) 516 for _, fld := range fields { 517 if !f(fld, d.Get(fld)) { 518 return 519 } 520 } 521 } 522 523 func (d *deterministicDynamic) Get(fd protoreflect.FieldDescriptor) protoreflect.Value { 524 v := d.Message.Get(fd) 525 if v.IsValid() && fd.IsMap() { 526 mp := v.Map() 527 if _, ok := mp.(*deterministicMap); !ok { 528 return protoreflect.ValueOfMap(&deterministicMap{Map: v.Map(), keyKind: fd.MapKey().Kind()}) 529 } 530 } 531 return v 532 } 533 534 type deterministicMap struct { 535 protoreflect.Map 536 keyKind protoreflect.Kind 537 } 538 539 func (m *deterministicMap) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) { 540 var keys []protoreflect.MapKey 541 m.Map.Range(func(k protoreflect.MapKey, _ protoreflect.Value) bool { 542 keys = append(keys, k) 543 return true 544 }) 545 sort.Slice(keys, func(i, j int) bool { 546 switch m.keyKind { 547 case protoreflect.BoolKind: 548 return !keys[i].Bool() && keys[j].Bool() 549 case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, 550 protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: 551 return keys[i].Int() < keys[j].Int() 552 case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, 553 protoreflect.Uint64Kind, protoreflect.Fixed64Kind: 554 return keys[i].Uint() < keys[j].Uint() 555 case protoreflect.StringKind: 556 return keys[i].String() < keys[j].String() 557 default: 558 panic("invalid kind: " + m.keyKind.String()) 559 } 560 }) 561 for _, key := range keys { 562 if !f(key, m.Map.Get(key)) { 563 break 564 } 565 } 566 } 567 568 func validateRecursive(msg protoreflect.Message, prefix string) error { 569 flds := msg.Descriptor().Fields() 570 var missingFields []string 571 for i := 0; i < flds.Len(); i++ { 572 fld := flds.Get(i) 573 if fld.Cardinality() == protoreflect.Required && !msg.Has(fld) { 574 missingFields = append(missingFields, fmt.Sprintf("%s%s", prefix, fld.Name())) 575 } 576 } 577 if len(missingFields) > 0 { 578 return fmt.Errorf("some required fields missing: %v", strings.Join(missingFields, ", ")) 579 } 580 581 var err error 582 msg.Range(func(fld protoreflect.FieldDescriptor, val protoreflect.Value) bool { 583 if fld.IsMap() { 584 md := fld.MapValue().Message() 585 if md != nil { 586 val.Map().Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { 587 chprefix := fmt.Sprintf("%s%s[%v].", prefix, fieldName(fld), k) 588 err = validateRecursive(v.Message(), chprefix) 589 if err != nil { 590 return false 591 } 592 return true 593 }) 594 if err != nil { 595 return false 596 } 597 } 598 } else { 599 md := fld.Message() 600 if md != nil { 601 if fld.IsList() { 602 sl := val.List() 603 for i := 0; i < sl.Len(); i++ { 604 v := sl.Get(i) 605 chprefix := fmt.Sprintf("%s%s[%d].", prefix, fieldName(fld), i) 606 err = validateRecursive(v.Message(), chprefix) 607 if err != nil { 608 return false 609 } 610 } 611 } else { 612 chprefix := fmt.Sprintf("%s%s.", prefix, fieldName(fld)) 613 err = validateRecursive(val.Message(), chprefix) 614 if err != nil { 615 return false 616 } 617 } 618 } 619 } 620 return true 621 }) 622 return err 623 } 624 625 func (interp *interpreter) interpretField(mc *messageContext, element proto.Message, msg protoreflect.Message, opt *descriptorpb.UninterpretedOption, nameIndex int, pathPrefix []int32) (path []int32, err error) { 626 var fld protoreflect.FieldDescriptor 627 nm := opt.GetName()[nameIndex] 628 node := interp.file.OptionNamePartNode(nm) 629 if nm.GetIsExtension() { 630 extName := nm.GetNamePart() 631 if extName[0] == '.' { 632 extName = extName[1:] /* skip leading dot */ 633 } 634 fld = interp.file.ResolveExtension(protoreflect.FullName(extName)) 635 if fld == nil { 636 return nil, interp.reporter.HandleErrorf(interp.nodeInfo(node).Start(), 637 "%vunrecognized extension %s of %s", 638 mc, extName, msg.Descriptor().FullName()) 639 } 640 if fld.ContainingMessage().FullName() != msg.Descriptor().FullName() { 641 return nil, interp.reporter.HandleErrorf(interp.nodeInfo(node).Start(), 642 "%vextension %s should extend %s but instead extends %s", 643 mc, extName, msg.Descriptor().FullName(), fld.ContainingMessage().FullName()) 644 } 645 } else { 646 fld = msg.Descriptor().Fields().ByName(protoreflect.Name(nm.GetNamePart())) 647 if fld == nil { 648 return nil, interp.reporter.HandleErrorf(interp.nodeInfo(node).Start(), 649 "%vfield %s of %s does not exist", 650 mc, nm.GetNamePart(), msg.Descriptor().FullName()) 651 } 652 } 653 654 path = append(pathPrefix, int32(fld.Number())) 655 656 if len(opt.GetName()) > nameIndex+1 { 657 nextnm := opt.GetName()[nameIndex+1] 658 nextnode := interp.file.OptionNamePartNode(nextnm) 659 k := fld.Kind() 660 if k != protoreflect.MessageKind && k != protoreflect.GroupKind { 661 return nil, interp.reporter.HandleErrorf(interp.nodeInfo(nextnode).Start(), 662 "%vcannot set field %s because %s is not a message", 663 mc, nextnm.GetNamePart(), nm.GetNamePart()) 664 } 665 if fld.Cardinality() == protoreflect.Repeated { 666 return nil, interp.reporter.HandleErrorf(interp.nodeInfo(nextnode).Start(), 667 "%vcannot set field %s because %s is repeated (must use an aggregate)", 668 mc, nextnm.GetNamePart(), nm.GetNamePart()) 669 } 670 var fdm protoreflect.Message 671 if msg.Has(fld) { 672 v := msg.Mutable(fld) 673 fdm = v.Message() 674 } else { 675 if ood := fld.ContainingOneof(); ood != nil { 676 existingFld := msg.WhichOneof(ood) 677 if existingFld != nil && existingFld.Number() != fld.Number() { 678 return nil, interp.reporter.HandleErrorf(interp.nodeInfo(node).Start(), 679 "%voneof %q already has field %q set", 680 mc, ood.Name(), fieldName(existingFld)) 681 } 682 } 683 fdm = newDynamic(fld.Message()) 684 msg.Set(fld, protoreflect.ValueOfMessage(fdm)) 685 } 686 // recurse to set next part of name 687 return interp.interpretField(mc, element, fdm, opt, nameIndex+1, path) 688 } 689 690 optNode := interp.file.OptionNode(opt) 691 if err := interp.setOptionField(mc, msg, fld, node, optNode.GetValue()); err != nil { 692 return nil, interp.reporter.HandleError(err) 693 } 694 if fld.IsMap() { 695 path = append(path, int32(msg.Get(fld).Map().Len())-1) 696 } else if fld.IsList() { 697 path = append(path, int32(msg.Get(fld).List().Len())-1) 698 } 699 return path, nil 700 } 701 702 func (interp *interpreter) setOptionField(mc *messageContext, msg protoreflect.Message, fld protoreflect.FieldDescriptor, name ast.Node, val ast.ValueNode) error { 703 v := val.Value() 704 if sl, ok := v.([]ast.ValueNode); ok { 705 // handle slices a little differently than the others 706 if fld.Cardinality() != protoreflect.Repeated { 707 return reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue is an array but field is not repeated", mc) 708 } 709 origPath := mc.optAggPath 710 defer func() { 711 mc.optAggPath = origPath 712 }() 713 for index, item := range sl { 714 mc.optAggPath = fmt.Sprintf("%s[%d]", origPath, index) 715 value, err := interp.fieldValue(mc, fld, item) 716 if err != nil { 717 return err 718 } 719 if fld.IsMap() { 720 entry := value.Message() 721 key := entry.Get(fld.MapKey()).MapKey() 722 val := entry.Get(fld.MapValue()) 723 if dm, ok := val.Interface().(*dynamicpb.Message); ok && (dm == nil || !dm.IsValid()) { 724 val = protoreflect.ValueOfMessage(newDynamic(fld.MapValue().Message())) 725 } 726 msg.Mutable(fld).Map().Set(key, val) 727 } else { 728 msg.Mutable(fld).List().Append(value) 729 } 730 } 731 return nil 732 } 733 734 value, err := interp.fieldValue(mc, fld, val) 735 if err != nil { 736 return err 737 } 738 739 if ood := fld.ContainingOneof(); ood != nil { 740 existingFld := msg.WhichOneof(ood) 741 if existingFld != nil && existingFld.Number() != fld.Number() { 742 return reporter.Errorf(interp.nodeInfo(name).Start(), "%voneof %q already has field %q set", mc, ood.Name(), fieldName(existingFld)) 743 } 744 } 745 746 if fld.IsMap() { 747 entry := value.Message() 748 key := entry.Get(fld.MapKey()).MapKey() 749 val := entry.Get(fld.MapValue()) 750 if dm, ok := val.Interface().(*dynamicpb.Message); ok && (dm == nil || !dm.IsValid()) { 751 val = protoreflect.ValueOfMessage(newDynamic(fld.MapValue().Message())) 752 } 753 msg.Mutable(fld).Map().Set(key, val) 754 } else if fld.IsList() { 755 msg.Mutable(fld).List().Append(value) 756 } else { 757 if msg.Has(fld) { 758 return reporter.Errorf(interp.nodeInfo(name).Start(), "%vnon-repeated option field %s already set", mc, fieldName(fld)) 759 } 760 msg.Set(fld, value) 761 } 762 763 return nil 764 } 765 766 type messageContext struct { 767 res parser.Result 768 file *descriptorpb.FileDescriptorProto 769 elementType string 770 elementName string 771 option *descriptorpb.UninterpretedOption 772 optAggPath string 773 } 774 775 func (c *messageContext) String() string { 776 var ctx bytes.Buffer 777 if c.elementType != "file" { 778 _, _ = fmt.Fprintf(&ctx, "%s %s: ", c.elementType, c.elementName) 779 } 780 if c.option != nil && c.option.Name != nil { 781 ctx.WriteString("option ") 782 writeOptionName(&ctx, c.option.Name) 783 if c.res.AST() == nil { 784 // if we have no source position info, try to provide as much context 785 // as possible (if nodes != nil, we don't need this because any errors 786 // will actually have file and line numbers) 787 if c.optAggPath != "" { 788 _, _ = fmt.Fprintf(&ctx, " at %s", c.optAggPath) 789 } 790 } 791 ctx.WriteString(": ") 792 } 793 return ctx.String() 794 } 795 796 func writeOptionName(buf *bytes.Buffer, parts []*descriptorpb.UninterpretedOption_NamePart) { 797 first := true 798 for _, p := range parts { 799 if first { 800 first = false 801 } else { 802 buf.WriteByte('.') 803 } 804 nm := p.GetNamePart() 805 if nm[0] == '.' { 806 // skip leading dot 807 nm = nm[1:] 808 } 809 if p.GetIsExtension() { 810 buf.WriteByte('(') 811 buf.WriteString(nm) 812 buf.WriteByte(')') 813 } else { 814 buf.WriteString(nm) 815 } 816 } 817 } 818 819 func fieldName(fld protoreflect.FieldDescriptor) string { 820 if fld.IsExtension() { 821 return fmt.Sprintf("(%s)", fld.FullName()) 822 } else { 823 return string(fld.Name()) 824 } 825 } 826 827 func valueKind(val interface{}) string { 828 switch val := val.(type) { 829 case ast.Identifier: 830 return "identifier" 831 case bool: 832 return "bool" 833 case int64: 834 if val < 0 { 835 return "negative integer" 836 } 837 return "integer" 838 case uint64: 839 return "integer" 840 case float64: 841 return "double" 842 case string, []byte: 843 return "string" 844 case []*ast.MessageFieldNode: 845 return "message" 846 case []ast.ValueNode: 847 return "array" 848 default: 849 return fmt.Sprintf("%T", val) 850 } 851 } 852 853 func (interp *interpreter) fieldValue(mc *messageContext, fld protoreflect.FieldDescriptor, val ast.ValueNode) (protoreflect.Value, error) { 854 k := fld.Kind() 855 switch k { 856 case protoreflect.EnumKind: 857 evd, err := interp.enumFieldValue(mc, fld.Enum(), val) 858 if err != nil { 859 return protoreflect.Value{}, err 860 } 861 return protoreflect.ValueOfEnum(evd.Number()), nil 862 863 case protoreflect.MessageKind, protoreflect.GroupKind: 864 v := val.Value() 865 if aggs, ok := v.([]*ast.MessageFieldNode); ok { 866 fmd := fld.Message() 867 fdm := newDynamic(fmd) 868 origPath := mc.optAggPath 869 defer func() { 870 mc.optAggPath = origPath 871 }() 872 for _, a := range aggs { 873 if origPath == "" { 874 mc.optAggPath = a.Name.Value() 875 } else { 876 mc.optAggPath = origPath + "." + a.Name.Value() 877 } 878 var ffld protoreflect.FieldDescriptor 879 if a.Name.IsExtension() { 880 n := string(a.Name.Name.AsIdentifier()) 881 ffld = interp.file.ResolveExtension(protoreflect.FullName(n)) 882 if ffld == nil { 883 // may need to qualify with package name 884 pkg := mc.file.GetPackage() 885 if pkg != "" { 886 ffld = interp.file.ResolveExtension(protoreflect.FullName(pkg + "." + n)) 887 } 888 } 889 } else { 890 ffld = fmd.Fields().ByName(protoreflect.Name(a.Name.Value())) 891 // Groups are indicated in the text format by the group name (which is 892 // camel-case), NOT the field name (which is lower-case). 893 // ...but only regular fields, not extensions that are groups... 894 if ffld != nil && ffld.Kind() == protoreflect.GroupKind && ffld.Message().Name() != protoreflect.Name(a.Name.Value()) { 895 // this is kind of silly to fail here, but this mimics protoc behavior 896 return protoreflect.Value{}, reporter.Errorf(interp.nodeInfo(val).Start(), "%vfield %s not found (did you mean the group named %s?)", mc, a.Name.Value(), ffld.Message().Name()) 897 } 898 if ffld == nil { 899 // could be a group name 900 for i := 0; i < fmd.Fields().Len(); i++ { 901 fd := fmd.Fields().Get(i) 902 if fd.Kind() == protoreflect.GroupKind && fd.Message().Name() == protoreflect.Name(a.Name.Value()) { 903 // found it! 904 ffld = fd 905 break 906 } 907 } 908 } 909 } 910 if ffld == nil { 911 return protoreflect.Value{}, reporter.Errorf(interp.nodeInfo(val).Start(), "%vfield %s not found", mc, string(a.Name.Name.AsIdentifier())) 912 } 913 if err := interp.setOptionField(mc, fdm, ffld, a.Name, a.Val); err != nil { 914 return protoreflect.Value{}, err 915 } 916 } 917 return protoreflect.ValueOfMessage(fdm), nil 918 } 919 return protoreflect.Value{}, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting message, got %s", mc, valueKind(v)) 920 921 default: 922 v, err := interp.scalarFieldValue(mc, descriptorpb.FieldDescriptorProto_Type(k), val) 923 if err != nil { 924 return protoreflect.Value{}, err 925 } 926 return protoreflect.ValueOf(v), nil 927 } 928 } 929 930 func (interp *interpreter) enumFieldValue(mc *messageContext, ed protoreflect.EnumDescriptor, val ast.ValueNode) (protoreflect.EnumValueDescriptor, error) { 931 v := val.Value() 932 if id, ok := v.(ast.Identifier); ok { 933 ev := ed.Values().ByName(protoreflect.Name(id)) 934 if ev == nil { 935 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%venum %s has no value named %s", mc, ed.FullName(), id) 936 } 937 return ev, nil 938 } 939 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting enum, got %s", mc, valueKind(v)) 940 } 941 942 func (interp *interpreter) scalarFieldValue(mc *messageContext, fldType descriptorpb.FieldDescriptorProto_Type, val ast.ValueNode) (interface{}, error) { 943 v := val.Value() 944 switch fldType { 945 case descriptorpb.FieldDescriptorProto_TYPE_BOOL: 946 if b, ok := v.(bool); ok { 947 return b, nil 948 } 949 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting bool, got %s", mc, valueKind(v)) 950 case descriptorpb.FieldDescriptorProto_TYPE_BYTES: 951 if str, ok := v.(string); ok { 952 return []byte(str), nil 953 } 954 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting bytes, got %s", mc, valueKind(v)) 955 case descriptorpb.FieldDescriptorProto_TYPE_STRING: 956 if str, ok := v.(string); ok { 957 return str, nil 958 } 959 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting string, got %s", mc, valueKind(v)) 960 case descriptorpb.FieldDescriptorProto_TYPE_INT32, descriptorpb.FieldDescriptorProto_TYPE_SINT32, descriptorpb.FieldDescriptorProto_TYPE_SFIXED32: 961 if i, ok := v.(int64); ok { 962 if i > math.MaxInt32 || i < math.MinInt32 { 963 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for int32", mc, i) 964 } 965 return int32(i), nil 966 } 967 if ui, ok := v.(uint64); ok { 968 if ui > math.MaxInt32 { 969 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for int32", mc, ui) 970 } 971 return int32(ui), nil 972 } 973 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting int32, got %s", mc, valueKind(v)) 974 case descriptorpb.FieldDescriptorProto_TYPE_UINT32, descriptorpb.FieldDescriptorProto_TYPE_FIXED32: 975 if i, ok := v.(int64); ok { 976 if i > math.MaxUint32 || i < 0 { 977 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for uint32", mc, i) 978 } 979 return uint32(i), nil 980 } 981 if ui, ok := v.(uint64); ok { 982 if ui > math.MaxUint32 { 983 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for uint32", mc, ui) 984 } 985 return uint32(ui), nil 986 } 987 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting uint32, got %s", mc, valueKind(v)) 988 case descriptorpb.FieldDescriptorProto_TYPE_INT64, descriptorpb.FieldDescriptorProto_TYPE_SINT64, descriptorpb.FieldDescriptorProto_TYPE_SFIXED64: 989 if i, ok := v.(int64); ok { 990 return i, nil 991 } 992 if ui, ok := v.(uint64); ok { 993 if ui > math.MaxInt64 { 994 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for int64", mc, ui) 995 } 996 return int64(ui), nil 997 } 998 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting int64, got %s", mc, valueKind(v)) 999 case descriptorpb.FieldDescriptorProto_TYPE_UINT64, descriptorpb.FieldDescriptorProto_TYPE_FIXED64: 1000 if i, ok := v.(int64); ok { 1001 if i < 0 { 1002 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for uint64", mc, i) 1003 } 1004 return uint64(i), nil 1005 } 1006 if ui, ok := v.(uint64); ok { 1007 return ui, nil 1008 } 1009 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting uint64, got %s", mc, valueKind(v)) 1010 case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE: 1011 if d, ok := v.(float64); ok { 1012 return d, nil 1013 } 1014 if i, ok := v.(int64); ok { 1015 return float64(i), nil 1016 } 1017 if u, ok := v.(uint64); ok { 1018 return float64(u), nil 1019 } 1020 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting double, got %s", mc, valueKind(v)) 1021 case descriptorpb.FieldDescriptorProto_TYPE_FLOAT: 1022 if d, ok := v.(float64); ok { 1023 if (d > math.MaxFloat32 || d < -math.MaxFloat32) && !math.IsInf(d, 1) && !math.IsInf(d, -1) && !math.IsNaN(d) { 1024 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %f is out of range for float", mc, d) 1025 } 1026 return float32(d), nil 1027 } 1028 if i, ok := v.(int64); ok { 1029 return float32(i), nil 1030 } 1031 if u, ok := v.(uint64); ok { 1032 return float32(u), nil 1033 } 1034 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting float, got %s", mc, valueKind(v)) 1035 default: 1036 return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vunrecognized field type: %s", mc, fldType) 1037 } 1038 } 1039 1040 func descriptorType(m proto.Message) string { 1041 switch m := m.(type) { 1042 case *descriptorpb.DescriptorProto: 1043 return "message" 1044 case *descriptorpb.DescriptorProto_ExtensionRange: 1045 return "extension range" 1046 case *descriptorpb.FieldDescriptorProto: 1047 if m.GetExtendee() == "" { 1048 return "field" 1049 } else { 1050 return "extension" 1051 } 1052 case *descriptorpb.EnumDescriptorProto: 1053 return "enum" 1054 case *descriptorpb.EnumValueDescriptorProto: 1055 return "enum value" 1056 case *descriptorpb.ServiceDescriptorProto: 1057 return "service" 1058 case *descriptorpb.MethodDescriptorProto: 1059 return "method" 1060 case *descriptorpb.FileDescriptorProto: 1061 return "file" 1062 default: 1063 // shouldn't be possible 1064 return fmt.Sprintf("%T", m) 1065 } 1066 }