From 180c6ba15fd86fa95371aef2b39516b128d98b8d Mon Sep 17 00:00:00 2001 From: Josh Humphries <2035234+jhump@users.noreply.github.com> Date: Fri, 6 Feb 2026 13:38:43 -0500 Subject: [PATCH 1/4] fix references to renamed function --- .../bufimage/bufimageutil/bufimageutil.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/private/bufpkg/bufimage/bufimageutil/bufimageutil.go b/private/bufpkg/bufimage/bufimageutil/bufimageutil.go index 6a264ee513..73310e3eb7 100644 --- a/private/bufpkg/bufimage/bufimageutil/bufimageutil.go +++ b/private/bufpkg/bufimage/bufimageutil/bufimageutil.go @@ -35,11 +35,11 @@ const ( ) var ( - // ErrImageFilterTypeNotFound is returned from ImageFilteredByTypes when + // ErrImageFilterTypeNotFound is returned from FilterImage when // a specified type cannot be found in an image. ErrImageFilterTypeNotFound = errors.New("not found") - // ErrImageFilterTypeIsImport is returned from ImageFilteredByTypes when + // ErrImageFilterTypeIsImport is returned from FilterImage when // a specified type name is declared in a module dependency. ErrImageFilterTypeIsImport = errors.New("type declared in imported module") ) @@ -69,11 +69,11 @@ func FreeMessageRangeStrings( return s, nil } -// ImageFilterOption is an option that can be passed to ImageFilteredByTypesWithOptions. +// ImageFilterOption is an option that can be passed to FilterImage. type ImageFilterOption func(*imageFilterOptions) // WithExcludeCustomOptions returns an option that will cause an image filtered via -// ImageFilteredByTypesWithOptions to *not* include custom options unless they are +// FilterImage to *not* include custom options unless they are // explicitly named in the list of filter types. func WithExcludeCustomOptions() ImageFilterOption { return func(opts *imageFilterOptions) { @@ -82,7 +82,7 @@ func WithExcludeCustomOptions() ImageFilterOption { } // WithExcludeKnownExtensions returns an option that will cause an image filtered via -// ImageFilteredByTypesWithOptions to *not* include the known extensions for included +// FilterImage to *not* include the known extensions for included // extendable messages unless they are explicitly named in the list of filter types. func WithExcludeKnownExtensions() ImageFilterOption { return func(opts *imageFilterOptions) { @@ -90,7 +90,7 @@ func WithExcludeKnownExtensions() ImageFilterOption { } } -// WithAllowIncludeOfImportedType returns an option for ImageFilteredByTypesWithOptions +// WithAllowIncludeOfImportedType returns an option for FilterImage // that allows a named included type to be in an imported file or module. Without this // option, only types defined directly in the image to be filtered are allowed. // Excluded types are always allowed to be in imported files or modules. @@ -100,7 +100,7 @@ func WithAllowIncludeOfImportedType() ImageFilterOption { } } -// WithIncludeTypes returns an option for ImageFilteredByTypesWithOptions that specifies +// WithIncludeTypes returns an option for FilterImage that specifies // the set of types that should be included in the filtered image. // // May be provided multiple times. The type names should be fully qualified. @@ -120,7 +120,7 @@ func WithIncludeTypes(typeNames ...string) ImageFilterOption { } } -// WithExcludeTypes returns an option for ImageFilteredByTypesWithOptions that +// WithExcludeTypes returns an option for FilterImage that // specifies the set of types that should be excluded from the filtered image. // // May be provided multiple times. The type names should be fully qualified. @@ -140,7 +140,7 @@ func WithExcludeTypes(typeNames ...string) ImageFilterOption { } } -// WithMutateInPlace returns an option for ImageFilteredByTypesWithOptions that specifies +// WithMutateInPlace returns an option for FilterImage that specifies // that the filtered image should be mutated in place. This option is useful when the // unfiltered image is no longer needed and the caller wants to avoid the overhead of // copying the image. From 6d362d77722042d436110ef39253db5263ac88d3 Mon Sep 17 00:00:00 2001 From: Josh Humphries <2035234+jhump@users.noreply.github.com> Date: Mon, 9 Feb 2026 11:28:35 -0500 Subject: [PATCH 2/4] update tests to also capture actual rewritten sources for source-code-info test cases --- .../bufimageutil/bufimageutil_test.go | 20 +- .../testdata/sourcecodeinfo/Bar.txtar | 49 ++ .../testdata/sourcecodeinfo/Baz.txtar | 15 + .../testdata/sourcecodeinfo/Do.txtar | 57 ++ .../testdata/sourcecodeinfo/Foo+Ext.txtar | 349 ++++++++++ .../testdata/sourcecodeinfo/Foo.txtar | 23 + .../testdata/sourcecodeinfo/NestedFoo.txtar | 189 ++++++ .../testdata/sourcecodeinfo/Quz.txtar | 13 + .../testdata/sourcecodeinfo/Svc.txtar | 59 ++ .../testdata/sourcecodeinfo/all.txtar | 608 ++++++++++++++++++ .../testdata/sourcecodeinfo/test.proto | 2 +- 11 files changed, 1375 insertions(+), 9 deletions(-) diff --git a/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go b/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go index e03815612c..404352cc54 100644 --- a/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go +++ b/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go @@ -274,17 +274,17 @@ func TestOptionImports(t *testing.T) { t.Run("exclude_foo", func(t *testing.T) { t.Parallel() - generated := runFilterImage(t, image, WithExcludeTypes("message_foo")) + generated, _ := runFilterImage(t, image, WithExcludeTypes("message_foo")) checkExpectation(t, context.Background(), generated, bucket, "foo.txtar") }) t.Run("exclude_foo_bar", func(t *testing.T) { t.Parallel() - generated := runFilterImage(t, image, WithExcludeTypes("message_foo", "message_bar")) + generated, _ := runFilterImage(t, image, WithExcludeTypes("message_foo", "message_bar")) checkExpectation(t, context.Background(), generated, bucket, "foo_bar.txtar") }) t.Run("exclude_bar", func(t *testing.T) { t.Parallel() - generated := runFilterImage(t, image, WithIncludeTypes("pkg.Foo"), WithExcludeTypes("message_bar")) + generated, _ := runFilterImage(t, image, WithIncludeTypes("pkg.Foo"), WithExcludeTypes("message_bar")) checkExpectation(t, context.Background(), generated, bucket, "bar.txtar") }) } @@ -541,11 +541,11 @@ func runDiffTest(t *testing.T, testdataDir string, expectedFile string, opts ... ctx := context.Background() bucket, image, err := getImage(ctx, slogtestext.NewLogger(t), testdataDir, bufimage.WithExcludeSourceCodeInfo()) require.NoError(t, err) - generated := runFilterImage(t, image, opts...) + generated, _ := runFilterImage(t, image, opts...) checkExpectation(t, ctx, generated, bucket, expectedFile) } -func runFilterImage(t *testing.T, image bufimage.Image, opts ...ImageFilterOption) []byte { +func runFilterImage(t *testing.T, image bufimage.Image, opts ...ImageFilterOption) ([]byte, bufimage.Image) { filteredImage, err := FilterImage(image, opts...) require.NoError(t, err) assert.NotNil(t, filteredImage) @@ -594,7 +594,7 @@ func runFilterImage(t *testing.T, image bufimage.Image, opts ...ImageFilterOptio return archive.Files[i].Name < archive.Files[j].Name }) generated := txtar.Format(archive) - return generated + return generated, filteredImage } func checkExpectation(t *testing.T, ctx context.Context, actual []byte, bucket storage.ReadWriteBucket, expectedFile string) { @@ -618,15 +618,19 @@ func runSourceCodeInfoTest(t *testing.T, typename string, expectedFile string, o bucket, image, err := getImage(ctx, slogtestext.NewLogger(t), "testdata/sourcecodeinfo") require.NoError(t, err) - filteredImage, err := FilterImage(image, append(opts, WithIncludeTypes(typename))...) + opts = append(opts, WithIncludeTypes(typename)) + generated, image := runFilterImage(t, image, opts...) + filteredImage, err := FilterImage(image, opts...) require.NoError(t, err) imageFile := filteredImage.GetFile("test.proto") sourceCodeInfo := imageFile.FileDescriptorProto().GetSourceCodeInfo() actual, err := protoencoding.NewJSONMarshaler(nil, protoencoding.JSONMarshalerWithIndent()).Marshal(sourceCodeInfo) require.NoError(t, err) + generated = append(generated, []byte("-- source_code_info.json --\n")...) + generated = append(generated, actual...) - checkExpectation(t, ctx, actual, bucket, expectedFile) + checkExpectation(t, ctx, generated, bucket, expectedFile) resolver, err := protoencoding.NewResolver(bufimage.ImageToFileDescriptorProtos(filteredImage)...) require.NoError(t, err) diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Bar.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Bar.txtar index 3e7d62fe31..eee1d43c06 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Bar.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Bar.txtar @@ -1,3 +1,52 @@ +-- test.proto -- +// Keep 1: comment on syntax +syntax = "proto2"; +// Keep 2: comment on package +package foo.bar; +// Keep 3: comment on option +option go_package = "foo.bar/baz"; +// "Keep if Bar" are also kept for Svc and Svc.Do since those +// elements depend on Bar. +// Keep if Bar: comment on message Bar +message Bar { + // Keep if Bar: comment on field foo + optional Foo foo = 1; + // Keep if Bar: comment on oneof status + oneof status { + // Keep if Bar: comment on field baz + Baz baz = 2; + // Keep if Bar: comment on field quz + Quz quz = 3; + } +} +// "Keep if Foo" are also kept for Bar, Svc, and Svc.Do since those +// elements depend on Foo. +// Keep if Foo: comment on message Foo +message Foo { + // We keep the following comment for NestedFoo because we don't + // discard options or option comments even if we're only retaining + // a message as a namespace for another retained element. + // Keep if Foo: comment on field name + optional string name = 1; + // Keep if Foo: comment on field bits + repeated int64 bits = 2; + extensions 100 to max; + reserved 10 to 20; + reserved "abc", "def", "ghi"; +} +// "Keep if Baz" and "Keep if Quz" are also kept for Bar, Svc, and Svc.Do +// since those elements depend on Baz and Quz. +// Keep if Baz: comment on enum Baz +enum Baz { + // Keep if Baz: comment on enum value BAZ_UNSPECIFIED + BAZ_UNSPECIFIED = 0; +} +// Keep if Quz: comment on enum Quz +enum Quz { + // Keep if Quz: comment on enum value QUZ_UNSPECIFIED + QUZ_UNSPECIFIED = 0; +} +-- source_code_info.json -- { "location": [ { diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Baz.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Baz.txtar index 44c12138c0..b33a0d3f5a 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Baz.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Baz.txtar @@ -1,3 +1,18 @@ +-- test.proto -- +// Keep 1: comment on syntax +syntax = "proto2"; +// Keep 2: comment on package +package foo.bar; +// Keep 3: comment on option +option go_package = "foo.bar/baz"; +// "Keep if Baz" and "Keep if Quz" are also kept for Bar, Svc, and Svc.Do +// since those elements depend on Baz and Quz. +// Keep if Baz: comment on enum Baz +enum Baz { + // Keep if Baz: comment on enum value BAZ_UNSPECIFIED + BAZ_UNSPECIFIED = 0; +} +-- source_code_info.json -- { "location": [ { diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Do.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Do.txtar index 48402599da..7ffede113d 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Do.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Do.txtar @@ -1,3 +1,60 @@ +-- test.proto -- +// Keep 1: comment on syntax +syntax = "proto2"; +// Keep 2: comment on package +package foo.bar; +// Keep 3: comment on option +option go_package = "foo.bar/baz"; +// "Keep if Bar" are also kept for Svc and Svc.Do since those +// elements depend on Bar. +// Keep if Bar: comment on message Bar +message Bar { + // Keep if Bar: comment on field foo + optional Foo foo = 1; + // Keep if Bar: comment on oneof status + oneof status { + // Keep if Bar: comment on field baz + Baz baz = 2; + // Keep if Bar: comment on field quz + Quz quz = 3; + } +} +// "Keep if Foo" are also kept for Bar, Svc, and Svc.Do since those +// elements depend on Foo. +// Keep if Foo: comment on message Foo +message Foo { + // We keep the following comment for NestedFoo because we don't + // discard options or option comments even if we're only retaining + // a message as a namespace for another retained element. + // Keep if Foo: comment on field name + optional string name = 1; + // Keep if Foo: comment on field bits + repeated int64 bits = 2; + extensions 100 to max; + reserved 10 to 20; + reserved "abc", "def", "ghi"; +} +// "Keep if Baz" and "Keep if Quz" are also kept for Bar, Svc, and Svc.Do +// since those elements depend on Baz and Quz. +// Keep if Baz: comment on enum Baz +enum Baz { + // Keep if Baz: comment on enum value BAZ_UNSPECIFIED + BAZ_UNSPECIFIED = 0; +} +// Keep if Quz: comment on enum Quz +enum Quz { + // Keep if Quz: comment on enum value QUZ_UNSPECIFIED + QUZ_UNSPECIFIED = 0; +} +// Keep if Svc: comment on service Svc +service Svc { + // Keep if Svc.Do: comment on rpc Do + rpc Do ( Foo ) returns ( Bar ) { + // Keep if Svc.Do: comment on option + option idempotency_level = NO_SIDE_EFFECTS; + } +} +-- source_code_info.json -- { "location": [ { diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo+Ext.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo+Ext.txtar index bb2fb5deeb..d064f23aae 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo+Ext.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo+Ext.txtar @@ -1,3 +1,352 @@ +-- google/protobuf/descriptor.proto -- +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). +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"; +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; +// =================================================================== +// Features +// TODO Enums in C++ gencode (and potentially other languages) are +// not well scoped. This means that each of the feature enums below can clash +// with each other. The short names we've chosen maximize call-site +// readability, but leave us very open to this scenario. A future feature will +// be designed and implemented to handle this, hopefully before we ever hit a +// conflict here. +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 + ]; + optional EnforceNamingStyle enforce_naming_style = 7 [ + edition_defaults = { value: "STYLE_LEGACY", edition: EDITION_LEGACY }, + edition_defaults = { value: "STYLE2024", edition: EDITION_2024 }, + feature_support = { edition_introduced: EDITION_2024 }, + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_FILE, + targets = TARGET_TYPE_EXTENSION_RANGE, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_ONEOF, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_ENUM_ENTRY, + targets = TARGET_TYPE_SERVICE, + targets = TARGET_TYPE_METHOD + ]; + optional VisibilityFeature.DefaultSymbolVisibility default_symbol_visibility = 8 [ + edition_defaults = { value: "EXPORT_ALL", edition: EDITION_LEGACY }, + edition_defaults = { value: "EXPORT_TOP_LEVEL", edition: EDITION_2024 }, + feature_support = { edition_introduced: EDITION_2024 }, + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_FILE + ]; + message VisibilityFeature { + enum DefaultSymbolVisibility { + DEFAULT_SYMBOL_VISIBILITY_UNKNOWN = 0; + // Default pre-EDITION_2024, all UNSET visibility are export. + EXPORT_ALL = 1; + // All top-level symbols default to export, nested default to local. + EXPORT_TOP_LEVEL = 2; + // All symbols default to local. + LOCAL_ALL = 3; + // All symbols local by default. Nested types cannot be exported. + // With special case caveat for message { enum {} reserved 1 to max; } + // This is the recommended setting for new protos. + STRICT = 4; + } + } + enum EnforceNamingStyle { + ENFORCE_NAMING_STYLE_UNKNOWN = 0; + STYLE2024 = 1; + STYLE_LEGACY = 2; + } + 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: 1003, + full_name: ".pb.python", + type: ".pb.PythonFeatures" + }, + declaration = { + number: 9990, + full_name: ".pb.proto1", + type: ".pb.Proto1Features" + } + ]; + extensions 9995 to 9999, 10000; + reserved 999; +} +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default = false]; + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default = false]; + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default = false]; + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementations still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + optional bool map_entry = 7; + // Enable the legacy handling of JSON field name conflicts. This lowercases + // and strips underscored from the fields before comparison in proto3 only. + // The new behavior takes `json_name` into account and applies to proto2 as + // well. + // + // This should only be used as a temporary measure against broken builds due + // to the change in behavior for JSON field name conflicts. + // + // TODO This is legacy behavior we plan to remove once downstream + // teams have had time to migrate. + optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 12; + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + extensions 1000 to max; + reserved 4, 5, 6, 8, 9; +} +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + repeated NamePart name = 2; + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + 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; + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents + // "foo.(bar.baz).moo". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } +} +-- test.proto -- +// Keep 1: comment on syntax +syntax = "proto2"; +// Keep 2: comment on package +package foo.bar; +// Keep if ext: comment on import descriptor.proto +import "google/protobuf/descriptor.proto"; +// Keep 3: comment on option +option go_package = "foo.bar/baz"; +// "Keep if Foo" are also kept for Bar, Svc, and Svc.Do since those +// elements depend on Foo. +// Keep if Foo: comment on message Foo +message Foo { + // We keep the following comment for NestedFoo because we don't + // discard options or option comments even if we're only retaining + // a message as a namespace for another retained element. + // Keep if Foo | NestedFoo: comment on option + option (bizniz) = "abc"; + // Keep if Foo: comment on field name + optional string name = 1; + // Keep if Foo: comment on field bits + repeated int64 bits = 2; + message NestedFoo { + // Keep if Foo + ext | NestedFoo: comment on option + option (bizniz) = "abc"; + // Keep if Foo + ext: comment on extend block + extend Foo { + // Keep if Foo + ext: comment on extension blah + repeated bytes blah = 101; + } + } + extensions 100 to max; + reserved 10 to 20; + reserved "abc", "def", "ghi"; +} +// Keep if ext: comment on extend block +extend google.protobuf.MessageOptions { + // Keep if ext: comment on custom option bizniz + optional string bizniz = 10101; +} +-- source_code_info.json -- { "location": [ { diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo.txtar index 80f32ea28f..5829afcda5 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo.txtar @@ -1,3 +1,26 @@ +-- test.proto -- +// Keep 1: comment on syntax +syntax = "proto2"; +// Keep 2: comment on package +package foo.bar; +// Keep 3: comment on option +option go_package = "foo.bar/baz"; +// "Keep if Foo" are also kept for Bar, Svc, and Svc.Do since those +// elements depend on Foo. +// Keep if Foo: comment on message Foo +message Foo { + // We keep the following comment for NestedFoo because we don't + // discard options or option comments even if we're only retaining + // a message as a namespace for another retained element. + // Keep if Foo: comment on field name + optional string name = 1; + // Keep if Foo: comment on field bits + repeated int64 bits = 2; + extensions 100 to max; + reserved 10 to 20; + reserved "abc", "def", "ghi"; +} +-- source_code_info.json -- { "location": [ { diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/NestedFoo.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/NestedFoo.txtar index a3fbd54223..88dbab3dde 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/NestedFoo.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/NestedFoo.txtar @@ -1,3 +1,192 @@ +-- google/protobuf/any.proto -- +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; +package google.protobuf; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "google.golang.org/protobuf/types/known/anypb"; +option java_multiple_files = true; +option java_outer_classname = "AnyProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; +// `Any` contains an arbitrary serialized protocol buffer message along with a +// URL that describes the type of the serialized message. +// +// Protobuf library provides support to pack/unpack Any values in the form +// of utility functions or additional generated methods of the Any type. +// +// Example 1: Pack and unpack a message in C++. +// +// Foo foo = ...; +// Any any; +// any.PackFrom(foo); +// ... +// if (any.UnpackTo(&foo)) { +// ... +// } +// +// Example 2: Pack and unpack a message in Java. +// +// Foo foo = ...; +// Any any = Any.pack(foo); +// ... +// if (any.is(Foo.class)) { +// foo = any.unpack(Foo.class); +// } +// // or ... +// if (any.isSameTypeAs(Foo.getDefaultInstance())) { +// foo = any.unpack(Foo.getDefaultInstance()); +// } +// +// Example 3: Pack and unpack a message in Python. +// +// foo = Foo(...) +// any = Any() +// any.Pack(foo) +// ... +// if any.Is(Foo.DESCRIPTOR): +// any.Unpack(foo) +// ... +// +// Example 4: Pack and unpack a message in Go +// +// foo := &pb.Foo{...} +// any, err := anypb.New(foo) +// if err != nil { +// ... +// } +// ... +// foo := &pb.Foo{} +// if err := any.UnmarshalTo(foo); err != nil { +// ... +// } +// +// The pack methods provided by protobuf library will by default use +// 'type.googleapis.com/full.type.name' as the type URL and the unpack +// methods only use the fully qualified type name after the last '/' +// in the type URL, for example "foo.bar.com/x/y.z" will yield type +// name "y.z". +// +// JSON +// ==== +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the `@type` +// field. Example (for message [google.protobuf.Duration][]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +message Any { + // A URL/resource name that uniquely identifies the type of the serialized + // protocol buffer message. This string must contain at least + // one "/" character. The last segment of the URL's path must represent + // the fully qualified name of the type (as in + // `path/google.protobuf.Duration`). The name should be in a canonical form + // (e.g., leading "." is not accepted). + // + // In practice, teams usually precompile into the binary all types that they + // expect it to use in the context of Any. However, for URLs which use the + // scheme `http`, `https`, or no scheme, one can optionally set up a type + // server that maps type URLs to message definitions as follows: + // + // * If no scheme is provided, `https` is assumed. + // * An HTTP GET on the URL must yield a [google.protobuf.Type][] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Note: this functionality is not currently available in the official + // protobuf release, and it is not used for type URLs beginning with + // type.googleapis.com. As of May 2023, there are no widely used type server + // implementations and no plans to implement one. + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. + // + string type_url = 1; + // Must be a valid serialized protocol buffer of the above specified type. + bytes value = 2; +} +-- test.proto -- +// Keep 1: comment on syntax +syntax = "proto2"; +// Keep 2: comment on package +package foo.bar; +// Keep if NestedFoo: comment on import any.proto +import "google/protobuf/any.proto"; +// Keep 3: comment on option +option go_package = "foo.bar/baz"; +message Foo { + // Keep if NestedFoo: comment on message NestedFoo + message NestedFoo { + // We keep the following comment for Foo + ext because we don't + // discard options or option comments even if we're only retaining + // a message as a namespace for another retained element. + // Keep if NestedFoo: comment on field uid + optional uint64 uid = 1; + // Keep if NestedFoo: comment on field meta + repeated google.protobuf.Any meta = 2; + // Keep if NestedFoo: comment on field state + optional State state = 3; + // Keep if NestedFoo: comment on enum State + enum State { + // Keep if NestedFoo: comment on enum value STATE_UNSPECIFIED + STATE_UNSPECIFIED = 0; + // Keep if NestedFoo: comment on enum value STATE_GOOD + STATE_GOOD = 1; + } + } +} +-- source_code_info.json -- { "location": [ { diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Quz.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Quz.txtar index 20a4c7223c..37b4a3a678 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Quz.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Quz.txtar @@ -1,3 +1,16 @@ +-- test.proto -- +// Keep 1: comment on syntax +syntax = "proto2"; +// Keep 2: comment on package +package foo.bar; +// Keep 3: comment on option +option go_package = "foo.bar/baz"; +// Keep if Quz: comment on enum Quz +enum Quz { + // Keep if Quz: comment on enum value QUZ_UNSPECIFIED + QUZ_UNSPECIFIED = 0; +} +-- source_code_info.json -- { "location": [ { diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Svc.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Svc.txtar index d621abb962..ccb9aaf131 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Svc.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Svc.txtar @@ -1,3 +1,62 @@ +-- test.proto -- +// Keep 1: comment on syntax +syntax = "proto2"; +// Keep 2: comment on package +package foo.bar; +// Keep 3: comment on option +option go_package = "foo.bar/baz"; +// "Keep if Bar" are also kept for Svc and Svc.Do since those +// elements depend on Bar. +// Keep if Bar: comment on message Bar +message Bar { + // Keep if Bar: comment on field foo + optional Foo foo = 1; + // Keep if Bar: comment on oneof status + oneof status { + // Keep if Bar: comment on field baz + Baz baz = 2; + // Keep if Bar: comment on field quz + Quz quz = 3; + } +} +// "Keep if Foo" are also kept for Bar, Svc, and Svc.Do since those +// elements depend on Foo. +// Keep if Foo: comment on message Foo +message Foo { + // We keep the following comment for NestedFoo because we don't + // discard options or option comments even if we're only retaining + // a message as a namespace for another retained element. + // Keep if Foo: comment on field name + optional string name = 1; + // Keep if Foo: comment on field bits + repeated int64 bits = 2; + extensions 100 to max; + reserved 10 to 20; + reserved "abc", "def", "ghi"; +} +// "Keep if Baz" and "Keep if Quz" are also kept for Bar, Svc, and Svc.Do +// since those elements depend on Baz and Quz. +// Keep if Baz: comment on enum Baz +enum Baz { + // Keep if Baz: comment on enum value BAZ_UNSPECIFIED + BAZ_UNSPECIFIED = 0; +} +// Keep if Quz: comment on enum Quz +enum Quz { + // Keep if Quz: comment on enum value QUZ_UNSPECIFIED + QUZ_UNSPECIFIED = 0; +} +// Keep if Svc: comment on service Svc +service Svc { + // Keep if Svc.Do: comment on rpc Do + rpc Do ( Foo ) returns ( Bar ) { + // Keep if Svc.Do: comment on option + option idempotency_level = NO_SIDE_EFFECTS; + } + // Keep if Svc: comment on rpc Dont + rpc Dont ( Foo ) returns ( Bar ); +} +-- source_code_info.json -- { "location": [ { diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/all.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/all.txtar index 3d08341efb..e0fe2b85b5 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/all.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/all.txtar @@ -1,3 +1,611 @@ +-- google/protobuf/any.proto -- +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; +package google.protobuf; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "google.golang.org/protobuf/types/known/anypb"; +option java_multiple_files = true; +option java_outer_classname = "AnyProto"; +option java_package = "com.google.protobuf"; +option objc_class_prefix = "GPB"; +// `Any` contains an arbitrary serialized protocol buffer message along with a +// URL that describes the type of the serialized message. +// +// Protobuf library provides support to pack/unpack Any values in the form +// of utility functions or additional generated methods of the Any type. +// +// Example 1: Pack and unpack a message in C++. +// +// Foo foo = ...; +// Any any; +// any.PackFrom(foo); +// ... +// if (any.UnpackTo(&foo)) { +// ... +// } +// +// Example 2: Pack and unpack a message in Java. +// +// Foo foo = ...; +// Any any = Any.pack(foo); +// ... +// if (any.is(Foo.class)) { +// foo = any.unpack(Foo.class); +// } +// // or ... +// if (any.isSameTypeAs(Foo.getDefaultInstance())) { +// foo = any.unpack(Foo.getDefaultInstance()); +// } +// +// Example 3: Pack and unpack a message in Python. +// +// foo = Foo(...) +// any = Any() +// any.Pack(foo) +// ... +// if any.Is(Foo.DESCRIPTOR): +// any.Unpack(foo) +// ... +// +// Example 4: Pack and unpack a message in Go +// +// foo := &pb.Foo{...} +// any, err := anypb.New(foo) +// if err != nil { +// ... +// } +// ... +// foo := &pb.Foo{} +// if err := any.UnmarshalTo(foo); err != nil { +// ... +// } +// +// The pack methods provided by protobuf library will by default use +// 'type.googleapis.com/full.type.name' as the type URL and the unpack +// methods only use the fully qualified type name after the last '/' +// in the type URL, for example "foo.bar.com/x/y.z" will yield type +// name "y.z". +// +// JSON +// ==== +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the `@type` +// field. Example (for message [google.protobuf.Duration][]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +message Any { + // A URL/resource name that uniquely identifies the type of the serialized + // protocol buffer message. This string must contain at least + // one "/" character. The last segment of the URL's path must represent + // the fully qualified name of the type (as in + // `path/google.protobuf.Duration`). The name should be in a canonical form + // (e.g., leading "." is not accepted). + // + // In practice, teams usually precompile into the binary all types that they + // expect it to use in the context of Any. However, for URLs which use the + // scheme `http`, `https`, or no scheme, one can optionally set up a type + // server that maps type URLs to message definitions as follows: + // + // * If no scheme is provided, `https` is assumed. + // * An HTTP GET on the URL must yield a [google.protobuf.Type][] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Note: this functionality is not currently available in the official + // protobuf release, and it is not used for type URLs beginning with + // type.googleapis.com. As of May 2023, there are no widely used type server + // implementations and no plans to implement one. + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. + // + string type_url = 1; + // Must be a valid serialized protocol buffer of the above specified type. + bytes value = 2; +} +-- google/protobuf/descriptor.proto -- +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). +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"; +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; +// =================================================================== +// Features +// TODO Enums in C++ gencode (and potentially other languages) are +// not well scoped. This means that each of the feature enums below can clash +// with each other. The short names we've chosen maximize call-site +// readability, but leave us very open to this scenario. A future feature will +// be designed and implemented to handle this, hopefully before we ever hit a +// conflict here. +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 + ]; + optional EnforceNamingStyle enforce_naming_style = 7 [ + edition_defaults = { value: "STYLE_LEGACY", edition: EDITION_LEGACY }, + edition_defaults = { value: "STYLE2024", edition: EDITION_2024 }, + feature_support = { edition_introduced: EDITION_2024 }, + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_FILE, + targets = TARGET_TYPE_EXTENSION_RANGE, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_FIELD, + targets = TARGET_TYPE_ONEOF, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_ENUM_ENTRY, + targets = TARGET_TYPE_SERVICE, + targets = TARGET_TYPE_METHOD + ]; + optional VisibilityFeature.DefaultSymbolVisibility default_symbol_visibility = 8 [ + edition_defaults = { value: "EXPORT_ALL", edition: EDITION_LEGACY }, + edition_defaults = { value: "EXPORT_TOP_LEVEL", edition: EDITION_2024 }, + feature_support = { edition_introduced: EDITION_2024 }, + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_FILE + ]; + message VisibilityFeature { + enum DefaultSymbolVisibility { + DEFAULT_SYMBOL_VISIBILITY_UNKNOWN = 0; + // Default pre-EDITION_2024, all UNSET visibility are export. + EXPORT_ALL = 1; + // All top-level symbols default to export, nested default to local. + EXPORT_TOP_LEVEL = 2; + // All symbols default to local. + LOCAL_ALL = 3; + // All symbols local by default. Nested types cannot be exported. + // With special case caveat for message { enum {} reserved 1 to max; } + // This is the recommended setting for new protos. + STRICT = 4; + } + } + enum EnforceNamingStyle { + ENFORCE_NAMING_STYLE_UNKNOWN = 0; + STYLE2024 = 1; + STYLE_LEGACY = 2; + } + 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: 1003, + full_name: ".pb.python", + type: ".pb.PythonFeatures" + }, + declaration = { + number: 9990, + full_name: ".pb.proto1", + type: ".pb.Proto1Features" + } + ]; + extensions 9995 to 9999, 10000; + reserved 999; +} +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default = false]; + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default = false]; + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default = false]; + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementations still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + optional bool map_entry = 7; + // Enable the legacy handling of JSON field name conflicts. This lowercases + // and strips underscored from the fields before comparison in proto3 only. + // The new behavior takes `json_name` into account and applies to proto2 as + // well. + // + // This should only be used as a temporary measure against broken builds due + // to the change in behavior for JSON field name conflicts. + // + // TODO This is legacy behavior we plan to remove once downstream + // teams have had time to migrate. + optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 12; + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + extensions 1000 to max; + reserved 4, 5, 6, 8, 9; +} +message ServiceOptions { + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default = false]; + // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. + optional FeatureSet features = 34; + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + extensions 1000 to max; +} +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + repeated NamePart name = 2; + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + 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; + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents + // "foo.(bar.baz).moo". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } +} +-- test.proto -- +// Keep 1: comment on syntax +syntax = "proto2"; +// Keep 2: comment on package +package foo.bar; +// Keep if NestedFoo: comment on import any.proto +import "google/protobuf/any.proto"; +// Keep if ext: comment on import descriptor.proto +import "google/protobuf/descriptor.proto"; +// Keep 3: comment on option +option go_package = "foo.bar/baz"; +// "Keep if Bar" are also kept for Svc and Svc.Do since those +// elements depend on Bar. +// Keep if Bar: comment on message Bar +message Bar { + // Keep if Bar: comment on field foo + optional Foo foo = 1; + // Keep if Bar: comment on oneof status + oneof status { + // Keep if Bar: comment on field baz + Baz baz = 2; + // Keep if Bar: comment on field quz + Quz quz = 3; + } +} +// Keep if all: comment on message Bedazzle +message Bedazzle { + // Keep if all: comment on field t + optional string t = 1; +} +// Keep if all: comment on message Buzz +message Buzz { + // Keep if all: comment on field s + optional string s = 1; +} +// "Keep if Foo" are also kept for Bar, Svc, and Svc.Do since those +// elements depend on Foo. +// Keep if Foo: comment on message Foo +message Foo { + // We keep the following comment for NestedFoo because we don't + // discard options or option comments even if we're only retaining + // a message as a namespace for another retained element. + // Keep if Foo | NestedFoo: comment on option + option (bizniz) = "abc"; + // Keep if Foo: comment on field name + optional string name = 1; + // Keep if Foo: comment on field bits + repeated int64 bits = 2; + // Keep if NestedFoo: comment on message NestedFoo + message NestedFoo { + // We keep the following comment for Foo + ext because we don't + // discard options or option comments even if we're only retaining + // a message as a namespace for another retained element. + // Keep if Foo + ext | NestedFoo: comment on option + option (bizniz) = "abc"; + // Keep if NestedFoo: comment on field uid + optional uint64 uid = 1; + // Keep if NestedFoo: comment on field meta + repeated google.protobuf.Any meta = 2; + // Keep if NestedFoo: comment on field state + optional State state = 3; + // Keep if NestedFoo: comment on enum State + enum State { + // Keep if NestedFoo: comment on enum value STATE_UNSPECIFIED + STATE_UNSPECIFIED = 0; + // Keep if NestedFoo: comment on enum value STATE_GOOD + STATE_GOOD = 1; + } + // Keep if Foo + ext: comment on extend block + extend Foo { + // Keep if Foo + ext: comment on extension blah + repeated bytes blah = 101; + } + } + extensions 100 to max; + reserved 10 to 20; + reserved "abc", "def", "ghi"; +} +// Keep if all: comment on message Frobnitz +message Frobnitz { + // Keep if all: comment on field xyz + optional bytes xyz = 1; +} +// "Keep if Baz" and "Keep if Quz" are also kept for Bar, Svc, and Svc.Do +// since those elements depend on Baz and Quz. +// Keep if Baz: comment on enum Baz +enum Baz { + // Keep if Baz: comment on enum value BAZ_UNSPECIFIED + BAZ_UNSPECIFIED = 0; +} +// Keep if Quz: comment on enum Quz +enum Quz { + // Keep if Quz: comment on enum value QUZ_UNSPECIFIED + QUZ_UNSPECIFIED = 0; +} +// Keep if all: comment on service BuzzService +service BuzzService { + // Keep if all: comment on method BuzzyBuzz + rpc BuzzyBuzz ( Buzz ) returns ( Bedazzle ); +} +// Keep if Svc: comment on service Svc +service Svc { + // Keep if Svc: comment on option + option (fizzbuzz) = "wxyz"; + // Keep if Svc.Do: comment on rpc Do + rpc Do ( Foo ) returns ( Bar ) { + // Keep if Svc.Do: comment on option + option idempotency_level = NO_SIDE_EFFECTS; + } + // Keep if Svc: comment on rpc Dont + rpc Dont ( Foo ) returns ( Bar ); +} +// Keep if ext: comment on extend block +extend google.protobuf.MessageOptions { + // Keep if ext: comment on custom option bizniz + optional string bizniz = 10101; +} +// Keep if ext: comment on extend block +extend google.protobuf.ServiceOptions { + // Keep if ext + Svc: comment on custom option fizzbuzz + optional string fizzbuzz = 10101; +} +-- source_code_info.json -- { "location": [ { diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/test.proto b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/test.proto index 5d9c4dd1ec..9a8dfb1370 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/test.proto +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/test.proto @@ -14,7 +14,7 @@ import "google/protobuf/descriptor.proto"; import weak "google/protobuf/struct.proto"; // Keep if NestedFoo: comment on import any.proto -import weak "google/protobuf/any.proto"; +import weak "google/protobuf/any.proto"; // Keep if ext: comment on extend block extend google.protobuf.MessageOptions { From 4a5b864784389846bc8d7ffa908295d45596585b Mon Sep 17 00:00:00 2001 From: Josh Humphries <2035234+jhump@users.noreply.github.com> Date: Mon, 9 Feb 2026 11:58:19 -0500 Subject: [PATCH 3/4] fix issue with rewriting weak imports --- .../bufimageutil/bufimageutil_test.go | 5 +++-- .../bufimage/bufimageutil/image_filter.go | 21 ++++++++++++------ .../testdata/sourcecodeinfo/Bar.txtar | 11 ---------- .../testdata/sourcecodeinfo/Baz.txtar | 11 ---------- .../testdata/sourcecodeinfo/Do.txtar | 11 ---------- .../testdata/sourcecodeinfo/Foo+Ext.txtar | 11 ---------- .../testdata/sourcecodeinfo/Foo.txtar | 11 ---------- .../testdata/sourcecodeinfo/NestedFoo.txtar | 20 ++++++++--------- .../testdata/sourcecodeinfo/Quz.txtar | 11 ---------- .../testdata/sourcecodeinfo/Svc.txtar | 11 ---------- .../testdata/sourcecodeinfo/all.txtar | 22 +++++++++---------- 11 files changed, 38 insertions(+), 107 deletions(-) diff --git a/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go b/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go index 404352cc54..cd8127852b 100644 --- a/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go +++ b/private/bufpkg/bufimage/bufimageutil/bufimageutil_test.go @@ -562,8 +562,9 @@ func runFilterImage(t *testing.T, image bufimage.Image, opts ...ImageFilterOptio // We may have filtered out custom options from the set in the step above. However, the options messages // still contain extension fields that refer to the custom options, as a result of building the image. - // So we serialize and then de-serialize, and use only the filtered results to parse extensions. That way, the result will omit custom options that aren't present in the filtered set (as they will be - // considered unrecognized fields). + // So we serialize and then de-serialize, and use only the filtered results to parse extensions. That way, + // the result will omit custom options that aren't present in the filtered set (as they will be considered + // unrecognized fields). fileDescriptorSet := &descriptorpb.FileDescriptorSet{ File: xslices.Map(filteredImage.Files(), func(imageFile bufimage.ImageFile) *descriptorpb.FileDescriptorProto { return imageFile.FileDescriptorProto() diff --git a/private/bufpkg/bufimage/bufimageutil/image_filter.go b/private/bufpkg/bufimage/bufimageutil/image_filter.go index d286ec0ba6..d97a91e289 100644 --- a/private/bufpkg/bufimage/bufimageutil/image_filter.go +++ b/private/bufpkg/bufimage/bufimageutil/image_filter.go @@ -15,6 +15,7 @@ package bufimageutil import ( + "errors" "fmt" "slices" "sort" @@ -254,6 +255,10 @@ func (b *sourcePathsBuilder) remapDependencies( dependencies := fileDescriptor.GetDependency() publicDependencies := fileDescriptor.GetPublicDependency() weakDependencies := fileDescriptor.GetWeakDependency() + // TODO: Add support for option dependencies when buf CLI supports edition 2024. + if len(fileDescriptor.GetOptionDependency()) > 0 { + return nil, nil, nil, false, errors.New("edition 2024 not yet supported: cannot filter a file descriptor with option dependencies") + } // Check if the imports need to be remapped. importsRequired := b.closure.imports[fileDescriptor.GetName()] @@ -271,14 +276,15 @@ func (b *sourcePathsBuilder) remapDependencies( return dependencies, publicDependencies, weakDependencies, false, nil } - indexFrom, indexTo := int32(0), int32(0) var newDependencies []string if b.options.mutateInPlace { newDependencies = dependencies[:0] } dependencyPath := append(sourcePath, fileDependencyTag) dependencyChanges := make([]int32, len(dependencies)) - for _, importPath := range dependencies { + indexTo := int32(0) + for i, importPath := range dependencies { + indexFrom := int32(i) path := append(dependencyPath, indexFrom) if _, ok := importsRequired[importPath]; ok { dependencyChanges[indexFrom] = indexTo @@ -293,7 +299,6 @@ func (b *sourcePathsBuilder) remapDependencies( sourcePathsRemap.markDeleted(path) dependencyChanges[indexFrom] = -1 } - indexFrom++ } // Add imports picked up via a public import. The filtered files do not use public imports. if publicImportCount := len(importsRequired); publicImportCount > 0 { @@ -314,14 +319,16 @@ func (b *sourcePathsBuilder) remapDependencies( newWeakDependencies = weakDependencies[:0] } weakDependencyPath := append(sourcePath, fileWeakDependencyTag) - for _, indexFrom := range weakDependencies { - path := append(weakDependencyPath, indexFrom) + for i, indexFrom := range weakDependencies { + weakFrom := int32(i) + path := append(weakDependencyPath, weakFrom) indexTo := dependencyChanges[indexFrom] if indexTo == -1 { sourcePathsRemap.markDeleted(path) } else { - if indexTo != indexFrom { - sourcePathsRemap.markMoved(path, indexTo) + weakTo := int32(len(newWeakDependencies)) + if weakTo != weakFrom { + sourcePathsRemap.markMoved(path, weakTo) } newWeakDependencies = append(newWeakDependencies, indexTo) } diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Bar.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Bar.txtar index eee1d43c06..986e21e26d 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Bar.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Bar.txtar @@ -101,17 +101,6 @@ enum Quz { ], "leadingComments": " Keep 3: comment on option\n" }, - { - "path": [ - 11, - 0 - ], - "span": [ - 13, - 7, - 11 - ] - }, { "path": [ 4, diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Baz.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Baz.txtar index b33a0d3f5a..40f13b8cbc 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Baz.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Baz.txtar @@ -67,17 +67,6 @@ enum Baz { ], "leadingComments": " Keep 3: comment on option\n" }, - { - "path": [ - 11, - 0 - ], - "span": [ - 13, - 7, - 11 - ] - }, { "path": [ 5, diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Do.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Do.txtar index 7ffede113d..ced7534362 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Do.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Do.txtar @@ -109,17 +109,6 @@ service Svc { ], "leadingComments": " Keep 3: comment on option\n" }, - { - "path": [ - 11, - 0 - ], - "span": [ - 13, - 7, - 11 - ] - }, { "path": [ 4, diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo+Ext.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo+Ext.txtar index d064f23aae..1a59730f43 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo+Ext.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo+Ext.txtar @@ -413,17 +413,6 @@ extend google.protobuf.MessageOptions { ], "leadingComments": " Keep if ext: comment on import descriptor.proto\n" }, - { - "path": [ - 11, - 0 - ], - "span": [ - 13, - 7, - 11 - ] - }, { "path": [ 7 diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo.txtar index 5829afcda5..9e8eff80b9 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Foo.txtar @@ -75,17 +75,6 @@ message Foo { ], "leadingComments": " Keep 3: comment on option\n" }, - { - "path": [ - 11, - 0 - ], - "span": [ - 13, - 7, - 11 - ] - }, { "path": [ 4, diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/NestedFoo.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/NestedFoo.txtar index 88dbab3dde..3c83914b74 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/NestedFoo.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/NestedFoo.txtar @@ -243,26 +243,26 @@ message Foo { }, { "path": [ - 11, + 3, 0 ], "span": [ - 13, - 7, - 11 - ] + 16, + 0, + 40 + ], + "leadingComments": " Keep if NestedFoo: comment on import any.proto\n" }, { "path": [ - 3, + 11, 0 ], "span": [ 16, - 0, - 40 - ], - "leadingComments": " Keep if NestedFoo: comment on import any.proto\n" + 7, + 11 + ] }, { "path": [ diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Quz.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Quz.txtar index 37b4a3a678..deee0b85bb 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Quz.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Quz.txtar @@ -65,17 +65,6 @@ enum Quz { ], "leadingComments": " Keep 3: comment on option\n" }, - { - "path": [ - 11, - 0 - ], - "span": [ - 13, - 7, - 11 - ] - }, { "path": [ 5, diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Svc.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Svc.txtar index ccb9aaf131..7901a8ab25 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Svc.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/Svc.txtar @@ -111,17 +111,6 @@ service Svc { ], "leadingComments": " Keep 3: comment on option\n" }, - { - "path": [ - 11, - 0 - ], - "span": [ - 13, - 7, - 11 - ] - }, { "path": [ 4, diff --git a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/all.txtar b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/all.txtar index e0fe2b85b5..9fe16809c8 100644 --- a/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/all.txtar +++ b/private/bufpkg/bufimage/bufimageutil/testdata/sourcecodeinfo/all.txtar @@ -672,17 +672,6 @@ extend google.protobuf.ServiceOptions { ], "leadingComments": " Keep if ext: comment on import descriptor.proto\n" }, - { - "path": [ - 11, - 0 - ], - "span": [ - 13, - 7, - 11 - ] - }, { "path": [ 3, @@ -695,6 +684,17 @@ extend google.protobuf.ServiceOptions { ], "leadingComments": " Keep if NestedFoo: comment on import any.proto\n" }, + { + "path": [ + 11, + 0 + ], + "span": [ + 16, + 7, + 11 + ] + }, { "path": [ 7 From de5325e96145536a3176a7d14289721d07b7c9ec Mon Sep 17 00:00:00 2001 From: Josh Humphries <2035234+jhump@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:03:48 -0500 Subject: [PATCH 4/4] make linter happy --- .golangci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index 32d2449c2c..66c1b84d4c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -476,6 +476,12 @@ linters: # and should be considered safe. path: private/bufpkg/bufcobra/markdown.go text: "printf: non-constant format string in call to p" + - linters: + - gosec + # This converts slice indexes in a FileDescriptorProto to int32, + # which are not an actual risk of overflow. + path: private/bufpkg/bufimage/bufimageutil/image_filter.go + text: "G115:" issues: max-same-issues: 0