1212#include < string>
1313#include < vector>
1414
15- #include " google/protobuf/compiler/code_generator.h"
1615#include " absl/container/flat_hash_map.h"
1716#include " absl/container/flat_hash_set.h"
1817#include " absl/log/absl_log.h"
2221#include " absl/strings/str_replace.h"
2322#include " absl/strings/str_split.h"
2423#include " absl/strings/string_view.h"
24+ #include " google/protobuf/compiler/code_generator.h"
25+ #include " google/protobuf/compiler/php/names.h"
2526#include " google/protobuf/compiler/retention.h"
2627#include " google/protobuf/descriptor.h"
2728#include " google/protobuf/descriptor.pb.h"
28- #include " google/protobuf/descriptor_legacy.h"
2929#include " google/protobuf/io/printer.h"
3030#include " google/protobuf/io/zero_copy_stream.h"
3131
@@ -537,16 +537,28 @@ void Outdent(io::Printer* printer) {
537537 printer->Outdent ();
538538}
539539
540- void GenerateField (const FieldDescriptor* field, io::Printer* printer,
541- const Options& options) {
540+ bool GenerateField (const FieldDescriptor* field, io::Printer* printer,
541+ const Options& options, std::string* error) {
542+ if (field->is_required ()) {
543+ *error = absl::StrCat (" Can't generate PHP code for required field " ,
544+ field->full_name (), " .\n " );
545+ return false ;
546+ }
547+ if (field->type () == FieldDescriptor::TYPE_GROUP) {
548+ *error = absl::StrCat (" Can't generate PHP code for group field " ,
549+ field->full_name (),
550+ " . Use regular message encoding instead.\n " );
551+ return false ;
552+ }
553+
542554 if (field->is_repeated ()) {
543555 GenerateFieldDocComment (printer, field, options, kFieldProperty );
544556 printer->Print (
545557 " private $^name^;\n " ,
546558 " name" , field->name ());
547559 } else if (field->real_containing_oneof ()) {
548560 // Oneof fields are handled by GenerateOneofField.
549- return ;
561+ return true ;
550562 } else {
551563 std::string initial_value =
552564 field->has_presence () ? " null" : DefaultForField (field);
@@ -556,6 +568,7 @@ void GenerateField(const FieldDescriptor* field, io::Printer* printer,
556568 " name" , field->name (),
557569 " initial_value" , initial_value);
558570 }
571+ return true ;
559572}
560573
561574void GenerateOneofField (const OneofDescriptor* oneof, io::Printer* printer) {
@@ -1270,9 +1283,17 @@ void LegacyReadOnlyGenerateClassFile(const FileDescriptor* file,
12701283 " fullname" , classname);
12711284}
12721285
1273- void GenerateEnumFile (const FileDescriptor* file, const EnumDescriptor* en,
1286+ bool GenerateEnumFile (const FileDescriptor* file, const EnumDescriptor* en,
12741287 const Options& options,
1275- GeneratorContext* generator_context) {
1288+ GeneratorContext* generator_context, std::string* error) {
1289+ if (en->is_closed ()) {
1290+ *error = absl::StrCat (" Can't generate PHP code for closed enum " ,
1291+ en->full_name (),
1292+ " . Please use either proto3 or editions without "
1293+ " `enum_type = CLOSED`.\n " );
1294+ return false ;
1295+ }
1296+
12761297 std::string filename = GeneratedClassFileName (en, options);
12771298 std::unique_ptr<io::ZeroCopyOutputStream> output (
12781299 generator_context->Open (filename));
@@ -1403,15 +1424,18 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
14031424 " old" , en->name ());
14041425 LegacyReadOnlyGenerateClassFile (file, en, options, generator_context);
14051426 }
1427+
1428+ return true ;
14061429}
14071430
1408- void GenerateMessageFile (const FileDescriptor* file, const Descriptor* message,
1431+ bool GenerateMessageFile (const FileDescriptor* file, const Descriptor* message,
14091432 const Options& options,
1410- GeneratorContext* generator_context) {
1433+ GeneratorContext* generator_context,
1434+ std::string* error) {
14111435 // Don't generate MapEntry messages -- we use the PHP extension's native
14121436 // support for map fields instead.
14131437 if (message->options ().map_entry ()) {
1414- return ;
1438+ return true ;
14151439 }
14161440
14171441 std::string filename = GeneratedClassFileName (message, options);
@@ -1461,7 +1485,9 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
14611485 // Field and oneof definitions.
14621486 for (int i = 0 ; i < message->field_count (); i++) {
14631487 const FieldDescriptor* field = message->field (i);
1464- GenerateField (field, &printer, options);
1488+ if (!GenerateField (field, &printer, options, error)) {
1489+ return false ;
1490+ }
14651491 }
14661492 for (int i = 0 ; i < message->real_oneof_decl_count (); i++) {
14671493 const OneofDescriptor* oneof = message->oneof_decl (i);
@@ -1533,12 +1559,18 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
15331559
15341560 // Nested messages and enums.
15351561 for (int i = 0 ; i < message->nested_type_count (); i++) {
1536- GenerateMessageFile (file, message->nested_type (i), options,
1537- generator_context);
1562+ if (!GenerateMessageFile (file, message->nested_type (i), options,
1563+ generator_context, error)) {
1564+ return false ;
1565+ }
15381566 }
15391567 for (int i = 0 ; i < message->enum_type_count (); i++) {
1540- GenerateEnumFile (file, message->enum_type (i), options, generator_context);
1568+ if (!GenerateEnumFile (file, message->enum_type (i), options,
1569+ generator_context, error)) {
1570+ return false ;
1571+ }
15411572 }
1573+ return true ;
15421574}
15431575
15441576void GenerateServiceFile (
@@ -1588,22 +1620,29 @@ void GenerateServiceFile(
15881620 printer.Print (" }\n\n " );
15891621}
15901622
1591- void GenerateFile (const FileDescriptor* file, const Options& options,
1592- GeneratorContext* generator_context) {
1623+ bool GenerateFile (const FileDescriptor* file, const Options& options,
1624+ GeneratorContext* generator_context, std::string* error ) {
15931625 GenerateMetadataFile (file, options, generator_context);
15941626
15951627 for (int i = 0 ; i < file->message_type_count (); i++) {
1596- GenerateMessageFile (file, file->message_type (i), options,
1597- generator_context);
1628+ if (!GenerateMessageFile (file, file->message_type (i), options,
1629+ generator_context, error)) {
1630+ return false ;
1631+ }
15981632 }
15991633 for (int i = 0 ; i < file->enum_type_count (); i++) {
1600- GenerateEnumFile (file, file->enum_type (i), options, generator_context);
1634+ if (!GenerateEnumFile (file, file->enum_type (i), options, generator_context,
1635+ error)) {
1636+ return false ;
1637+ }
16011638 }
16021639 if (file->options ().php_generic_services ()) {
16031640 for (int i = 0 ; i < file->service_count (); i++) {
16041641 GenerateServiceFile (file, file->service (i), options, generator_context);
16051642 }
16061643 }
1644+
1645+ return true ;
16071646}
16081647
16091648static std::string EscapePhpdoc (absl::string_view input) {
@@ -2283,18 +2322,7 @@ bool Generator::Generate(const FileDescriptor* file, const Options& options,
22832322 return false ;
22842323 }
22852324
2286- if (!options.is_descriptor &&
2287- FileDescriptorLegacy (file).syntax () !=
2288- FileDescriptorLegacy::Syntax::SYNTAX_PROTO3) {
2289- *error =
2290- " Can only generate PHP code for proto3 .proto files.\n "
2291- " Please add 'syntax = \" proto3\" ;' to the top of your .proto file.\n " ;
2292- return false ;
2293- }
2294-
2295- GenerateFile (file, options, generator_context);
2296-
2297- return true ;
2325+ return GenerateFile (file, options, generator_context, error);
22982326}
22992327
23002328bool Generator::GenerateAll (const std::vector<const FileDescriptor*>& files,
0 commit comments