Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
7aab46c
Add exclude_options configuration for generation
emcfarlane Feb 5, 2025
e2608aa
Fix lint issues and file iter
emcfarlane Feb 7, 2025
d05d210
Use protoreflect for remapping
emcfarlane Feb 12, 2025
5940c75
Remap dependencies
emcfarlane Feb 12, 2025
f763966
Refactor for image filtering
emcfarlane Feb 14, 2025
4935430
Refactor for include and exclude of types
emcfarlane Feb 24, 2025
400f958
Fix handling of extensions
emcfarlane Feb 25, 2025
2a66cf2
Fix import types
emcfarlane Feb 25, 2025
2c4378d
Fix extension inclusions
emcfarlane Feb 25, 2025
a0b373e
Checkpoint
emcfarlane Feb 26, 2025
11a88a9
Refactor for transitive closure
emcfarlane Feb 27, 2025
99902e6
Cleanup testcase
emcfarlane Feb 27, 2025
b5b7daa
Cleanup
emcfarlane Feb 27, 2025
e2c5f8b
Fix import dropping for options
emcfarlane Feb 27, 2025
8e286f4
Fix build
emcfarlane Feb 27, 2025
cb5a8ee
Mutate in place
emcfarlane Feb 27, 2025
00ebe13
Add mutate in place option
emcfarlane Feb 27, 2025
20b720b
Update docs
emcfarlane Feb 28, 2025
3cec9b8
Fix generation per image
emcfarlane Mar 3, 2025
5997223
Cleanup
emcfarlane Mar 3, 2025
764626a
Cleanup
emcfarlane Mar 3, 2025
dc449ef
Remove gosec workarounds
emcfarlane Mar 3, 2025
90cc4a0
Cleanup
emcfarlane Mar 3, 2025
cffd97c
Remove pointers from trailing slice
emcfarlane Mar 4, 2025
b460387
Drop extension TODO
emcfarlane Mar 4, 2025
e531a7a
Add types and options for inputs and plugins
emcfarlane Mar 7, 2025
2a2017a
Sort key parts
emcfarlane Mar 10, 2025
49cf91c
Only exclusion of types
emcfarlane Mar 11, 2025
07ea2e0
Docs
emcfarlane Mar 11, 2025
c43b74e
Remove inclusion of extension restriction
emcfarlane Mar 11, 2025
347120a
Merge branch 'main' into ed/excludeOptions
emcfarlane Mar 11, 2025
d66e197
Add exclude-types flag
emcfarlane Mar 11, 2025
883527c
Add CHANGELOG
emcfarlane Mar 11, 2025
5decf0b
Add testcases
emcfarlane Mar 11, 2025
e07f2b7
Fix lint
emcfarlane Mar 11, 2025
a3f2055
Cleanup
emcfarlane Mar 11, 2025
b8ed6d7
Cleanup
emcfarlane Mar 11, 2025
cbfb29f
Cleanup
emcfarlane Mar 11, 2025
13c3882
Use slices.Backward
emcfarlane Mar 14, 2025
3124c00
Improve generator key
emcfarlane Mar 14, 2025
eaf49d2
Fix unused deps
emcfarlane Mar 17, 2025
59f5d78
Add unused deps testcase
emcfarlane Mar 17, 2025
07152c5
Fix changelog
emcfarlane Mar 17, 2025
bf07344
Merge branch 'main' into ed/excludeOptions
emcfarlane Mar 17, 2025
cd43600
Fix mutate in place source code locations
emcfarlane Mar 18, 2025
f291c2a
Update docs
emcfarlane Mar 18, 2025
e78e983
Fix name pluginConfigForKey
emcfarlane Mar 19, 2025
e39dddd
Fix pluginConfig ref for local job
emcfarlane Mar 19, 2025
56c5fda
Fix indexedPluginConfig consistency
emcfarlane Mar 19, 2025
9a80424
Update --exclude-types comment
emcfarlane Mar 19, 2025
60dbf41
Remove dead comment
emcfarlane Mar 19, 2025
a57873e
Clarify test comment
emcfarlane Mar 19, 2025
986a33f
Use IncludeTypes
emcfarlane Mar 19, 2025
e7de3e8
Clarify input config ExcludeType docs
emcfarlane Mar 19, 2025
d7849e1
Remove options == nil checks
emcfarlane Mar 19, 2025
62dc5d4
Move exclude set
emcfarlane Mar 19, 2025
4c75c24
Move TODO for globs
emcfarlane Mar 19, 2025
cd9d8a1
Improve excludeElement extendee check
emcfarlane Mar 19, 2025
219ff4b
Clarify hasOption on unknown types
emcfarlane Mar 19, 2025
c20a21c
Doc check is import used
emcfarlane Mar 19, 2025
9e8f745
TODO for better enclosing isDirty check
emcfarlane Mar 19, 2025
bc52487
Clarify input config docs for ExcludeTypes
emcfarlane Mar 19, 2025
7b12e98
Do TODO for enclosingType
emcfarlane Mar 19, 2025
5035d61
Simplify default check
emcfarlane Mar 19, 2025
12ce214
Fix include method but exclude input or output
emcfarlane Mar 20, 2025
f5cfcd5
Fix empty oneofs
emcfarlane Mar 20, 2025
01f7b09
Fix spacing
emcfarlane Mar 20, 2025
f5398e5
Cleanup
emcfarlane Mar 20, 2025
62b4402
Check extendee valid for extension inclusions
emcfarlane Mar 20, 2025
1696cca
Use IncludeTypes naming
emcfarlane Mar 20, 2025
584bde7
Use includeTypes names
emcfarlane Mar 20, 2025
1585379
Merge branch 'main' into ed/excludeOptions
emcfarlane Mar 25, 2025
304f0af
Set options as unrecognized bytes
emcfarlane Mar 25, 2025
698e350
Revert "Set options as unrecognized bytes"
emcfarlane Mar 25, 2025
d57a7d9
Move import check to closure
emcfarlane Mar 27, 2025
7b1f6bf
Fix docs
emcfarlane Mar 27, 2025
d327c23
Add range check
emcfarlane Mar 27, 2025
b4c1f56
Remove options remap
emcfarlane Mar 27, 2025
b6a92ee
Remap depencies to catch changes
emcfarlane Mar 28, 2025
412b940
Fix race on bufimage.NewImageForProto
emcfarlane Mar 28, 2025
c6b0e6a
Fix source paths remaps for deps
emcfarlane Mar 28, 2025
3c13e37
Format testdata
emcfarlane Mar 28, 2025
1c78fc9
Test consecutive fitlers
emcfarlane Mar 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion private/bufpkg/bufimage/bufimageutil/bufimageutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ func (t *transitiveClosure) addElement(
}

case *descriptorpb.DescriptorProto:
oneofFieldCounts := make([]int, len(typedDescriptor.GetOneofDecl()))
// Options and types for all fields
for _, field := range typedDescriptor.GetField() {
isIncluded, err := t.addFieldType(field, descriptorInfo.file.Path(), imageIndex, opts)
Expand All @@ -452,12 +453,21 @@ func (t *transitiveClosure) addElement(
if !isIncluded {
continue
}
if index := field.OneofIndex; index != nil {
oneofFieldCounts[*index]++
}
if err := t.exploreCustomOptions(field, referrerFile, imageIndex, opts); err != nil {
return err
}
}
// Options for all oneofs in this message
for _, oneOfDescriptor := range typedDescriptor.GetOneofDecl() {
for index, oneOfDescriptor := range typedDescriptor.GetOneofDecl() {
if oneofFieldCounts[index] == 0 {
// An empty oneof is not a valid protobuf construct, so we can
// safely exclude it.
t.elements[oneOfDescriptor] = inclusionModeExcluded
continue
}
if err := t.exploreCustomOptions(oneOfDescriptor, descriptorInfo.file.Path(), imageIndex, opts); err != nil {
return err
}
Expand Down
12 changes: 12 additions & 0 deletions private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,18 @@ func TestNesting(t *testing.T) {
})
}

func TestOneof(t *testing.T) {
t.Parallel()
t.Run("exclude-partial", func(t *testing.T) {
t.Parallel()
runDiffTest(t, "testdata/oneofs", "pkg.Foo.exclude-partial.txtar", WithIncludeTypes("pkg.Foo"), WithExcludeTypes("pkg.FooEnum", "pkg.Bar.BarNested"))
})
t.Run("exclude-bar", func(t *testing.T) {
t.Parallel()
runDiffTest(t, "testdata/oneofs", "pkg.Foo.exclude-bar.txtar", WithIncludeTypes("pkg.Foo"), WithExcludeTypes("pkg.FooEnum", "pkg.Bar"))
})
}

func TestOptions(t *testing.T) {
t.Parallel()
t.Run("include_option", func(t *testing.T) {
Expand Down
4 changes: 4 additions & 0 deletions private/bufpkg/bufimage/bufimageutil/image_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,10 @@ func (b *sourcePathsBuilder) remapOneof(
sourcePath protoreflect.SourcePath,
oneof *descriptorpb.OneofDescriptorProto,
) (*descriptorpb.OneofDescriptorProto, bool, error) {
if mode, ok := b.closure.elements[oneof]; ok && mode == inclusionModeExcluded {
// Oneofs can be explicitly excluded when all fields for it are excluded.
return nil, true, nil
}
options, changed, err := remapMessage(nil, append(sourcePath, oneofOptionsTag), oneof.GetOptions(), b.remapOptions)
if err != nil {
return nil, false, err
Expand Down
31 changes: 31 additions & 0 deletions private/bufpkg/bufimage/bufimageutil/testdata/oneofs/a.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
syntax = "proto3";
package pkg;
import "google/protobuf/descriptor.proto";

message Foo {
oneof oneofFoo {
option (oneof_foo) = "str";
string foo = 1;
FooEnum foo_enum = 2;
}
oneof oneofBar {
option (oneof_bar) = "str";
Bar bar = 3;
Bar.BarNested bar_nested = 4;
}
}

enum FooEnum {
FOO_ENUM_X = 0;
FOO_ENUM_Y = 1;
}
message Bar {
string bar = 1;
message BarNested {
string bar = 1;
}
}
extend google.protobuf.OneofOptions {
optional string oneof_foo = 50000;
optional string oneof_bar = 50001;
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
-- a.proto --
syntax = "proto3";
package pkg;
import "google/protobuf/descriptor.proto";
message Foo {
oneof oneofFoo {
option (oneof_foo) = "str";
string foo = 1;
}
}
extend google.protobuf.OneofOptions {
string oneof_foo = 50000;
}
-- google/protobuf/descriptor.proto --
syntax = "proto2";
package google.protobuf;
option cc_enable_arenas = true;
option csharp_namespace = "Google.Protobuf.Reflection";
option go_package = "google.golang.org/protobuf/types/descriptorpb";
option java_outer_classname = "DescriptorProtos";
option java_package = "com.google.protobuf";
option objc_class_prefix = "GPB";
option optimize_for = SPEED;
message FeatureSet {
optional FieldPresence field_presence = 1 [
edition_defaults = { value: "EXPLICIT", edition: EDITION_LEGACY },
edition_defaults = { value: "IMPLICIT", edition: EDITION_PROTO3 },
edition_defaults = { value: "EXPLICIT", edition: EDITION_2023 },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_FIELD,
targets = TARGET_TYPE_FILE
];
optional EnumType enum_type = 2 [
edition_defaults = { value: "CLOSED", edition: EDITION_LEGACY },
edition_defaults = { value: "OPEN", edition: EDITION_PROTO3 },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_ENUM,
targets = TARGET_TYPE_FILE
];
optional RepeatedFieldEncoding repeated_field_encoding = 3 [
edition_defaults = { value: "EXPANDED", edition: EDITION_LEGACY },
edition_defaults = { value: "PACKED", edition: EDITION_PROTO3 },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_FIELD,
targets = TARGET_TYPE_FILE
];
optional Utf8Validation utf8_validation = 4 [
edition_defaults = { value: "NONE", edition: EDITION_LEGACY },
edition_defaults = { value: "VERIFY", edition: EDITION_PROTO3 },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_FIELD,
targets = TARGET_TYPE_FILE
];
optional MessageEncoding message_encoding = 5 [
edition_defaults = { value: "LENGTH_PREFIXED", edition: EDITION_LEGACY },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_FIELD,
targets = TARGET_TYPE_FILE
];
optional JsonFormat json_format = 6 [
edition_defaults = { value: "LEGACY_BEST_EFFORT", edition: EDITION_LEGACY },
edition_defaults = { value: "ALLOW", edition: EDITION_PROTO3 },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_MESSAGE,
targets = TARGET_TYPE_ENUM,
targets = TARGET_TYPE_FILE
];
enum EnumType {
ENUM_TYPE_UNKNOWN = 0;
OPEN = 1;
CLOSED = 2;
}
enum FieldPresence {
FIELD_PRESENCE_UNKNOWN = 0;
EXPLICIT = 1;
IMPLICIT = 2;
LEGACY_REQUIRED = 3;
}
enum JsonFormat {
JSON_FORMAT_UNKNOWN = 0;
ALLOW = 1;
LEGACY_BEST_EFFORT = 2;
}
enum MessageEncoding {
MESSAGE_ENCODING_UNKNOWN = 0;
LENGTH_PREFIXED = 1;
DELIMITED = 2;
}
enum RepeatedFieldEncoding {
REPEATED_FIELD_ENCODING_UNKNOWN = 0;
PACKED = 1;
EXPANDED = 2;
}
enum Utf8Validation {
UTF8_VALIDATION_UNKNOWN = 0;
VERIFY = 2;
NONE = 3;
reserved 1;
}
extensions 1000 to 9994 [
declaration = {
number: 1000,
full_name: ".pb.cpp",
type: ".pb.CppFeatures"
},
declaration = {
number: 1001,
full_name: ".pb.java",
type: ".pb.JavaFeatures"
},
declaration = {
number: 1002,
full_name: ".pb.go",
type: ".pb.GoFeatures"
},
declaration = {
number: 9990,
full_name: ".pb.proto1",
type: ".pb.Proto1Features"
}
];
extensions 9995 to 9999, 10000;
reserved 999;
}
message OneofOptions {
optional FeatureSet features = 1;
repeated UninterpretedOption uninterpreted_option = 999;
extensions 1000 to max;
}
message UninterpretedOption {
repeated NamePart name = 2;
optional string identifier_value = 3;
optional uint64 positive_int_value = 4;
optional int64 negative_int_value = 5;
optional double double_value = 6;
optional bytes string_value = 7;
optional string aggregate_value = 8;
message NamePart {
required string name_part = 1;
required bool is_extension = 2;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
-- a.proto --
syntax = "proto3";
package pkg;
import "google/protobuf/descriptor.proto";
message Bar {
string bar = 1;
}
message Foo {
oneof oneofFoo {
option (oneof_foo) = "str";
string foo = 1;
}
oneof oneofBar {
option (oneof_bar) = "str";
Bar bar = 3;
}
}
extend google.protobuf.OneofOptions {
string oneof_foo = 50000;
string oneof_bar = 50001;
}
-- google/protobuf/descriptor.proto --
syntax = "proto2";
package google.protobuf;
option cc_enable_arenas = true;
option csharp_namespace = "Google.Protobuf.Reflection";
option go_package = "google.golang.org/protobuf/types/descriptorpb";
option java_outer_classname = "DescriptorProtos";
option java_package = "com.google.protobuf";
option objc_class_prefix = "GPB";
option optimize_for = SPEED;
message FeatureSet {
optional FieldPresence field_presence = 1 [
edition_defaults = { value: "EXPLICIT", edition: EDITION_LEGACY },
edition_defaults = { value: "IMPLICIT", edition: EDITION_PROTO3 },
edition_defaults = { value: "EXPLICIT", edition: EDITION_2023 },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_FIELD,
targets = TARGET_TYPE_FILE
];
optional EnumType enum_type = 2 [
edition_defaults = { value: "CLOSED", edition: EDITION_LEGACY },
edition_defaults = { value: "OPEN", edition: EDITION_PROTO3 },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_ENUM,
targets = TARGET_TYPE_FILE
];
optional RepeatedFieldEncoding repeated_field_encoding = 3 [
edition_defaults = { value: "EXPANDED", edition: EDITION_LEGACY },
edition_defaults = { value: "PACKED", edition: EDITION_PROTO3 },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_FIELD,
targets = TARGET_TYPE_FILE
];
optional Utf8Validation utf8_validation = 4 [
edition_defaults = { value: "NONE", edition: EDITION_LEGACY },
edition_defaults = { value: "VERIFY", edition: EDITION_PROTO3 },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_FIELD,
targets = TARGET_TYPE_FILE
];
optional MessageEncoding message_encoding = 5 [
edition_defaults = { value: "LENGTH_PREFIXED", edition: EDITION_LEGACY },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_FIELD,
targets = TARGET_TYPE_FILE
];
optional JsonFormat json_format = 6 [
edition_defaults = { value: "LEGACY_BEST_EFFORT", edition: EDITION_LEGACY },
edition_defaults = { value: "ALLOW", edition: EDITION_PROTO3 },
feature_support = { edition_introduced: EDITION_2023 },
retention = RETENTION_RUNTIME,
targets = TARGET_TYPE_MESSAGE,
targets = TARGET_TYPE_ENUM,
targets = TARGET_TYPE_FILE
];
enum EnumType {
ENUM_TYPE_UNKNOWN = 0;
OPEN = 1;
CLOSED = 2;
}
enum FieldPresence {
FIELD_PRESENCE_UNKNOWN = 0;
EXPLICIT = 1;
IMPLICIT = 2;
LEGACY_REQUIRED = 3;
}
enum JsonFormat {
JSON_FORMAT_UNKNOWN = 0;
ALLOW = 1;
LEGACY_BEST_EFFORT = 2;
}
enum MessageEncoding {
MESSAGE_ENCODING_UNKNOWN = 0;
LENGTH_PREFIXED = 1;
DELIMITED = 2;
}
enum RepeatedFieldEncoding {
REPEATED_FIELD_ENCODING_UNKNOWN = 0;
PACKED = 1;
EXPANDED = 2;
}
enum Utf8Validation {
UTF8_VALIDATION_UNKNOWN = 0;
VERIFY = 2;
NONE = 3;
reserved 1;
}
extensions 1000 to 9994 [
declaration = {
number: 1000,
full_name: ".pb.cpp",
type: ".pb.CppFeatures"
},
declaration = {
number: 1001,
full_name: ".pb.java",
type: ".pb.JavaFeatures"
},
declaration = {
number: 1002,
full_name: ".pb.go",
type: ".pb.GoFeatures"
},
declaration = {
number: 9990,
full_name: ".pb.proto1",
type: ".pb.Proto1Features"
}
];
extensions 9995 to 9999, 10000;
reserved 999;
}
message OneofOptions {
optional FeatureSet features = 1;
repeated UninterpretedOption uninterpreted_option = 999;
extensions 1000 to max;
}
message UninterpretedOption {
repeated NamePart name = 2;
optional string identifier_value = 3;
optional uint64 positive_int_value = 4;
optional int64 negative_int_value = 5;
optional double double_value = 6;
optional bytes string_value = 7;
optional string aggregate_value = 8;
message NamePart {
required string name_part = 1;
required bool is_extension = 2;
}
}