Explicitly reject fields that are closed enums with implicit presence in Java generators.

The normal case of this is already rejected by the .proto parser, this additional check covers legacy_closed_enum cases. Those cases will otherwise reach a CHECK-fail, this just makes for a clearer error message that this is simply a disallowed combination.

PiperOrigin-RevId: 696648744
pull/19269/head
Protobuf Team Bot 3 weeks ago committed by Copybara-Service
parent 251f5ee66e
commit ed480662ed
  1. 17
      csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs
  2. 11
      src/google/protobuf/compiler/java/file.cc
  3. 22
      src/google/protobuf/compiler/java/generator_unittest.cc

@ -1,17 +0,0 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#endregion
namespace Google.Protobuf.Reflection;
internal sealed partial class FeatureSetDescriptor
{
// Canonical serialized form of the edition defaults, generated by embed_edition_defaults.
private const string DefaultsBase64 =
"ChMYhAciACoMCAEQAhgCIAMoATACChMY5wciACoMCAIQARgBIAIoATABChMY6AciDAgBEAEYASACKAEwASoAIOYHKOgH";
}

@ -240,6 +240,17 @@ bool FileGenerator::Validate(std::string* error) {
<< "name for the .proto file to be safe.";
}
// Check that no field is a closed enum with implicit presence. For normal
// cases this will be rejected by protoc before the generator is invoked, but
// for cases like legacy_closed_enum it may reach the generator.
google::protobuf::internal::VisitDescriptors(*file_, [&](const FieldDescriptor& field) {
if (field.enum_type() != nullptr && !SupportUnknownEnumValue(&field) &&
!field.has_presence() && !field.is_repeated()) {
absl::StrAppend(error, "Field ", field.full_name(),
" has a closed enum type with implicit presence.\n");
}
});
// Print a warning if optimize_for = LITE_RUNTIME is used.
if (file_->options().optimize_for() == FileOptions::LITE_RUNTIME &&
!options_.enforce_lite) {

@ -65,6 +65,28 @@ TEST_F(JavaGeneratorTest, BasicError) {
"foo.proto:4:7: Expected \"required\", \"optional\", or \"repeated\"");
}
TEST_F(JavaGeneratorTest, ImplicitPresenceLegacyClosedEnumDisallowed) {
CreateTempFile("foo.proto",
R"schema(
edition = "2023";
import "third_party/java/protobuf/java_features.proto";
option features.field_presence = IMPLICIT;
enum Bar {
AAA = 0;
}
message Foo {
Bar bar = 1 [features.(pb.java).legacy_closed_enum = true];
}
)schema");
RunProtoc(
"protocol_compiler --proto_path=$tmpdir --java_out=$tmpdir foo.proto");
ExpectErrorSubstring(
"foo.proto: Field Foo.bar has a closed enum type with implicit "
"presence.");
}
} // namespace
} // namespace java

Loading…
Cancel
Save