Forráskód Böngészése

Created Options struct for PHP codegen options.

Joshua Haberman 5 éve
szülő
commit
f1256df893

+ 167 - 153
src/google/protobuf/compiler/php/php_generator.cc

@@ -78,34 +78,39 @@ namespace protobuf {
 namespace compiler {
 namespace php {
 
+struct Options {
+  bool is_descriptor = false;
+  bool aggregate_metadata = false;
+  std::set<string> aggregate_metadata_prefixes;
+};
+
 namespace {
 
 // Forward decls.
-std::string PhpName(const std::string& full_name, bool is_descriptor);
+std::string PhpName(const std::string& full_name, const Options& options);
 std::string IntToString(int32 value);
 std::string FilenameToClassname(const string& filename);
 std::string GeneratedMetadataFileName(const FileDescriptor* file,
-                                      bool is_descriptor);
+                                      const Options& options);
 std::string UnderscoresToCamelCase(const string& name, bool cap_first_letter);
 std::string BinaryToHex(const string& binary);
 void Indent(io::Printer* printer);
 void Outdent(io::Printer* printer);
-void GenerateAddFilesToPool(const FileDescriptor* file,
-                            const std::set<string>& aggregate_metadata_prefixes,
+void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options,
                             io::Printer* printer);
 void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message,
-                               int is_descriptor);
+                               const Options& options);
 void GenerateMessageConstructorDocComment(io::Printer* printer,
                                           const Descriptor* message,
-                                          int is_descriptor);
+                                          const Options& options);
 void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
-                             int is_descriptor, int function_type);
+                             const Options& options, int function_type);
 void GenerateWrapperFieldGetterDocComment(io::Printer* printer,
                                           const FieldDescriptor* field);
 void GenerateWrapperFieldSetterDocComment(io::Printer* printer,
                                           const FieldDescriptor* field);
 void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
-                            int is_descriptor);
+                            const Options& options);
 void GenerateEnumValueDocComment(io::Printer* printer,
                                  const EnumValueDescriptor* value);
 void GenerateServiceDocComment(io::Printer* printer,
@@ -139,8 +144,8 @@ std::string ReservedNamePrefix(const string& classname,
 }
 
 template <typename DescriptorType>
-std::string DescriptorFullName(const DescriptorType* desc, bool is_descriptor) {
-  if (is_descriptor) {
+std::string DescriptorFullName(const DescriptorType* desc, bool is_internal) {
+  if (is_internal) {
     return StringReplace(desc->full_name(),
                          "google.protobuf",
                          "google.protobuf.internal", false);
@@ -229,7 +234,8 @@ std::string ConstantNamePrefix(const string& classname) {
 }
 
 template <typename DescriptorType>
-std::string RootPhpNamespace(const DescriptorType* desc, bool is_descriptor) {
+std::string RootPhpNamespace(const DescriptorType* desc,
+                             const Options& options) {
   if (desc->file()->options().has_php_namespace()) {
     const string& php_namespace = desc->file()->options().php_namespace();
     if (!php_namespace.empty()) {
@@ -239,15 +245,15 @@ std::string RootPhpNamespace(const DescriptorType* desc, bool is_descriptor) {
   }
 
   if (!desc->file()->package().empty()) {
-    return PhpName(desc->file()->package(), is_descriptor);
+    return PhpName(desc->file()->package(), options);
   }
   return "";
 }
 
 template <typename DescriptorType>
-std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
+std::string FullClassName(const DescriptorType* desc, const Options& options) {
   string classname = GeneratedClassNameImpl(desc);
-  string php_namespace = RootPhpNamespace(desc, is_descriptor);
+  string php_namespace = RootPhpNamespace(desc, options);
   if (!php_namespace.empty()) {
     return php_namespace + "\\" + classname;
   }
@@ -255,17 +261,25 @@ std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
 }
 
 template <typename DescriptorType>
-std::string LegacyFullClassName(const DescriptorType* desc, bool is_descriptor) {
+std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
+  Options options;
+  options.is_descriptor = is_descriptor;
+  return FullClassName(desc, options);
+}
+
+template <typename DescriptorType>
+std::string LegacyFullClassName(const DescriptorType* desc,
+                                const Options& options) {
   string classname = LegacyGeneratedClassName(desc);
-  string php_namespace = RootPhpNamespace(desc, is_descriptor);
+  string php_namespace = RootPhpNamespace(desc, options);
   if (!php_namespace.empty()) {
     return php_namespace + "\\" + classname;
   }
   return classname;
 }
 
-std::string PhpName(const std::string& full_name, bool is_descriptor) {
-  if (is_descriptor) {
+std::string PhpName(const std::string& full_name, const Options& options) {
+  if (options.is_descriptor) {
     return kDescriptorPackageName;
   }
 
@@ -314,7 +328,7 @@ std::string DefaultForField(const FieldDescriptor* field) {
 }
 
 std::string GeneratedMetadataFileName(const FileDescriptor* file,
-                                      bool is_descriptor) {
+                                      const Options& options) {
   const string& proto_file = file->name();
   int start_index = 0;
   int first_index = proto_file.find_first_of("/", start_index);
@@ -324,7 +338,7 @@ std::string GeneratedMetadataFileName(const FileDescriptor* file,
   if (proto_file == kEmptyFile) {
     return kEmptyMetadataFile;
   }
-  if (is_descriptor) {
+  if (options.is_descriptor) {
     return kDescriptorMetadataFile;
   }
 
@@ -371,10 +385,17 @@ std::string GeneratedMetadataFileName(const FileDescriptor* file,
   return result + ReservedNamePrefix(segment, file) + segment + ".php";
 }
 
+std::string GeneratedMetadataFileName(const FileDescriptor* file,
+                                      bool is_descriptor) {
+  Options options;
+  options.is_descriptor = is_descriptor;
+  return GeneratedMetadataFileName(file, options);
+}
+
 template <typename DescriptorType>
 std::string GeneratedClassFileName(const DescriptorType* desc,
-                                     bool is_descriptor) {
-  std::string result = FullClassName(desc, is_descriptor);
+                                   const Options& options) {
+  std::string result = FullClassName(desc, options);
   for (int i = 0; i < result.size(); i++) {
     if (result[i] == '\\') {
       result[i] = '/';
@@ -385,8 +406,8 @@ std::string GeneratedClassFileName(const DescriptorType* desc,
 
 template <typename DescriptorType>
 std::string LegacyGeneratedClassFileName(const DescriptorType* desc,
-                                     bool is_descriptor) {
-  std::string result = LegacyFullClassName(desc, is_descriptor);
+                                         const Options& options) {
+  std::string result = LegacyFullClassName(desc, options);
 
   for (int i = 0; i < result.size(); i++) {
     if (result[i] == '\\') {
@@ -397,8 +418,8 @@ std::string LegacyGeneratedClassFileName(const DescriptorType* desc,
 }
 
 std::string GeneratedServiceFileName(const ServiceDescriptor* service,
-                                    bool is_descriptor) {
-  std::string result = FullClassName(service, is_descriptor) + "Interface";
+                                     const Options& options) {
+  std::string result = FullClassName(service, options) + "Interface";
   for (int i = 0; i < result.size(); i++) {
     if (result[i] == '\\') {
       result[i] = '/';
@@ -422,7 +443,8 @@ std::string LabelForField(const FieldDescriptor* field) {
   }
 }
 
-std::string PhpSetterTypeName(const FieldDescriptor* field, bool is_descriptor) {
+std::string PhpSetterTypeName(const FieldDescriptor* field,
+                              const Options& options) {
   if (field->is_map()) {
     return "array|\\Google\\Protobuf\\Internal\\MapField";
   }
@@ -455,7 +477,7 @@ std::string PhpSetterTypeName(const FieldDescriptor* field, bool is_descriptor)
       type = "string";
       break;
     case FieldDescriptor::TYPE_MESSAGE:
-      type = "\\" + FullClassName(field->message_type(), is_descriptor);
+      type = "\\" + FullClassName(field->message_type(), options);
       break;
     case FieldDescriptor::TYPE_GROUP:
       return "null";
@@ -472,7 +494,15 @@ std::string PhpSetterTypeName(const FieldDescriptor* field, bool is_descriptor)
   return type;
 }
 
-std::string PhpGetterTypeName(const FieldDescriptor* field, bool is_descriptor) {
+std::string PhpSetterTypeName(const FieldDescriptor* field,
+                              bool is_descriptor) {
+  Options options;
+  options.is_descriptor = is_descriptor;
+  return PhpSetterTypeName(field, options);
+}
+
+std::string PhpGetterTypeName(const FieldDescriptor* field,
+                              const Options& options) {
   if (field->is_map()) {
     return "\\Google\\Protobuf\\Internal\\MapField";
   }
@@ -497,23 +527,40 @@ std::string PhpGetterTypeName(const FieldDescriptor* field, bool is_descriptor)
     case FieldDescriptor::TYPE_STRING:
     case FieldDescriptor::TYPE_BYTES: return "string";
     case FieldDescriptor::TYPE_MESSAGE:
-      return "\\" + FullClassName(field->message_type(), is_descriptor);
+      return "\\" + FullClassName(field->message_type(), options);
     case FieldDescriptor::TYPE_GROUP: return "null";
     default: assert(false); return "";
   }
 }
 
-std::string EnumOrMessageSuffix(
-    const FieldDescriptor* field, bool is_descriptor) {
+std::string PhpGetterTypeName(const FieldDescriptor* field,
+                              bool is_descriptor) {
+  Options options;
+  options.is_descriptor = is_descriptor;
+  return PhpGetterTypeName(field, options);
+}
+
+std::string EnumOrMessageSuffix(const FieldDescriptor* field,
+                                const Options& options) {
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-    return ", '" + DescriptorFullName(field->message_type(), is_descriptor) + "'";
+    return ", '" +
+           DescriptorFullName(field->message_type(), options.is_descriptor) +
+           "'";
   }
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
-    return ", '" + DescriptorFullName(field->enum_type(), is_descriptor) + "'";
+    return ", '" +
+           DescriptorFullName(field->enum_type(), options.is_descriptor) + "'";
   }
   return "";
 }
 
+std::string EnumOrMessageSuffix(const FieldDescriptor* field,
+                                bool is_descriptor) {
+  Options options;
+  options.is_descriptor = is_descriptor;
+  return EnumOrMessageSuffix(field, options);
+}
+
 // Converts a name to camel-case. If cap_first_letter is true, capitalize the
 // first letter.
 std::string UnderscoresToCamelCase(const string& name, bool cap_first_letter) {
@@ -581,9 +628,9 @@ void Outdent(io::Printer* printer) {
 }
 
 void GenerateField(const FieldDescriptor* field, io::Printer* printer,
-                   bool is_descriptor) {
+                   const Options& options) {
   if (field->is_repeated()) {
-    GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty);
+    GenerateFieldDocComment(printer, field, options, kFieldProperty);
     printer->Print(
         "private $^name^;\n",
         "name", field->name());
@@ -593,7 +640,7 @@ void GenerateField(const FieldDescriptor* field, io::Printer* printer,
   } else {
     std::string initial_value =
         field->has_presence() ? "null" : DefaultForField(field);
-    GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty);
+    GenerateFieldDocComment(printer, field, options, kFieldProperty);
     printer->Print(
         "protected $^name^ = ^initial_value^;\n",
         "name", field->name(),
@@ -609,12 +656,12 @@ void GenerateOneofField(const OneofDescriptor* oneof, io::Printer* printer) {
       "name", oneof->name());
 }
 
-void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
+void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
                            io::Printer* printer) {
   const OneofDescriptor* oneof = field->real_containing_oneof();
 
   // Generate getter.
-  GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
+  GenerateFieldDocComment(printer, field, options, kFieldGetter);
 
   if (oneof != NULL) {
     printer->Print(
@@ -671,7 +718,7 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
   }
 
   // Generate setter.
-  GenerateFieldDocComment(printer, field, is_descriptor, kFieldSetter);
+  GenerateFieldDocComment(printer, field, options, kFieldSetter);
   printer->Print(
       "public function set^camel_name^($var)\n"
       "{\n",
@@ -694,12 +741,12 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
       printer->Print(
           ", \\^class_name^);\n",
           "class_name",
-          FullClassName(value->message_type(), is_descriptor) + "::class");
+          FullClassName(value->message_type(), options) + "::class");
     } else if (value->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
       printer->Print(
           ", \\^class_name^);\n",
           "class_name",
-          FullClassName(value->enum_type(), is_descriptor) + "::class");
+          FullClassName(value->enum_type(), options) + "::class");
     } else {
       printer->Print(");\n");
     }
@@ -712,23 +759,23 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
       printer->Print(
           ", \\^class_name^);\n",
           "class_name",
-          FullClassName(field->message_type(), is_descriptor) + "::class");
+          FullClassName(field->message_type(), options) + "::class");
     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
       printer->Print(
           ", \\^class_name^);\n",
           "class_name",
-          FullClassName(field->enum_type(), is_descriptor) + "::class");
+          FullClassName(field->enum_type(), options) + "::class");
     } else {
       printer->Print(");\n");
     }
   } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     printer->Print(
         "GPBUtil::checkMessage($var, \\^class_name^::class);\n",
-        "class_name", FullClassName(field->message_type(), is_descriptor));
+        "class_name", FullClassName(field->message_type(), options));
   } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
     printer->Print(
         "GPBUtil::checkEnum($var, \\^class_name^::class);\n",
-        "class_name", FullClassName(field->enum_type(), is_descriptor));
+        "class_name", FullClassName(field->enum_type(), options));
   } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
     printer->Print(
         "GPBUtil::checkString($var, ^utf8^);\n",
@@ -888,19 +935,15 @@ void GenerateMessageToPool(const string& name_prefix, const Descriptor* message,
   }
 }
 
-void GenerateAddFileToPool(
-    const FileDescriptor* file,
-    bool is_descriptor,
-    bool aggregate_metadata,
-    const std::set<string>& aggregate_metadata_prefixes,
-    io::Printer* printer) {
+void GenerateAddFileToPool(const FileDescriptor* file, const Options& options,
+                           io::Printer* printer) {
   printer->Print(
       "public static $is_initialized = false;\n\n"
       "public static function initOnce() {\n");
   Indent(printer);
 
-  if (aggregate_metadata) {
-    GenerateAddFilesToPool(file, aggregate_metadata_prefixes, printer);
+  if (options.aggregate_metadata) {
+    GenerateAddFilesToPool(file, options, printer);
   } else {
     printer->Print(
         "$pool = \\Google\\Protobuf\\Internal\\"
@@ -909,7 +952,7 @@ void GenerateAddFileToPool(
         "  return;\n"
         "}\n");
 
-    if (is_descriptor) {
+    if (options.is_descriptor) {
       for (int i = 0; i < file->message_type_count(); i++) {
         GenerateMessageToPool("", file->message_type(i), printer);
       }
@@ -929,7 +972,7 @@ void GenerateAddFileToPool(
           continue;
         }
         std::string dependency_filename =
-            GeneratedMetadataFileName(file->dependency(i), is_descriptor);
+            GeneratedMetadataFileName(file->dependency(i), options);
         printer->Print(
             "\\^name^::initOnce();\n",
             "name", FilenameToClassname(dependency_filename));
@@ -1016,12 +1059,12 @@ static void AnalyzeDependencyForFile(
 
 static bool NeedsUnwrapping(
     const FileDescriptor* file,
-    const std::set<string>& aggregate_metadata_prefixes) {
+    const Options& options) {
   bool has_aggregate_metadata_prefix = false;
-  if (aggregate_metadata_prefixes.empty()) {
+  if (options.aggregate_metadata_prefixes.empty()) {
     has_aggregate_metadata_prefix = true;
   } else {
-    for (const auto& prefix : aggregate_metadata_prefixes) {
+    for (const auto& prefix : options.aggregate_metadata_prefixes) {
       if (HasPrefixString(file->package(), prefix)) {
         has_aggregate_metadata_prefix = true;
         break;
@@ -1034,7 +1077,7 @@ static bool NeedsUnwrapping(
 
 void GenerateAddFilesToPool(
     const FileDescriptor* file,
-    const std::set<string>& aggregate_metadata_prefixes,
+    const Options& options,
     io::Printer* printer) {
   printer->Print(
       "$pool = \\Google\\Protobuf\\Internal\\"
@@ -1064,7 +1107,7 @@ void GenerateAddFilesToPool(
       }
     }
 
-    bool needs_aggregate = NeedsUnwrapping(file, aggregate_metadata_prefixes);
+    bool needs_aggregate = NeedsUnwrapping(file, options);
 
     if (needs_aggregate) {
       auto file_proto = sorted_file_set.add_file();
@@ -1089,8 +1132,7 @@ void GenerateAddFilesToPool(
         it->clear_extension();
       }
     } else {
-      std::string dependency_filename =
-          GeneratedMetadataFileName(file, false);
+      std::string dependency_filename = GeneratedMetadataFileName(file, false);
       printer->Print(
           "\\^name^::initOnce();\n",
           "name", FilenameToClassname(dependency_filename));
@@ -1115,8 +1157,8 @@ void GenerateAddFilesToPool(
       "static::$is_initialized = true;\n");
 }
 
-void GenerateUseDeclaration(bool is_descriptor, io::Printer* printer) {
-  if (!is_descriptor) {
+void GenerateUseDeclaration(const Options& options, io::Printer* printer) {
+  if (!options.is_descriptor) {
     printer->Print(
         "use Google\\Protobuf\\Internal\\GPBType;\n"
         "use Google\\Protobuf\\Internal\\RepeatedField;\n"
@@ -1151,12 +1193,9 @@ std::string FilenameToClassname(const string& filename) {
   return result;
 }
 
-void GenerateMetadataFile(const FileDescriptor* file,
-                          bool is_descriptor,
-                          bool aggregate_metadata,
-                          const std::set<string>& aggregate_metadata_prefixes,
+void GenerateMetadataFile(const FileDescriptor* file, const Options& options,
                           GeneratorContext* generator_context) {
-  std::string filename = GeneratedMetadataFileName(file, is_descriptor);
+  std::string filename = GeneratedMetadataFileName(file, options);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
@@ -1183,32 +1222,30 @@ void GenerateMetadataFile(const FileDescriptor* file,
   }
   Indent(&printer);
 
-  GenerateAddFileToPool(file, is_descriptor, aggregate_metadata,
-                        aggregate_metadata_prefixes, &printer);
+  GenerateAddFileToPool(file, options, &printer);
 
   Outdent(&printer);
   printer.Print("}\n\n");
 }
 
 template <typename DescriptorType>
-void LegacyGenerateClassFile(const FileDescriptor* file, const DescriptorType* desc,
-                         bool is_descriptor,
-                         GeneratorContext* generator_context) {
-
-  std::string filename = LegacyGeneratedClassFileName(desc, is_descriptor);
+void LegacyGenerateClassFile(const FileDescriptor* file,
+                             const DescriptorType* desc, const Options& options,
+                             GeneratorContext* generator_context) {
+  std::string filename = LegacyGeneratedClassFileName(desc, options);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
 
   GenerateHead(file, &printer);
 
-  std::string php_namespace = RootPhpNamespace(desc, is_descriptor);
+  std::string php_namespace = RootPhpNamespace(desc, options);
   if (!php_namespace.empty()) {
     printer.Print(
         "namespace ^name^;\n\n",
         "name", php_namespace);
   }
-  std::string newname = FullClassName(desc, is_descriptor);
+  std::string newname = FullClassName(desc, options);
   printer.Print("if (false) {\n");
   Indent(&printer);
   printer.Print("/**\n");
@@ -1224,13 +1261,14 @@ void LegacyGenerateClassFile(const FileDescriptor* file, const DescriptorType* d
       "new", GeneratedClassNameImpl(desc));
   printer.Print("@trigger_error('^old^ is deprecated and will be removed in "
       "the next major release. Use ^fullname^ instead', E_USER_DEPRECATED);\n\n",
-      "old", LegacyFullClassName(desc, is_descriptor),
+      "old", LegacyFullClassName(desc, options),
       "fullname", newname);
 }
 
 void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
-                      bool is_descriptor, GeneratorContext* generator_context) {
-  std::string filename = GeneratedClassFileName(en, is_descriptor);
+                      const Options& options,
+                      GeneratorContext* generator_context) {
+  std::string filename = GeneratedClassFileName(en, options);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
@@ -1250,7 +1288,7 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
     printer.Print("use UnexpectedValueException;\n\n");
   }
 
-  GenerateEnumDocComment(&printer, en, is_descriptor);
+  GenerateEnumDocComment(&printer, en, options);
 
   if (lastindex != string::npos) {
     fullname = fullname.substr(lastindex + 1);
@@ -1327,14 +1365,13 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
     printer.Print(
         "class_alias(^new^::class, \\^old^::class);\n\n",
         "new", fullname,
-        "old", LegacyFullClassName(en, is_descriptor));
-    LegacyGenerateClassFile(file, en, is_descriptor, generator_context);
+        "old", LegacyFullClassName(en, options));
+    LegacyGenerateClassFile(file, en, options, generator_context);
   }
 }
 
 void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
-                         bool is_descriptor,
-                         bool aggregate_metadata,
+                         const Options& options,
                          GeneratorContext* generator_context) {
   // Don't generate MapEntry messages -- we use the PHP extension's native
   // support for map fields instead.
@@ -1342,7 +1379,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
     return;
   }
 
-  std::string filename = GeneratedClassFileName(message, is_descriptor);
+  std::string filename = GeneratedClassFileName(message, options);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
@@ -1358,9 +1395,9 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
         "name", fullname.substr(0, lastindex));
   }
 
-  GenerateUseDeclaration(is_descriptor, &printer);
+  GenerateUseDeclaration(options, &printer);
 
-  GenerateMessageDocComment(&printer, message, is_descriptor);
+  GenerateMessageDocComment(&printer, message, options);
   if (lastindex != string::npos) {
     fullname = fullname.substr(lastindex + 1);
   }
@@ -1389,7 +1426,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
   // Field and oneof definitions.
   for (int i = 0; i < message->field_count(); i++) {
     const FieldDescriptor* field = message->field(i);
-    GenerateField(field, &printer, is_descriptor);
+    GenerateField(field, &printer, options);
   }
   for (int i = 0; i < message->real_oneof_decl_count(); i++) {
     const OneofDescriptor* oneof = message->oneof_decl(i);
@@ -1397,13 +1434,12 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
   }
   printer.Print("\n");
 
-  GenerateMessageConstructorDocComment(&printer, message, is_descriptor);
+  GenerateMessageConstructorDocComment(&printer, message, options);
   printer.Print(
       "public function __construct($data = NULL) {\n");
   Indent(&printer);
 
-  std::string metadata_filename =
-      GeneratedMetadataFileName(file, is_descriptor);
+  std::string metadata_filename = GeneratedMetadataFileName(file, options);
   std::string metadata_fullname = FilenameToClassname(metadata_filename);
   printer.Print(
       "\\^fullname^::initOnce();\n",
@@ -1418,7 +1454,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
   // Field and oneof accessors.
   for (int i = 0; i < message->field_count(); i++) {
     const FieldDescriptor* field = message->field(i);
-    GenerateFieldAccessor(field, is_descriptor, &printer);
+    GenerateFieldAccessor(field, options, &printer);
   }
   for (int i = 0; i < message->real_oneof_decl_count(); i++) {
     const OneofDescriptor* oneof = message->oneof_decl(i);
@@ -1444,26 +1480,24 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
     printer.Print(
         "class_alias(^new^::class, \\^old^::class);\n\n",
         "new", fullname,
-        "old", LegacyFullClassName(message, is_descriptor));
-    LegacyGenerateClassFile(file, message, is_descriptor, generator_context);
+        "old", LegacyFullClassName(message, options));
+    LegacyGenerateClassFile(file, message, options, generator_context);
   }
 
   // Nested messages and enums.
   for (int i = 0; i < message->nested_type_count(); i++) {
-    GenerateMessageFile(file, message->nested_type(i), is_descriptor,
-                        aggregate_metadata,
+    GenerateMessageFile(file, message->nested_type(i), options,
                         generator_context);
   }
   for (int i = 0; i < message->enum_type_count(); i++) {
-    GenerateEnumFile(file, message->enum_type(i), is_descriptor,
-                     generator_context);
+    GenerateEnumFile(file, message->enum_type(i), options, generator_context);
   }
 }
 
-void GenerateServiceFile(const FileDescriptor* file,
-  const ServiceDescriptor* service, bool is_descriptor,
-  GeneratorContext* generator_context) {
-  std::string filename = GeneratedServiceFileName(service, is_descriptor);
+void GenerateServiceFile(
+    const FileDescriptor* file, const ServiceDescriptor* service,
+    const Options& options, GeneratorContext* generator_context) {
+  std::string filename = GeneratedServiceFileName(service, options);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
@@ -1507,26 +1541,20 @@ void GenerateServiceFile(const FileDescriptor* file,
   printer.Print("}\n\n");
 }
 
-void GenerateFile(const FileDescriptor* file, bool is_descriptor,
-                  bool aggregate_metadata,
-                  const std::set<string>& aggregate_metadata_prefixes,
+void GenerateFile(const FileDescriptor* file, const Options& options,
                   GeneratorContext* generator_context) {
-  GenerateMetadataFile(file, is_descriptor, aggregate_metadata,
-                       aggregate_metadata_prefixes, generator_context);
+  GenerateMetadataFile(file, options, generator_context);
 
   for (int i = 0; i < file->message_type_count(); i++) {
-    GenerateMessageFile(file, file->message_type(i), is_descriptor,
-                        aggregate_metadata,
+    GenerateMessageFile(file, file->message_type(i), options,
                         generator_context);
   }
   for (int i = 0; i < file->enum_type_count(); i++) {
-    GenerateEnumFile(file, file->enum_type(i), is_descriptor,
-                     generator_context);
+    GenerateEnumFile(file, file->enum_type(i), options, generator_context);
   }
   if (file->options().php_generic_services()) {
     for (int i = 0; i < file->service_count(); i++) {
-      GenerateServiceFile(file, file->service(i), is_descriptor,
-                          generator_context);
+      GenerateServiceFile(file, file->service(i), options, generator_context);
     }
   }
 }
@@ -1629,20 +1657,20 @@ static string FirstLineOf(const string& value) {
   return result;
 }
 
-void GenerateMessageDocComment(io::Printer* printer,
-                               const Descriptor* message, int is_descriptor) {
+void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message,
+                               const Options& options) {
   printer->Print("/**\n");
   GenerateDocCommentBody(printer, message);
   printer->Print(
     " * Generated from protobuf message <code>^messagename^</code>\n"
     " */\n",
-    "fullname", EscapePhpdoc(FullClassName(message, is_descriptor)),
+    "fullname", EscapePhpdoc(FullClassName(message, options)),
     "messagename", EscapePhpdoc(message->full_name()));
 }
 
 void GenerateMessageConstructorDocComment(io::Printer* printer,
                                           const Descriptor* message,
-                                          int is_descriptor) {
+                                          const Options& options) {
   // In theory we should have slightly different comments for setters, getters,
   // etc., but in practice everyone already knows the difference between these
   // so it's redundant information.
@@ -1660,7 +1688,7 @@ void GenerateMessageConstructorDocComment(io::Printer* printer,
   for (int i = 0; i < message->field_count(); i++) {
     const FieldDescriptor* field = message->field(i);
     printer->Print(" *     @type ^php_type^ $^var^\n",
-      "php_type", PhpSetterTypeName(field, is_descriptor),
+      "php_type", PhpSetterTypeName(field, options),
       "var", field->name());
     SourceLocation location;
     if (field->GetSourceLocation(&location)) {
@@ -1682,7 +1710,7 @@ void GenerateServiceDocComment(io::Printer* printer,
 }
 
 void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
-                             int is_descriptor, int function_type) {
+                             const Options& options, int function_type) {
   // In theory we should have slightly different comments for setters, getters,
   // etc., but in practice everyone already knows the difference between these
   // so it's redundant information.
@@ -1698,11 +1726,11 @@ void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
     "def", EscapePhpdoc(FirstLineOf(field->DebugString())));
   if (function_type == kFieldSetter) {
     printer->Print(" * @param ^php_type^ $var\n",
-      "php_type", PhpSetterTypeName(field, is_descriptor));
+      "php_type", PhpSetterTypeName(field, options));
     printer->Print(" * @return $this\n");
   } else if (function_type == kFieldGetter) {
     printer->Print(" * @return ^php_type^\n",
-      "php_type", PhpGetterTypeName(field, is_descriptor));
+      "php_type", PhpGetterTypeName(field, options));
   }
   printer->Print(" */\n");
 }
@@ -1743,7 +1771,7 @@ void GenerateWrapperFieldSetterDocComment(io::Printer* printer, const FieldDescr
 }
 
 void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
-                            int is_descriptor) {
+                            const Options& options) {
   printer->Print("/**\n");
   GenerateDocCommentBody(printer, enum_);
   printer->Print(
@@ -1784,32 +1812,26 @@ void GenerateServiceMethodDocComment(io::Printer* printer,
 bool Generator::Generate(const FileDescriptor* file, const string& parameter,
                          GeneratorContext* generator_context,
                          string* error) const {
-  return Generate(file, false, false, std::set<string>(),
-                  generator_context, error);
+  return Generate(file, Options(), generator_context, error);
 }
 
-bool Generator::Generate(
-    const FileDescriptor* file,
-    bool is_descriptor,
-    bool aggregate_metadata,
-    const std::set<string>& aggregate_metadata_prefixes,
-    GeneratorContext* generator_context,
-    string* error) const {
-  if (is_descriptor && file->name() != kDescriptorFile) {
+bool Generator::Generate(const FileDescriptor* file, const Options& options,
+                         GeneratorContext* generator_context,
+                         string* error) const {
+  if (options.is_descriptor && file->name() != kDescriptorFile) {
     *error =
         "Can only generate PHP code for google/protobuf/descriptor.proto.\n";
     return false;
   }
 
-  if (!is_descriptor && file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
+  if (!options.is_descriptor && file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
     *error =
         "Can only generate PHP code for proto3 .proto files.\n"
         "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n";
     return false;
   }
 
-  GenerateFile(file, is_descriptor, aggregate_metadata,
-               aggregate_metadata_prefixes, generator_context);
+  GenerateFile(file, options, generator_context);
 
   return true;
 }
@@ -1818,32 +1840,24 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
                             const std::string& parameter,
                             GeneratorContext* generator_context,
                             std::string* error) const {
-  bool is_descriptor = false;
-  bool aggregate_metadata = false;
-  std::set<string> aggregate_metadata_prefixes;
+  Options options;
 
   for (const auto& option : Split(parameter, ",", true)) {
     const std::vector<std::string> option_pair = Split(option, "=", true);
     if (HasPrefixString(option_pair[0], "aggregate_metadata")) {
-      string options_string = option_pair[1];
-      const std::vector<std::string> options =
-          Split(options_string, "#", false);
-      aggregate_metadata = true;
-      for (int i = 0; i < options.size(); i++) {
-        aggregate_metadata_prefixes.insert(options[i]);
-        GOOGLE_LOG(INFO) << options[i];
+      options.aggregate_metadata = true;
+      for (const auto& prefix : Split(option_pair[1], "#", false)) {
+        options.aggregate_metadata_prefixes.insert(prefix);
+        GOOGLE_LOG(INFO) << prefix;
       }
     }
     if (option_pair[0] == "internal") {
-      is_descriptor = true;
+      options.is_descriptor = true;
     }
   }
 
   for (auto file : files) {
-    if (!Generate(
-             file, is_descriptor, aggregate_metadata,
-             aggregate_metadata_prefixes,
-             generator_context, error)) {
+    if (!Generate(file, options, generator_context, error)) {
       return false;
     }
   }

+ 3 - 3
src/google/protobuf/compiler/php/php_generator.h

@@ -43,6 +43,8 @@ namespace protobuf {
 namespace compiler {
 namespace php {
 
+struct Options;
+
 class PROTOC_EXPORT Generator : public CodeGenerator {
  public:
   virtual bool Generate(
@@ -63,9 +65,7 @@ class PROTOC_EXPORT Generator : public CodeGenerator {
  private:
   bool Generate(
       const FileDescriptor* file,
-      bool is_descriptor,
-      bool aggregate_metadata,
-      const std::set<string>& aggregate_metadata_prefixes,
+      const Options& options,
       GeneratorContext* generator_context,
       string* error) const;
 };