Skip to content

Commit

Permalink
gofmt 1.19; add support for v2 extendable messages in *dynamic.Message (
Browse files Browse the repository at this point in the history
#533)

Also includes some cleanup to remove reflective code paths that can now safely directly access newer fields
  • Loading branch information
jhump committed Sep 28, 2022
1 parent bccb0aa commit 101791c
Show file tree
Hide file tree
Showing 26 changed files with 393 additions and 452 deletions.
100 changes: 47 additions & 53 deletions desc/builder/doc.go
Expand Up @@ -3,8 +3,7 @@
// new descriptors as are there methods for converting existing descriptors into
// builders, for modification.
//
//
// Factory Functions
// # Factory Functions
//
// Builders are created using the numerous factory functions. Each type of
// descriptor has two kinds of factory functions for the corresponding type of
Expand All @@ -26,8 +25,7 @@
// nil values for required fields (such as field types, RPC method types, and
// extendee type for extensions).
//
//
// Auto-Assigning Tag Numbers and File Names
// # Auto-Assigning Tag Numbers and File Names
//
// The factory function for fields does not accept a tag number. This is because
// tags, for fields where none is set or is explicitly set to zero, are
Expand All @@ -48,8 +46,7 @@
// can have their tags auto-assigned. If an extension is constructed with a zero
// tag (which is not valid), the factory function will panic.
//
//
// Descriptor Hierarchy
// # Descriptor Hierarchy
//
// The hierarchy for builders is mutable. A descriptor builder, such as a field,
// can be moved from one message to another. When this is done, the field is
Expand All @@ -59,10 +56,10 @@
// can simply be copied. This allows for copying a descriptor from one parent to
// another, like so:
//
// msg := builder.FromMessage(someMsgDesc)
// field1 := msg.GetField("foo")
// field2 := *field1 // field2 is now a copy
// otherMsg.AddField(&field2)
// msg := builder.FromMessage(someMsgDesc)
// field1 := msg.GetField("foo")
// field2 := *field1 // field2 is now a copy
// otherMsg.AddField(&field2)
//
// All descriptors have a link up the hierarchy to the file in which they were
// declared. However, it is *not* necessary to construct this full hierarchy
Expand All @@ -80,22 +77,21 @@
// unnamed) package. In order to put descriptors into a proper package
// namespace, they must be added to a file that has the right package name.
//
//
// Builder Pattern and Method Chaining
// # Builder Pattern and Method Chaining
//
// Each descriptor has some special fields that can only be updated via a Set*
// method. They also all have some exported fields that can be updated by just
// assigning to the field. But even exported fields have accompanying Set*
// methods in order to support a typical method-chaining flow when building
// objects:
//
// msg, err := builder.NewMessage("MyMessage").
// AddField(NewField("foo", FieldTypeScalar(descriptor.FieldDescriptorProto_TYPE_STRING)).
// SetDefaultValue("bar")).
// AddField(NewField("baz", FieldTypeScalar(descriptor.FieldDescriptorProto_TYPE_INT64)).
// SetLabel(descriptor.FieldDescriptorProto_LABEL_REPEATED).
// SetOptions(&descriptor.FieldOptions{Packed: proto.Bool(true)})).
// Build()
// msg, err := builder.NewMessage("MyMessage").
// AddField(NewField("foo", FieldTypeScalar(descriptor.FieldDescriptorProto_TYPE_STRING)).
// SetDefaultValue("bar")).
// AddField(NewField("baz", FieldTypeScalar(descriptor.FieldDescriptorProto_TYPE_INT64)).
// SetLabel(descriptor.FieldDescriptorProto_LABEL_REPEATED).
// SetOptions(&descriptor.FieldOptions{Packed: proto.Bool(true)})).
// Build()
//
// So the various Set* methods all return the builder itself so that multiple
// fields may be set in a single invocation chain.
Expand All @@ -104,8 +100,7 @@
// can return an error if validation fails. If the method-chaining Set* form is
// used with inputs that fail validation, the Set* method will panic.
//
//
// Type References and Imported Types
// # Type References and Imported Types
//
// When defining fields whose type is a message or enum and when defining
// methods (whose request and response type are a message), the type can be set
Expand All @@ -128,8 +123,7 @@
// imports the other). And the same would be true if one or both files were
// explicitly assigned to a file, but not both to the same file.
//
//
// Validations and Caveats
// # Validations and Caveats
//
// Descriptors that are attained from a builder do not necessarily represent a
// valid construct in the proto source language. There are some validations
Expand All @@ -153,40 +147,40 @@
// in errors (or panics for factory functions and methods that do not return
// errors). These are the rules that are currently enforced:
//
// 1. Import cycles are not allowed. (See above for more details.)
// 2. Within a single file, symbols are not allowed to have naming conflicts.
// This means that is not legal to create a message and an extension with
// the same name in the same file.
// 3. Messages are not allowed to have multiple fields with the same tag. Note
// that only non-extension fields are checked when using builders. So
// builders will allow tag collisions for extensions. (Use caution.)
// 4. Map keys can only be integer types, booleans, and strings.
// 5. Fields cannot have tags in the special reserved range 19000-19999. Also
// the maximum allowed tag value is 536870911 (2^29 - 1). Finally, fields
// cannot have negative values.
// 6. Element names should include only underscore, letters, and numbers, and
// must begin with an underscore or letter.
// 1. Import cycles are not allowed. (See above for more details.)
// 2. Within a single file, symbols are not allowed to have naming conflicts.
// This means that is not legal to create a message and an extension with
// the same name in the same file.
// 3. Messages are not allowed to have multiple fields with the same tag. Note
// that only non-extension fields are checked when using builders. So
// builders will allow tag collisions for extensions. (Use caution.)
// 4. Map keys can only be integer types, booleans, and strings.
// 5. Fields cannot have tags in the special reserved range 19000-19999. Also
// the maximum allowed tag value is 536870911 (2^29 - 1). Finally, fields
// cannot have negative values.
// 6. Element names should include only underscore, letters, and numbers, and
// must begin with an underscore or letter.
//
// Validation rules that are *not* enforced by builders, and thus would be
// allowed and result in illegal constructs, include the following:
//
// 1. Files with a syntax of proto3 are not allowed to have required fields.
// 2. Files with a syntax of proto3 are not allowed to have messages that
// define extension ranges.
// 3. Files with a syntax of proto3 are not allowed to use groups.
// 4. Files with a syntax of proto3 are not allowed to declare default values
// for fields.
// 5. Names are supposed to be globally unique, even across multiple files
// if multiple files are defined in the same package.
// 6. Extension fields must use tag numbers that are in an extension range
// defined on the extended message.
// 7. Multiple extensions for the same message cannot re-use tag numbers, even
// across multiple files.
// 8. Non-extension fields are not allowed to use tags that lie in a message's
// extension ranges or reserved ranges.
// 9. Non-extension fields are not allowed to use names that the message has
// marked as reserved.
// 10. Extension ranges and reserved ranges must not overlap.
// 1. Files with a syntax of proto3 are not allowed to have required fields.
// 2. Files with a syntax of proto3 are not allowed to have messages that
// define extension ranges.
// 3. Files with a syntax of proto3 are not allowed to use groups.
// 4. Files with a syntax of proto3 are not allowed to declare default values
// for fields.
// 5. Names are supposed to be globally unique, even across multiple files
// if multiple files are defined in the same package.
// 6. Extension fields must use tag numbers that are in an extension range
// defined on the extended message.
// 7. Multiple extensions for the same message cannot re-use tag numbers, even
// across multiple files.
// 8. Non-extension fields are not allowed to use tags that lie in a message's
// extension ranges or reserved ranges.
// 9. Non-extension fields are not allowed to use names that the message has
// marked as reserved.
// 10. Extension ranges and reserved ranges must not overlap.
//
// This list may change in the future, as more validation rules may be
// implemented in the builders.
Expand Down
27 changes: 15 additions & 12 deletions desc/builder/field.go
Expand Up @@ -538,19 +538,22 @@ func (flb *FieldBuilder) buildProto(path []int32, sourceInfo *dpb.SourceCodeInfo
return nil, fmt.Errorf("tag for field %s cannot be above max %d", GetFullyQualifiedName(flb), maxTag)
}

fd := &dpb.FieldDescriptorProto{
Name: proto.String(flb.name),
Number: proto.Int32(flb.number),
Options: flb.Options,
Label: lbl,
Type: flb.fieldType.fieldType.Enum(),
TypeName: typeName,
JsonName: proto.String(jsName),
DefaultValue: def,
Extendee: extendee,
}
var proto3Optional *bool
if flb.Proto3Optional {
internal.SetProto3Optional(fd)
proto3Optional = proto.Bool(true)
}

fd := &dpb.FieldDescriptorProto{
Name: proto.String(flb.name),
Number: proto.Int32(flb.number),
Options: flb.Options,
Label: lbl,
Type: flb.fieldType.fieldType.Enum(),
TypeName: typeName,
JsonName: proto.String(jsName),
DefaultValue: def,
Extendee: extendee,
Proto3Optional: proto3Optional,
}
return fd, nil
}
Expand Down
6 changes: 4 additions & 2 deletions desc/convert.go
Expand Up @@ -160,7 +160,8 @@ func addAllFiles(src []*FileDescriptor, results *[]*dpb.FileDescriptorProto, see
// set's *last* file will be the returned descriptor. The set's remaining files must comprise
// the full set of transitive dependencies of that last file. This is the same format and
// order used by protoc when emitting a FileDescriptorSet file with an invocation like so:
// protoc --descriptor_set_out=./test.protoset --include_imports -I. test.proto
//
// protoc --descriptor_set_out=./test.protoset --include_imports -I. test.proto
func CreateFileDescriptorFromSet(fds *dpb.FileDescriptorSet) (*FileDescriptor, error) {
return createFileDescriptorFromSet(fds, nil)
}
Expand All @@ -180,7 +181,8 @@ func createFileDescriptorFromSet(fds *dpb.FileDescriptorSet, r *ImportResolver)
// full set of transitive dependencies for all files therein or else a link error will occur
// and be returned instead of the slice of descriptors. This is the same format used by
// protoc when a FileDescriptorSet file with an invocation like so:
// protoc --descriptor_set_out=./test.protoset --include_imports -I. test.proto
//
// protoc --descriptor_set_out=./test.protoset --include_imports -I. test.proto
func CreateFileDescriptorsFromSet(fds *dpb.FileDescriptorSet) (map[string]*FileDescriptor, error) {
return createFileDescriptorsFromSet(fds, nil)
}
Expand Down
29 changes: 15 additions & 14 deletions desc/descriptor.go
Expand Up @@ -1040,7 +1040,7 @@ func (fd *FieldDescriptor) IsRepeated() bool {
// extensions), will be nested in synthetic oneofs that contain only the single
// field.
func (fd *FieldDescriptor) IsProto3Optional() bool {
return internal.GetProto3Optional(fd.proto)
return fd.proto.GetProto3Optional()
}

// HasPresence returns true if this field can distinguish when a value is
Expand Down Expand Up @@ -1101,19 +1101,20 @@ func (fd *FieldDescriptor) GetEnumType() *EnumDescriptor {
// Otherwise, it returns the declared default value for the field or a zero value, if no
// default is declared or if the file is proto3. The type of said return value corresponds
// to the type of the field:
// +-------------------------+-----------+
// | Declared Type | Go Type |
// +-------------------------+-----------+
// | int32, sint32, sfixed32 | int32 |
// | int64, sint64, sfixed64 | int64 |
// | uint32, fixed32 | uint32 |
// | uint64, fixed64 | uint64 |
// | float | float32 |
// | double | double32 |
// | bool | bool |
// | string | string |
// | bytes | []byte |
// +-------------------------+-----------+
//
// +-------------------------+-----------+
// | Declared Type | Go Type |
// +-------------------------+-----------+
// | int32, sint32, sfixed32 | int32 |
// | int64, sint64, sfixed64 | int64 |
// | uint32, fixed32 | uint32 |
// | uint64, fixed64 | uint64 |
// | float | float32 |
// | double | double32 |
// | bool | bool |
// | string | string |
// | bytes | []byte |
// +-------------------------+-----------+
func (fd *FieldDescriptor) GetDefaultValue() interface{} {
return fd.getDefaultValue()
}
Expand Down
7 changes: 2 additions & 5 deletions desc/doc.go
Expand Up @@ -27,8 +27,7 @@
// Also see the grpcreflect, dynamic, and grpcdynamic packages in this same
// repo to see just how useful rich descriptors really are.
//
//
// Loading Descriptors
// # Loading Descriptors
//
// Rich descriptors can be accessed in similar ways as their "poor" cousins
// (descriptor protos). Instead of using proto.FileDescriptor, use
Expand All @@ -40,8 +39,7 @@
// the descriptors returned from these Load* functions will include source code
// information, and thus include comments for elements.
//
//
// Creating Descriptors
// # Creating Descriptors
//
// It is also possible create rich descriptors for proto messages that a given
// Go program doesn't even know about. For example, they could be loaded from a
Expand All @@ -61,5 +59,4 @@
//
// Also see the desc/builder sub-package, for another API that makes it easier
// to synthesize descriptors programmatically.
//
package desc
26 changes: 16 additions & 10 deletions desc/imports.go
Expand Up @@ -76,25 +76,31 @@ func ResolveImport(importPath string) string {
//
// For example, let's say we have two proto source files: "foo/bar.proto" and
// "fubar/baz.proto". The latter imports the former using a line like so:
// import "foo/bar.proto";
//
// import "foo/bar.proto";
//
// However, when protoc is invoked, the command-line args looks like so:
// protoc -Ifoo/ --go_out=foo/ bar.proto
// protoc -I./ -Ifubar/ --go_out=fubar/ baz.proto
//
// protoc -Ifoo/ --go_out=foo/ bar.proto
// protoc -I./ -Ifubar/ --go_out=fubar/ baz.proto
//
// Because the path given to protoc is just "bar.proto" and "baz.proto", this is
// how they are registered in the Go protobuf runtime. So, when loading the
// descriptor for "fubar/baz.proto", we'll see an import path of "foo/bar.proto"
// but will find no file registered with that path:
// fd, err := desc.LoadFileDescriptor("baz.proto")
// // err will be non-nil, complaining that there is no such file
// // found named "foo/bar.proto"
//
// fd, err := desc.LoadFileDescriptor("baz.proto")
// // err will be non-nil, complaining that there is no such file
// // found named "foo/bar.proto"
//
// This can be remedied by registering alternate import paths using an
// ImportResolver. Continuing with the example above, the code below would fix
// any link issue:
// var r desc.ImportResolver
// r.RegisterImportPath("bar.proto", "foo/bar.proto")
// fd, err := r.LoadFileDescriptor("baz.proto")
// // err will be nil; descriptor successfully loaded!
//
// var r desc.ImportResolver
// r.RegisterImportPath("bar.proto", "foo/bar.proto")
// fd, err := r.LoadFileDescriptor("baz.proto")
// // err will be nil; descriptor successfully loaded!
//
// If there are files that are *always* imported using a different relative
// path then how they are registered, consider using the global
Expand Down

0 comments on commit 101791c

Please sign in to comment.