Home | History | Annotate | Download | only in cpp
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // http://code.google.com/p/protobuf/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 // Author: kenton (at) google.com (Kenton Varda)
     32 //  Based on original Protocol Buffers design by
     33 //  Sanjay Ghemawat, Jeff Dean, and others.
     34 
     35 #include <google/protobuf/compiler/cpp/cpp_file.h>
     36 #include <google/protobuf/compiler/cpp/cpp_enum.h>
     37 #include <google/protobuf/compiler/cpp/cpp_service.h>
     38 #include <google/protobuf/compiler/cpp/cpp_extension.h>
     39 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
     40 #include <google/protobuf/compiler/cpp/cpp_message.h>
     41 #include <google/protobuf/compiler/cpp/cpp_field.h>
     42 #include <google/protobuf/io/printer.h>
     43 #include <google/protobuf/descriptor.pb.h>
     44 #include <google/protobuf/stubs/strutil.h>
     45 
     46 namespace google {
     47 namespace protobuf {
     48 namespace compiler {
     49 namespace cpp {
     50 
     51 // ===================================================================
     52 
     53 FileGenerator::FileGenerator(const FileDescriptor* file,
     54                              const string& dllexport_decl)
     55   : file_(file),
     56     message_generators_(
     57       new scoped_ptr<MessageGenerator>[file->message_type_count()]),
     58     enum_generators_(
     59       new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
     60     service_generators_(
     61       new scoped_ptr<ServiceGenerator>[file->service_count()]),
     62     extension_generators_(
     63       new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
     64     dllexport_decl_(dllexport_decl) {
     65 
     66   for (int i = 0; i < file->message_type_count(); i++) {
     67     message_generators_[i].reset(
     68       new MessageGenerator(file->message_type(i), dllexport_decl));
     69   }
     70 
     71   for (int i = 0; i < file->enum_type_count(); i++) {
     72     enum_generators_[i].reset(
     73       new EnumGenerator(file->enum_type(i), dllexport_decl));
     74   }
     75 
     76   for (int i = 0; i < file->service_count(); i++) {
     77     service_generators_[i].reset(
     78       new ServiceGenerator(file->service(i), dllexport_decl));
     79   }
     80 
     81   for (int i = 0; i < file->extension_count(); i++) {
     82     extension_generators_[i].reset(
     83       new ExtensionGenerator(file->extension(i), dllexport_decl));
     84   }
     85 
     86   SplitStringUsing(file_->package(), ".", &package_parts_);
     87 }
     88 
     89 FileGenerator::~FileGenerator() {}
     90 
     91 void FileGenerator::GenerateHeader(io::Printer* printer) {
     92   string filename_identifier = FilenameIdentifier(file_->name());
     93 
     94   // Generate top of header.
     95   printer->Print(
     96     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
     97     "// source: $filename$\n"
     98     "\n"
     99     "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
    100     "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
    101     "\n"
    102     "#include <string>\n"
    103     "\n",
    104     "filename", file_->name(),
    105     "filename_identifier", filename_identifier);
    106 
    107   printer->Print(
    108     "#include <google/protobuf/stubs/common.h>\n"
    109     "\n");
    110 
    111   // Verify the protobuf library header version is compatible with the protoc
    112   // version before going any further.
    113   printer->Print(
    114     "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
    115     "#error This file was generated by a newer version of protoc which is\n"
    116     "#error incompatible with your Protocol Buffer headers.  Please update\n"
    117     "#error your headers.\n"
    118     "#endif\n"
    119     "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
    120     "#error This file was generated by an older version of protoc which is\n"
    121     "#error incompatible with your Protocol Buffer headers.  Please\n"
    122     "#error regenerate this file with a newer version of protoc.\n"
    123     "#endif\n"
    124     "\n",
    125     "min_header_version",
    126       SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
    127     "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
    128 
    129   // OK, it's now safe to #include other files.
    130   printer->Print(
    131     "#include <google/protobuf/generated_message_util.h>\n"
    132     "#include <google/protobuf/repeated_field.h>\n"
    133     "#include <google/protobuf/extension_set.h>\n");
    134 
    135   if (HasDescriptorMethods(file_)) {
    136     printer->Print(
    137       "#include <google/protobuf/generated_message_reflection.h>\n");
    138   }
    139 
    140   if (HasGenericServices(file_)) {
    141     printer->Print(
    142       "#include <google/protobuf/service.h>\n");
    143   }
    144 
    145 
    146   for (int i = 0; i < file_->dependency_count(); i++) {
    147     printer->Print(
    148       "#include \"$dependency$.pb.h\"\n",
    149       "dependency", StripProto(file_->dependency(i)->name()));
    150   }
    151 
    152   printer->Print(
    153     "// @@protoc_insertion_point(includes)\n");
    154 
    155   // Open namespace.
    156   GenerateNamespaceOpeners(printer);
    157 
    158   // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
    159   // functions, so that we can declare them to be friends of each class.
    160   printer->Print(
    161     "\n"
    162     "// Internal implementation detail -- do not call these.\n"
    163     "void $dllexport_decl$ $adddescriptorsname$();\n",
    164     "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
    165     "dllexport_decl", dllexport_decl_);
    166 
    167   printer->Print(
    168     // Note that we don't put dllexport_decl on these because they are only
    169     // called by the .pb.cc file in which they are defined.
    170     "void $assigndescriptorsname$();\n"
    171     "void $shutdownfilename$();\n"
    172     "\n",
    173     "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
    174     "shutdownfilename", GlobalShutdownFileName(file_->name()));
    175 
    176   // Generate forward declarations of classes.
    177   for (int i = 0; i < file_->message_type_count(); i++) {
    178     message_generators_[i]->GenerateForwardDeclaration(printer);
    179   }
    180 
    181   printer->Print("\n");
    182 
    183   // Generate enum definitions.
    184   for (int i = 0; i < file_->message_type_count(); i++) {
    185     message_generators_[i]->GenerateEnumDefinitions(printer);
    186   }
    187   for (int i = 0; i < file_->enum_type_count(); i++) {
    188     enum_generators_[i]->GenerateDefinition(printer);
    189   }
    190 
    191   printer->Print(kThickSeparator);
    192   printer->Print("\n");
    193 
    194   // Generate class definitions.
    195   for (int i = 0; i < file_->message_type_count(); i++) {
    196     if (i > 0) {
    197       printer->Print("\n");
    198       printer->Print(kThinSeparator);
    199       printer->Print("\n");
    200     }
    201     message_generators_[i]->GenerateClassDefinition(printer);
    202   }
    203 
    204   printer->Print("\n");
    205   printer->Print(kThickSeparator);
    206   printer->Print("\n");
    207 
    208   if (HasGenericServices(file_)) {
    209     // Generate service definitions.
    210     for (int i = 0; i < file_->service_count(); i++) {
    211       if (i > 0) {
    212         printer->Print("\n");
    213         printer->Print(kThinSeparator);
    214         printer->Print("\n");
    215       }
    216       service_generators_[i]->GenerateDeclarations(printer);
    217     }
    218 
    219     printer->Print("\n");
    220     printer->Print(kThickSeparator);
    221     printer->Print("\n");
    222   }
    223 
    224   // Declare extension identifiers.
    225   for (int i = 0; i < file_->extension_count(); i++) {
    226     extension_generators_[i]->GenerateDeclaration(printer);
    227   }
    228 
    229   printer->Print("\n");
    230   printer->Print(kThickSeparator);
    231   printer->Print("\n");
    232 
    233   // Generate class inline methods.
    234   for (int i = 0; i < file_->message_type_count(); i++) {
    235     if (i > 0) {
    236       printer->Print(kThinSeparator);
    237       printer->Print("\n");
    238     }
    239     message_generators_[i]->GenerateInlineMethods(printer);
    240   }
    241 
    242   printer->Print(
    243     "\n"
    244     "// @@protoc_insertion_point(namespace_scope)\n");
    245 
    246   // Close up namespace.
    247   GenerateNamespaceClosers(printer);
    248 
    249   // Emit GetEnumDescriptor specializations into google::protobuf namespace:
    250   if (HasDescriptorMethods(file_)) {
    251     // The SWIG conditional is to avoid a null-pointer dereference
    252     // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
    253     //   namespace X { void Y<Z::W>(); }
    254     // which appears in GetEnumDescriptor() specializations.
    255     printer->Print(
    256         "\n"
    257         "#ifndef SWIG\n"
    258         "namespace google {\nnamespace protobuf {\n"
    259         "\n");
    260     for (int i = 0; i < file_->message_type_count(); i++) {
    261       message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
    262     }
    263     for (int i = 0; i < file_->enum_type_count(); i++) {
    264       enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
    265     }
    266     printer->Print(
    267         "\n"
    268         "}  // namespace google\n}  // namespace protobuf\n"
    269         "#endif  // SWIG\n");
    270   }
    271 
    272   printer->Print(
    273     "\n"
    274     "// @@protoc_insertion_point(global_scope)\n"
    275     "\n");
    276 
    277   printer->Print(
    278     "#endif  // PROTOBUF_$filename_identifier$__INCLUDED\n",
    279     "filename_identifier", filename_identifier);
    280 }
    281 
    282 void FileGenerator::GenerateSource(io::Printer* printer) {
    283   printer->Print(
    284     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
    285     "\n"
    286     // The generated code calls accessors that might be deprecated. We don't
    287     // want the compiler to warn in generated code.
    288     "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
    289     "#include \"$basename$.pb.h\"\n"
    290 
    291     "#include <google/protobuf/stubs/once.h>\n"
    292     "#include <google/protobuf/io/coded_stream.h>\n"
    293     "#include <google/protobuf/wire_format_lite_inl.h>\n",
    294     "basename", StripProto(file_->name()));
    295 
    296   if (HasDescriptorMethods(file_)) {
    297     printer->Print(
    298       "#include <google/protobuf/descriptor.h>\n"
    299       "#include <google/protobuf/reflection_ops.h>\n"
    300       "#include <google/protobuf/wire_format.h>\n");
    301   }
    302 
    303   printer->Print(
    304     "// @@protoc_insertion_point(includes)\n");
    305 
    306   GenerateNamespaceOpeners(printer);
    307 
    308   if (HasDescriptorMethods(file_)) {
    309     printer->Print(
    310       "\n"
    311       "namespace {\n"
    312       "\n");
    313     for (int i = 0; i < file_->message_type_count(); i++) {
    314       message_generators_[i]->GenerateDescriptorDeclarations(printer);
    315     }
    316     for (int i = 0; i < file_->enum_type_count(); i++) {
    317       printer->Print(
    318         "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
    319         "name", ClassName(file_->enum_type(i), false));
    320     }
    321 
    322     if (HasGenericServices(file_)) {
    323       for (int i = 0; i < file_->service_count(); i++) {
    324         printer->Print(
    325           "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
    326           "name", file_->service(i)->name());
    327       }
    328     }
    329 
    330     printer->Print(
    331       "\n"
    332       "}  // namespace\n"
    333       "\n");
    334   }
    335 
    336   // Define our externally-visible BuildDescriptors() function.  (For the lite
    337   // library, all this does is initialize default instances.)
    338   GenerateBuildDescriptors(printer);
    339 
    340   // Generate enums.
    341   for (int i = 0; i < file_->enum_type_count(); i++) {
    342     enum_generators_[i]->GenerateMethods(printer);
    343   }
    344 
    345   // Generate classes.
    346   for (int i = 0; i < file_->message_type_count(); i++) {
    347     printer->Print("\n");
    348     printer->Print(kThickSeparator);
    349     printer->Print("\n");
    350     message_generators_[i]->GenerateClassMethods(printer);
    351   }
    352 
    353   if (HasGenericServices(file_)) {
    354     // Generate services.
    355     for (int i = 0; i < file_->service_count(); i++) {
    356       if (i == 0) printer->Print("\n");
    357       printer->Print(kThickSeparator);
    358       printer->Print("\n");
    359       service_generators_[i]->GenerateImplementation(printer);
    360     }
    361   }
    362 
    363   // Define extensions.
    364   for (int i = 0; i < file_->extension_count(); i++) {
    365     extension_generators_[i]->GenerateDefinition(printer);
    366   }
    367 
    368   printer->Print(
    369     "\n"
    370     "// @@protoc_insertion_point(namespace_scope)\n");
    371 
    372   GenerateNamespaceClosers(printer);
    373 
    374   printer->Print(
    375     "\n"
    376     "// @@protoc_insertion_point(global_scope)\n");
    377 }
    378 
    379 void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
    380   // AddDescriptors() is a file-level procedure which adds the encoded
    381   // FileDescriptorProto for this .proto file to the global DescriptorPool
    382   // for generated files (DescriptorPool::generated_pool()).  It always runs
    383   // at static initialization time, so all files will be registered before
    384   // main() starts.  This procedure also constructs default instances and
    385   // registers extensions.
    386   //
    387   // Its sibling, AssignDescriptors(), actually pulls the compiled
    388   // FileDescriptor from the DescriptorPool and uses it to populate all of
    389   // the global variables which store pointers to the descriptor objects.
    390   // It also constructs the reflection objects.  It is called the first time
    391   // anyone calls descriptor() or GetReflection() on one of the types defined
    392   // in the file.
    393 
    394   // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
    395   // and we only use AddDescriptors() to allocate default instances.
    396   if (HasDescriptorMethods(file_)) {
    397     printer->Print(
    398       "\n"
    399       "void $assigndescriptorsname$() {\n",
    400       "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
    401     printer->Indent();
    402 
    403     // Make sure the file has found its way into the pool.  If a descriptor
    404     // is requested *during* static init then AddDescriptors() may not have
    405     // been called yet, so we call it manually.  Note that it's fine if
    406     // AddDescriptors() is called multiple times.
    407     printer->Print(
    408       "$adddescriptorsname$();\n",
    409       "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
    410 
    411     // Get the file's descriptor from the pool.
    412     printer->Print(
    413       "const ::google::protobuf::FileDescriptor* file =\n"
    414       "  ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
    415       "    \"$filename$\");\n"
    416       // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
    417       // being unused when compiling an empty .proto file.
    418       "GOOGLE_CHECK(file != NULL);\n",
    419       "filename", file_->name());
    420 
    421     // Go through all the stuff defined in this file and generated code to
    422     // assign the global descriptor pointers based on the file descriptor.
    423     for (int i = 0; i < file_->message_type_count(); i++) {
    424       message_generators_[i]->GenerateDescriptorInitializer(printer, i);
    425     }
    426     for (int i = 0; i < file_->enum_type_count(); i++) {
    427       enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
    428     }
    429     if (HasGenericServices(file_)) {
    430       for (int i = 0; i < file_->service_count(); i++) {
    431         service_generators_[i]->GenerateDescriptorInitializer(printer, i);
    432       }
    433     }
    434 
    435     printer->Outdent();
    436     printer->Print(
    437       "}\n"
    438       "\n");
    439 
    440     // ---------------------------------------------------------------
    441 
    442     // protobuf_AssignDescriptorsOnce():  The first time it is called, calls
    443     // AssignDescriptors().  All later times, waits for the first call to
    444     // complete and then returns.
    445     printer->Print(
    446       "namespace {\n"
    447       "\n"
    448       "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
    449       "inline void protobuf_AssignDescriptorsOnce() {\n"
    450       "  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
    451       "                 &$assigndescriptorsname$);\n"
    452       "}\n"
    453       "\n",
    454       "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
    455 
    456     // protobuf_RegisterTypes():  Calls
    457     // MessageFactory::InternalRegisterGeneratedType() for each message type.
    458     printer->Print(
    459       "void protobuf_RegisterTypes(const ::std::string&) {\n"
    460       "  protobuf_AssignDescriptorsOnce();\n");
    461     printer->Indent();
    462 
    463     for (int i = 0; i < file_->message_type_count(); i++) {
    464       message_generators_[i]->GenerateTypeRegistrations(printer);
    465     }
    466 
    467     printer->Outdent();
    468     printer->Print(
    469       "}\n"
    470       "\n"
    471       "}  // namespace\n");
    472   }
    473 
    474   // -----------------------------------------------------------------
    475 
    476   // ShutdownFile():  Deletes descriptors, default instances, etc. on shutdown.
    477   printer->Print(
    478     "\n"
    479     "void $shutdownfilename$() {\n",
    480     "shutdownfilename", GlobalShutdownFileName(file_->name()));
    481   printer->Indent();
    482 
    483   for (int i = 0; i < file_->message_type_count(); i++) {
    484     message_generators_[i]->GenerateShutdownCode(printer);
    485   }
    486 
    487   printer->Outdent();
    488   printer->Print(
    489     "}\n");
    490 
    491   // -----------------------------------------------------------------
    492 
    493   // Now generate the AddDescriptors() function.
    494   printer->Print(
    495     "\n"
    496     "void $adddescriptorsname$() {\n"
    497     // We don't need any special synchronization here because this code is
    498     // called at static init time before any threads exist.
    499     "  static bool already_here = false;\n"
    500     "  if (already_here) return;\n"
    501     "  already_here = true;\n"
    502     "  GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
    503     "\n",
    504     "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
    505   printer->Indent();
    506 
    507   // Call the AddDescriptors() methods for all of our dependencies, to make
    508   // sure they get added first.
    509   for (int i = 0; i < file_->dependency_count(); i++) {
    510     const FileDescriptor* dependency = file_->dependency(i);
    511     // Print the namespace prefix for the dependency.
    512     vector<string> dependency_package_parts;
    513     SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
    514     printer->Print("::");
    515     for (int i = 0; i < dependency_package_parts.size(); i++) {
    516       printer->Print("$name$::",
    517                      "name", dependency_package_parts[i]);
    518     }
    519     // Call its AddDescriptors function.
    520     printer->Print(
    521       "$name$();\n",
    522       "name", GlobalAddDescriptorsName(dependency->name()));
    523   }
    524 
    525   if (HasDescriptorMethods(file_)) {
    526     // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
    527     // and embed it as a string literal, which is parsed and built into real
    528     // descriptors at initialization time.
    529     FileDescriptorProto file_proto;
    530     file_->CopyTo(&file_proto);
    531     string file_data;
    532     file_proto.SerializeToString(&file_data);
    533 
    534     printer->Print(
    535       "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
    536 
    537     // Only write 40 bytes per line.
    538     static const int kBytesPerLine = 40;
    539     for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
    540       printer->Print("\n  \"$data$\"",
    541         "data", CEscape(file_data.substr(i, kBytesPerLine)));
    542     }
    543     printer->Print(
    544       ", $size$);\n",
    545       "size", SimpleItoa(file_data.size()));
    546 
    547     // Call MessageFactory::InternalRegisterGeneratedFile().
    548     printer->Print(
    549       "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
    550       "  \"$filename$\", &protobuf_RegisterTypes);\n",
    551       "filename", file_->name());
    552   }
    553 
    554   // Allocate and initialize default instances.  This can't be done lazily
    555   // since default instances are returned by simple accessors and are used with
    556   // extensions.  Speaking of which, we also register extensions at this time.
    557   for (int i = 0; i < file_->message_type_count(); i++) {
    558     message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
    559   }
    560   for (int i = 0; i < file_->extension_count(); i++) {
    561     extension_generators_[i]->GenerateRegistration(printer);
    562   }
    563   for (int i = 0; i < file_->message_type_count(); i++) {
    564     message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
    565   }
    566 
    567   printer->Print(
    568     "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
    569     "shutdownfilename", GlobalShutdownFileName(file_->name()));
    570 
    571   printer->Outdent();
    572 
    573   printer->Print(
    574     "}\n"
    575     "\n"
    576     "// Force AddDescriptors() to be called at static initialization time.\n"
    577     "struct StaticDescriptorInitializer_$filename$ {\n"
    578     "  StaticDescriptorInitializer_$filename$() {\n"
    579     "    $adddescriptorsname$();\n"
    580     "  }\n"
    581     "} static_descriptor_initializer_$filename$_;\n"
    582     "\n",
    583     "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
    584     "filename", FilenameIdentifier(file_->name()));
    585 }
    586 
    587 void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
    588   if (package_parts_.size() > 0) printer->Print("\n");
    589 
    590   for (int i = 0; i < package_parts_.size(); i++) {
    591     printer->Print("namespace $part$ {\n",
    592                    "part", package_parts_[i]);
    593   }
    594 }
    595 
    596 void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
    597   if (package_parts_.size() > 0) printer->Print("\n");
    598 
    599   for (int i = package_parts_.size() - 1; i >= 0; i--) {
    600     printer->Print("}  // namespace $part$\n",
    601                    "part", package_parts_[i]);
    602   }
    603 }
    604 
    605 }  // namespace cpp
    606 }  // namespace compiler
    607 }  // namespace protobuf
    608 }  // namespace google
    609