Force plugins to specify their edition support window.

This is similar to what we did for built-in generators, and gives us the ability to create a new edition without subtley breaking generators that don't support it yet.

PiperOrigin-RevId: 586756816
pull/14916/head
Mike Kruskal 2023-11-30 12:38:49 -08:00 committed by Copybara-Service
parent c793ec4631
commit cba41100fb
13 changed files with 366 additions and 49 deletions

View File

@ -2551,29 +2551,43 @@ bool CommandLineInterface::EnforceProto3OptionalSupport(
bool CommandLineInterface::EnforceEditionsSupport(
const std::string& codegen_name, uint64_t supported_features,
Edition minimum_edition, Edition maximum_edition,
const std::vector<const FileDescriptor*>& parsed_files) const {
if (supported_features & CodeGenerator::FEATURE_SUPPORTS_EDITIONS) {
// This generator explicitly supports editions.
return true;
}
if (experimental_editions_) {
// The user has explicitly specified the experimental flag.
return true;
}
for (const auto* fd : parsed_files) {
if (fd->edition() < Edition::EDITION_2023) {
// Legacy proto2/proto3 files don't need any checks.
continue;
}
// Skip enforcement for allowlisted files.
if (IsEarlyEditionsFile(fd->name())) continue;
if (FileDescriptorLegacy(fd).syntax() ==
FileDescriptorLegacy::SYNTAX_EDITIONS) {
std::cerr
<< fd->name() << ": is an editions file, but code generator "
<< codegen_name
<< " hasn't been updated to support editions yet. Please ask "
"the owner of this code generator to add support or "
"switch back to proto2/proto3.\n\nSee "
"https://protobuf.dev/editions/overview/ for more information."
<< std::endl;
if ((supported_features & CodeGenerator::FEATURE_SUPPORTS_EDITIONS) == 0) {
std::cerr << absl::Substitute(
"$0: is an editions file, but code generator $1 hasn't been "
"updated to support editions yet. Please ask the owner of this code "
"generator to add support or switch back to proto2/proto3.\n\nSee "
"https://protobuf.dev/editions/overview/ for more information.",
fd->name(), codegen_name);
return false;
}
if (fd->edition() < minimum_edition) {
std::cerr << absl::Substitute(
"$0: is a file using edition $2, which isn't supported by code "
"generator $1. Please upgrade your file to at least edition $3.",
fd->name(), codegen_name, fd->edition(), minimum_edition);
return false;
}
if (fd->edition() > maximum_edition) {
std::cerr << absl::Substitute(
"$0: is a file using edition $2, which isn't supported by code "
"generator $1. Please ask the owner of this code generator to add "
"support or switch back to a maximum of edition $3.",
fd->name(), codegen_name, fd->edition(), maximum_edition);
return false;
}
}
@ -2622,7 +2636,9 @@ bool CommandLineInterface::GenerateOutput(
if (!EnforceEditionsSupport(
output_directive.name,
output_directive.generator->GetSupportedFeatures(), parsed_files)) {
output_directive.generator->GetSupportedFeatures(),
output_directive.generator->GetMinimumEdition(),
output_directive.generator->GetMaximumEdition(), parsed_files)) {
return false;
}
@ -2826,11 +2842,15 @@ bool CommandLineInterface::GeneratePluginOutput(
// Generator returned an error.
*error = response.error();
return false;
} else if (!EnforceProto3OptionalSupport(
plugin_name, response.supported_features(), parsed_files)) {
}
if (!EnforceProto3OptionalSupport(plugin_name, response.supported_features(),
parsed_files)) {
return false;
} else if (!EnforceEditionsSupport(plugin_name, response.supported_features(),
parsed_files)) {
}
if (!EnforceEditionsSupport(plugin_name, response.supported_features(),
static_cast<Edition>(response.minimum_edition()),
static_cast<Edition>(response.maximum_edition()),
parsed_files)) {
return false;
}

View File

@ -224,6 +224,7 @@ class PROTOC_EXPORT CommandLineInterface {
bool EnforceEditionsSupport(
const std::string& codegen_name, uint64_t supported_features,
Edition minimum_edition, Edition maximum_edition,
const std::vector<const FileDescriptor*>& parsed_files) const;

View File

@ -1530,6 +1530,74 @@ TEST_F(CommandLineInterfaceTest, Plugin_InvalidFeatureExtensionError) {
"google.protobuf.FeatureSet");
}
TEST_F(CommandLineInterfaceTest, Plugin_DeprecatedEdition) {
CreateTempFile("foo.proto", R"schema(
edition = "2023";
message Foo {
int32 i = 1;
}
)schema");
SetMockGeneratorTestCase("high_minimum");
Run("protocol_compiler "
"--proto_path=$tmpdir foo.proto --plug_out=$tmpdir");
ExpectErrorSubstring(
"foo.proto: This file uses editions, but --experimental_editions has not "
"been enabled. This syntax is experimental and should be avoided.");
}
TEST_F(CommandLineInterfaceTest, Plugin_FutureEdition) {
CreateTempFile("foo.proto", R"schema(
edition = "2023";
message Foo {
int32 i = 1;
}
)schema");
SetMockGeneratorTestCase("low_maximum");
Run("protocol_compiler "
"--proto_path=$tmpdir foo.proto --plug_out=$tmpdir");
ExpectErrorSubstring(
"foo.proto: This file uses editions, but --experimental_editions has not "
"been enabled. This syntax is experimental and should be avoided.");
}
TEST_F(CommandLineInterfaceTest, Plugin_VersionSkewFuture) {
CreateTempFile("foo.proto", R"schema(
edition = "99997_TEST_ONLY";
message Foo {
int32 i = 1;
}
)schema");
SetMockGeneratorTestCase("high_maximum");
Run("protocol_compiler "
"--proto_path=$tmpdir foo.proto --plug_out=$tmpdir");
ExpectErrorSubstring(
"foo.proto:2:5: Edition 99997_TEST_ONLY is later than the maximum "
"supported edition 2023");
}
TEST_F(CommandLineInterfaceTest, Plugin_VersionSkewPast) {
CreateTempFile("foo.proto", R"schema(
edition = "1_TEST_ONLY";
message Foo {
int32 i = 1;
}
)schema");
SetMockGeneratorTestCase("low_minimum");
Run("protocol_compiler "
"--proto_path=$tmpdir foo.proto --plug_out=$tmpdir");
ExpectErrorSubstring(
"foo.proto:2:5: Edition 1_TEST_ONLY is earlier than the minimum "
"supported edition PROTO2");
}
TEST_F(CommandLineInterfaceTest, Plugin_MissingFeatureExtensionError) {
CreateTempFile("foo.proto", R"schema(
edition = "2023";

View File

@ -80,6 +80,10 @@ MockCodeGenerator::MockCodeGenerator(absl::string_view name) : name_(name) {
feature_extensions_ = {nullptr};
} else if (key == "no_feature_defaults") {
feature_extensions_ = {};
} else if (key == "high_maximum") {
maximum_edition_ = Edition::EDITION_99997_TEST_ONLY;
} else if (key == "low_minimum") {
maximum_edition_ = Edition::EDITION_1_TEST_ONLY;
}
}
@ -203,6 +207,15 @@ bool MockCodeGenerator::Generate(const FileDescriptor* file,
const std::string& parameter,
GeneratorContext* context,
std::string* error) const {
// Override minimum/maximum after generating the pool to simulate a plugin
// that "works" but doesn't advertise support of the current edition.
absl::string_view test_case = getenv("TEST_CASE");
if (test_case == "high_minimum") {
minimum_edition_ = Edition::EDITION_99997_TEST_ONLY;
} else if (test_case == "low_maximum") {
maximum_edition_ = Edition::EDITION_PROTO2;
}
if (FileDescriptorLegacy(file).syntax() ==
FileDescriptorLegacy::SYNTAX_EDITIONS &&
(suppressed_features_ & CodeGenerator::FEATURE_SUPPORTS_EDITIONS) == 0) {

View File

@ -119,8 +119,8 @@ class MockCodeGenerator : public CodeGenerator {
private:
std::string name_;
uint64_t suppressed_features_ = 0;
Edition minimum_edition_ = PROTOBUF_MINIMUM_EDITION;
Edition maximum_edition_ = PROTOBUF_MAXIMUM_EDITION;
mutable Edition minimum_edition_ = PROTOBUF_MINIMUM_EDITION;
mutable Edition maximum_edition_ = PROTOBUF_MAXIMUM_EDITION;
std::vector<const FieldDescriptor*> feature_extensions_ = {
GetExtensionReflection(pb::test)};

View File

@ -740,7 +740,9 @@ bool Parser::ParseSyntaxIdentifier(const FileDescriptorProto* file,
if (has_edition) {
if (!Edition_Parse(absl::StrCat("EDITION_", syntax), &edition_) ||
edition_ < Edition::EDITION_2023) {
edition_ == Edition::EDITION_PROTO2 ||
edition_ == Edition::EDITION_PROTO3 ||
edition_ == Edition::EDITION_UNKNOWN) {
RecordError(syntax_token.line, syntax_token.column, [&] {
return absl::StrCat("Unknown edition \"", syntax, "\".");
});

View File

@ -137,6 +137,10 @@ bool GenerateCode(const CodeGeneratorRequest& request,
&context, &error);
response->set_supported_features(generator.GetSupportedFeatures());
response->set_minimum_edition(
static_cast<int>(generator.GetMinimumEdition()));
response->set_maximum_edition(
static_cast<int>(generator.GetMaximumEdition()));
if (!succeeded && error.empty()) {
error =

View File

@ -84,7 +84,9 @@ inline constexpr CodeGeneratorResponse::Impl_::Impl_(
error_(
&::google::protobuf::internal::fixed_address_empty_string,
::_pbi::ConstantInitialized()),
supported_features_{::uint64_t{0u}} {}
supported_features_{::uint64_t{0u}},
minimum_edition_{0},
maximum_edition_{0} {}
template <typename>
PROTOBUF_CONSTEXPR CodeGeneratorResponse::CodeGeneratorResponse(::_pbi::ConstantInitialized)
@ -194,9 +196,13 @@ const ::uint32_t
~0u, // no sizeof(Split)
PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_.error_),
PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_.supported_features_),
PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_.minimum_edition_),
PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_.maximum_edition_),
PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _impl_.file_),
0,
1,
2,
3,
~0u,
};
@ -205,7 +211,7 @@ static const ::_pbi::MigrationSchema
{0, 12, -1, sizeof(::google::protobuf::compiler::Version)},
{16, 29, -1, sizeof(::google::protobuf::compiler::CodeGeneratorRequest)},
{34, 46, -1, sizeof(::google::protobuf::compiler::CodeGeneratorResponse_File)},
{50, 61, -1, sizeof(::google::protobuf::compiler::CodeGeneratorResponse)},
{50, 63, -1, sizeof(::google::protobuf::compiler::CodeGeneratorResponse)},
};
static const ::_pb::Message* const file_default_instances[] = {
@ -226,19 +232,20 @@ const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2epro
"FileDescriptorProto\022E\n\027source_file_descr"
"iptors\030\021 \003(\0132$.google.protobuf.FileDescr"
"iptorProto\022;\n\020compiler_version\030\003 \001(\0132!.g"
"oogle.protobuf.compiler.Version\"\340\002\n\025Code"
"oogle.protobuf.compiler.Version\"\222\003\n\025Code"
"GeneratorResponse\022\r\n\005error\030\001 \001(\t\022\032\n\022supp"
"orted_features\030\002 \001(\004\022B\n\004file\030\017 \003(\01324.goo"
"gle.protobuf.compiler.CodeGeneratorRespo"
"nse.File\032\177\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n\017insert"
"ion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\t\022\?\n\023gene"
"rated_code_info\030\020 \001(\0132\".google.protobuf."
"GeneratedCodeInfo\"W\n\007Feature\022\020\n\014FEATURE_"
"NONE\020\000\022\033\n\027FEATURE_PROTO3_OPTIONAL\020\001\022\035\n\031F"
"EATURE_SUPPORTS_EDITIONS\020\002Br\n\034com.google"
".protobuf.compilerB\014PluginProtosZ)google"
".golang.org/protobuf/types/pluginpb\252\002\030Go"
"ogle.Protobuf.Compiler"
"orted_features\030\002 \001(\004\022\027\n\017minimum_edition\030"
"\003 \001(\005\022\027\n\017maximum_edition\030\004 \001(\005\022B\n\004file\030\017"
" \003(\01324.google.protobuf.compiler.CodeGene"
"ratorResponse.File\032\177\n\004File\022\014\n\004name\030\001 \001(\t"
"\022\027\n\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001"
"(\t\022\?\n\023generated_code_info\030\020 \001(\0132\".google"
".protobuf.GeneratedCodeInfo\"W\n\007Feature\022\020"
"\n\014FEATURE_NONE\020\000\022\033\n\027FEATURE_PROTO3_OPTIO"
"NAL\020\001\022\035\n\031FEATURE_SUPPORTS_EDITIONS\020\002Br\n\034"
"com.google.protobuf.compilerB\014PluginProt"
"osZ)google.golang.org/protobuf/types/plu"
"ginpb\252\002\030Google.Protobuf.Compiler"
};
static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] =
{
@ -248,7 +255,7 @@ static ::absl::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_
const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto = {
false,
false,
902,
952,
descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
"google/protobuf/compiler/plugin.proto",
&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
@ -1300,7 +1307,13 @@ CodeGeneratorResponse::CodeGeneratorResponse(
_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(
from._internal_metadata_);
new (&_impl_) Impl_(internal_visibility(), arena, from._impl_);
_impl_.supported_features_ = from._impl_.supported_features_;
::memcpy(reinterpret_cast<char *>(&_impl_) +
offsetof(Impl_, supported_features_),
reinterpret_cast<const char *>(&from._impl_) +
offsetof(Impl_, supported_features_),
offsetof(Impl_, maximum_edition_) -
offsetof(Impl_, supported_features_) +
sizeof(Impl_::maximum_edition_));
// @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse)
}
@ -1313,7 +1326,12 @@ inline PROTOBUF_NDEBUG_INLINE CodeGeneratorResponse::Impl_::Impl_(
inline void CodeGeneratorResponse::SharedCtor(::_pb::Arena* arena) {
new (&_impl_) Impl_(internal_visibility(), arena);
_impl_.supported_features_ = {};
::memset(reinterpret_cast<char *>(&_impl_) +
offsetof(Impl_, supported_features_),
0,
offsetof(Impl_, maximum_edition_) -
offsetof(Impl_, supported_features_) +
sizeof(Impl_::maximum_edition_));
}
CodeGeneratorResponse::~CodeGeneratorResponse() {
// @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse)
@ -1349,7 +1367,11 @@ PROTOBUF_NOINLINE void CodeGeneratorResponse::Clear() {
if (cached_has_bits & 0x00000001u) {
_impl_.error_.ClearNonDefaultToEmpty();
}
_impl_.supported_features_ = ::uint64_t{0u};
if (cached_has_bits & 0x0000000eu) {
::memset(&_impl_.supported_features_, 0, static_cast<::size_t>(
reinterpret_cast<char*>(&_impl_.maximum_edition_) -
reinterpret_cast<char*>(&_impl_.supported_features_)) + sizeof(_impl_.maximum_edition_));
}
_impl_._has_bits_.Clear();
_internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>();
}
@ -1362,15 +1384,15 @@ const char* CodeGeneratorResponse::_InternalParse(
PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1
const ::_pbi::TcParseTable<2, 3, 1, 60, 2> CodeGeneratorResponse::_table_ = {
const ::_pbi::TcParseTable<3, 5, 1, 60, 2> CodeGeneratorResponse::_table_ = {
{
PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_._has_bits_),
0, // no _extensions_
15, 24, // max_field_number, fast_idx_mask
15, 56, // max_field_number, fast_idx_mask
offsetof(decltype(_table_), field_lookup_table),
4294950908, // skipmap
4294950896, // skipmap
offsetof(decltype(_table_), field_entries),
3, // num_field_entries
5, // num_field_entries
1, // num_aux_entries
offsetof(decltype(_table_), aux_entries),
&_CodeGeneratorResponse_default_instance_._instance,
@ -1386,6 +1408,14 @@ const ::_pbi::TcParseTable<2, 3, 1, 60, 2> CodeGeneratorResponse::_table_ = {
// optional uint64 supported_features = 2;
{::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(CodeGeneratorResponse, _impl_.supported_features_), 1>(),
{16, 1, 0, PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_.supported_features_)}},
// optional int32 minimum_edition = 3;
{::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(CodeGeneratorResponse, _impl_.minimum_edition_), 2>(),
{24, 2, 0, PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_.minimum_edition_)}},
// optional int32 maximum_edition = 4;
{::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(CodeGeneratorResponse, _impl_.maximum_edition_), 3>(),
{32, 3, 0, PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_.maximum_edition_)}},
{::_pbi::TcParser::MiniParse, {}},
{::_pbi::TcParser::MiniParse, {}},
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
{::_pbi::TcParser::FastMtR1,
{122, 63, 0, PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_.file_)}},
@ -1398,6 +1428,12 @@ const ::_pbi::TcParseTable<2, 3, 1, 60, 2> CodeGeneratorResponse::_table_ = {
// optional uint64 supported_features = 2;
{PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_.supported_features_), _Internal::kHasBitsOffset + 1, 0,
(0 | ::_fl::kFcOptional | ::_fl::kUInt64)},
// optional int32 minimum_edition = 3;
{PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_.minimum_edition_), _Internal::kHasBitsOffset + 2, 0,
(0 | ::_fl::kFcOptional | ::_fl::kInt32)},
// optional int32 maximum_edition = 4;
{PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_.maximum_edition_), _Internal::kHasBitsOffset + 3, 0,
(0 | ::_fl::kFcOptional | ::_fl::kInt32)},
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
{PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_.file_), -1, 0,
(0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)},
@ -1433,6 +1469,20 @@ const ::_pbi::TcParseTable<2, 3, 1, 60, 2> CodeGeneratorResponse::_table_ = {
2, this->_internal_supported_features(), target);
}
// optional int32 minimum_edition = 3;
if (cached_has_bits & 0x00000004u) {
target = ::google::protobuf::internal::WireFormatLite::
WriteInt32ToArrayWithField<3>(
stream, this->_internal_minimum_edition(), target);
}
// optional int32 maximum_edition = 4;
if (cached_has_bits & 0x00000008u) {
target = ::google::protobuf::internal::WireFormatLite::
WriteInt32ToArrayWithField<4>(
stream, this->_internal_maximum_edition(), target);
}
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
for (unsigned i = 0,
n = static_cast<unsigned>(this->_internal_file_size()); i < n; i++) {
@ -1465,7 +1515,7 @@ const ::_pbi::TcParseTable<2, 3, 1, 60, 2> CodeGeneratorResponse::_table_ = {
::google::protobuf::internal::WireFormatLite::MessageSize(msg);
}
cached_has_bits = _impl_._has_bits_[0];
if (cached_has_bits & 0x00000003u) {
if (cached_has_bits & 0x0000000fu) {
// optional string error = 1;
if (cached_has_bits & 0x00000001u) {
total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize(
@ -1478,6 +1528,18 @@ const ::_pbi::TcParseTable<2, 3, 1, 60, 2> CodeGeneratorResponse::_table_ = {
this->_internal_supported_features());
}
// optional int32 minimum_edition = 3;
if (cached_has_bits & 0x00000004u) {
total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(
this->_internal_minimum_edition());
}
// optional int32 maximum_edition = 4;
if (cached_has_bits & 0x00000008u) {
total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(
this->_internal_maximum_edition());
}
}
return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_);
}
@ -1494,13 +1556,19 @@ void CodeGeneratorResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, c
_this->_internal_mutable_file()->MergeFrom(
from._internal_file());
cached_has_bits = from._impl_._has_bits_[0];
if (cached_has_bits & 0x00000003u) {
if (cached_has_bits & 0x0000000fu) {
if (cached_has_bits & 0x00000001u) {
_this->_internal_set_error(from._internal_error());
}
if (cached_has_bits & 0x00000002u) {
_this->_impl_.supported_features_ = from._impl_.supported_features_;
}
if (cached_has_bits & 0x00000004u) {
_this->_impl_.minimum_edition_ = from._impl_.minimum_edition_;
}
if (cached_has_bits & 0x00000008u) {
_this->_impl_.maximum_edition_ = from._impl_.maximum_edition_;
}
}
_this->_impl_._has_bits_[0] |= cached_has_bits;
_this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_);
@ -1525,7 +1593,12 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* PROTOBUF_RESTRIC
swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]);
_impl_.file_.InternalSwap(&other->_impl_.file_);
::_pbi::ArenaStringPtr::InternalSwap(&_impl_.error_, &other->_impl_.error_, arena);
swap(_impl_.supported_features_, other->_impl_.supported_features_);
::google::protobuf::internal::memswap<
PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_.maximum_edition_)
+ sizeof(CodeGeneratorResponse::_impl_.maximum_edition_)
- PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_.supported_features_)>(
reinterpret_cast<char*>(&_impl_.supported_features_),
reinterpret_cast<char*>(&other->_impl_.supported_features_));
}
::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const {

View File

@ -708,6 +708,8 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes
kFileFieldNumber = 15,
kErrorFieldNumber = 1,
kSupportedFeaturesFieldNumber = 2,
kMinimumEditionFieldNumber = 3,
kMaximumEditionFieldNumber = 4,
};
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
int file_size() const;
@ -753,13 +755,35 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes
::uint64_t _internal_supported_features() const;
void _internal_set_supported_features(::uint64_t value);
public:
// optional int32 minimum_edition = 3;
bool has_minimum_edition() const;
void clear_minimum_edition() ;
::int32_t minimum_edition() const;
void set_minimum_edition(::int32_t value);
private:
::int32_t _internal_minimum_edition() const;
void _internal_set_minimum_edition(::int32_t value);
public:
// optional int32 maximum_edition = 4;
bool has_maximum_edition() const;
void clear_maximum_edition() ;
::int32_t maximum_edition() const;
void set_maximum_edition(::int32_t value);
private:
::int32_t _internal_maximum_edition() const;
void _internal_set_maximum_edition(::int32_t value);
public:
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
private:
class _Internal;
friend class ::google::protobuf::internal::TcParser;
static const ::google::protobuf::internal::TcParseTable<
2, 3, 1,
3, 5, 1,
60, 2>
_table_;
friend class ::google::protobuf::MessageLite;
@ -780,6 +804,8 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
::google::protobuf::internal::ArenaStringPtr error_;
::uint64_t supported_features_;
::int32_t minimum_edition_;
::int32_t maximum_edition_;
PROTOBUF_TSAN_DECLARE_MEMBER
};
union { Impl_ _impl_; };
@ -1990,6 +2016,62 @@ inline void CodeGeneratorResponse::_internal_set_supported_features(::uint64_t v
_impl_.supported_features_ = value;
}
// optional int32 minimum_edition = 3;
inline bool CodeGeneratorResponse::has_minimum_edition() const {
bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
return value;
}
inline void CodeGeneratorResponse::clear_minimum_edition() {
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
_impl_.minimum_edition_ = 0;
_impl_._has_bits_[0] &= ~0x00000004u;
}
inline ::int32_t CodeGeneratorResponse::minimum_edition() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.minimum_edition)
return _internal_minimum_edition();
}
inline void CodeGeneratorResponse::set_minimum_edition(::int32_t value) {
_internal_set_minimum_edition(value);
_impl_._has_bits_[0] |= 0x00000004u;
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.minimum_edition)
}
inline ::int32_t CodeGeneratorResponse::_internal_minimum_edition() const {
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
return _impl_.minimum_edition_;
}
inline void CodeGeneratorResponse::_internal_set_minimum_edition(::int32_t value) {
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
_impl_.minimum_edition_ = value;
}
// optional int32 maximum_edition = 4;
inline bool CodeGeneratorResponse::has_maximum_edition() const {
bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
return value;
}
inline void CodeGeneratorResponse::clear_maximum_edition() {
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
_impl_.maximum_edition_ = 0;
_impl_._has_bits_[0] &= ~0x00000008u;
}
inline ::int32_t CodeGeneratorResponse::maximum_edition() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.maximum_edition)
return _internal_maximum_edition();
}
inline void CodeGeneratorResponse::set_maximum_edition(::int32_t value) {
_internal_set_maximum_edition(value);
_impl_._has_bits_[0] |= 0x00000008u;
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.maximum_edition)
}
inline ::int32_t CodeGeneratorResponse::_internal_maximum_edition() const {
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
return _impl_.maximum_edition_;
}
inline void CodeGeneratorResponse::_internal_set_maximum_edition(::int32_t value) {
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
_impl_.maximum_edition_ = value;
}
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
inline int CodeGeneratorResponse::_internal_file_size() const {
return _internal_file().size();

View File

@ -102,6 +102,18 @@ message CodeGeneratorResponse {
FEATURE_SUPPORTS_EDITIONS = 2;
}
// The minimum edition this plugin supports. This will be treated as an
// Edition enum, but we want to allow unknown values. It should be specified
// according the edition enum value, *not* the edition number. Only takes
// effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
optional int32 minimum_edition = 3;
// The maximum edition this plugin supports. This will be treated as an
// Edition enum, but we want to allow unknown values. It should be specified
// according the edition enum value, *not* the edition number. Only takes
// effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
optional int32 maximum_edition = 4;
// Represents a single generated file.
message File {
// The file name, relative to the output directory. The name must not

View File

@ -170,6 +170,10 @@ class Plugin {
UPB_DESC(compiler_CodeGeneratorResponse_FEATURE_SUPPORTS_EDITIONS);
UPB_DESC(compiler_CodeGeneratorResponse_set_supported_features)
(response_, features);
UPB_DESC(compiler_CodeGeneratorResponse_set_minimum_edition)
(response_, UPB_DESC(EDITION_PROTO2));
UPB_DESC(compiler_CodeGeneratorResponse_set_maximum_edition)
(response_, UPB_DESC(EDITION_2023));
}
void WriteResponse() {

View File

@ -34,7 +34,7 @@ const upb_MiniTable* google__protobuf__compiler__CodeGeneratorRequest_msg_init()
const upb_MiniTable* google__protobuf__compiler__CodeGeneratorResponse_msg_init() {
static upb_MiniTable* mini_table = NULL;
static const char* mini_descriptor = "$1,lG";
static const char* mini_descriptor = "$1,((jG";
if (mini_table) return mini_table;
mini_table =
upb_MiniTable_Build(mini_descriptor, strlen(mini_descriptor),

View File

@ -488,6 +488,36 @@ UPB_INLINE bool google_protobuf_compiler_CodeGeneratorResponse_has_supported_fea
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 2);
return _upb_Message_HasNonExtensionField(msg, &field);
}
UPB_INLINE void google_protobuf_compiler_CodeGeneratorResponse_clear_minimum_edition(google_protobuf_compiler_CodeGeneratorResponse* msg) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 3);
_upb_Message_ClearNonExtensionField(msg, &field);
}
UPB_INLINE int32_t google_protobuf_compiler_CodeGeneratorResponse_minimum_edition(const google_protobuf_compiler_CodeGeneratorResponse* msg) {
int32_t default_val = (int32_t)0;
int32_t ret;
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 3);
_upb_Message_GetNonExtensionField(msg, &field, &default_val, &ret);
return ret;
}
UPB_INLINE bool google_protobuf_compiler_CodeGeneratorResponse_has_minimum_edition(const google_protobuf_compiler_CodeGeneratorResponse* msg) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 3);
return _upb_Message_HasNonExtensionField(msg, &field);
}
UPB_INLINE void google_protobuf_compiler_CodeGeneratorResponse_clear_maximum_edition(google_protobuf_compiler_CodeGeneratorResponse* msg) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 4);
_upb_Message_ClearNonExtensionField(msg, &field);
}
UPB_INLINE int32_t google_protobuf_compiler_CodeGeneratorResponse_maximum_edition(const google_protobuf_compiler_CodeGeneratorResponse* msg) {
int32_t default_val = (int32_t)0;
int32_t ret;
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 4);
_upb_Message_GetNonExtensionField(msg, &field, &default_val, &ret);
return ret;
}
UPB_INLINE bool google_protobuf_compiler_CodeGeneratorResponse_has_maximum_edition(const google_protobuf_compiler_CodeGeneratorResponse* msg) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 4);
return _upb_Message_HasNonExtensionField(msg, &field);
}
UPB_INLINE void google_protobuf_compiler_CodeGeneratorResponse_clear_file(google_protobuf_compiler_CodeGeneratorResponse* msg) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 15);
_upb_Message_ClearNonExtensionField(msg, &field);
@ -534,6 +564,14 @@ UPB_INLINE void google_protobuf_compiler_CodeGeneratorResponse_set_supported_fea
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 2);
_upb_Message_SetNonExtensionField(msg, &field, &value);
}
UPB_INLINE void google_protobuf_compiler_CodeGeneratorResponse_set_minimum_edition(google_protobuf_compiler_CodeGeneratorResponse *msg, int32_t value) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 3);
_upb_Message_SetNonExtensionField(msg, &field, &value);
}
UPB_INLINE void google_protobuf_compiler_CodeGeneratorResponse_set_maximum_edition(google_protobuf_compiler_CodeGeneratorResponse *msg, int32_t value) {
const upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 4);
_upb_Message_SetNonExtensionField(msg, &field, &value);
}
UPB_INLINE google_protobuf_compiler_CodeGeneratorResponse_File** google_protobuf_compiler_CodeGeneratorResponse_mutable_file(google_protobuf_compiler_CodeGeneratorResponse* msg, size_t* size) {
upb_MiniTableField field = *upb_MiniTable_FindFieldByNumber(google__protobuf__compiler__CodeGeneratorResponse_msg_init(), 15);
upb_Array* arr = upb_Message_GetMutableArray(msg, &field);