LCOV - code coverage report
Current view: top level - third_party/protobuf/src/google/protobuf/compiler/csharp - csharp_message.cc (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 0 204 0.0 %
Date: 2015-10-10 Functions: 0 17 0.0 %

          Line data    Source code
       1             : // Protocol Buffers - Google's data interchange format
       2             : // Copyright 2008 Google Inc.  All rights reserved.
       3             : // https://developers.google.com/protocol-buffers/
       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             : #include <sstream>
      32             : #include <algorithm>
      33             : #include <map>
      34             : 
      35             : #include <google/protobuf/compiler/code_generator.h>
      36             : #include <google/protobuf/compiler/plugin.h>
      37             : #include <google/protobuf/descriptor.h>
      38             : #include <google/protobuf/descriptor.pb.h>
      39             : #include <google/protobuf/io/printer.h>
      40             : #include <google/protobuf/io/zero_copy_stream.h>
      41             : #include <google/protobuf/stubs/strutil.h>
      42             : #include <google/protobuf/wire_format.h>
      43             : #include <google/protobuf/wire_format_lite.h>
      44             : 
      45             : #include <google/protobuf/compiler/csharp/csharp_enum.h>
      46             : #include <google/protobuf/compiler/csharp/csharp_field_base.h>
      47             : #include <google/protobuf/compiler/csharp/csharp_helpers.h>
      48             : #include <google/protobuf/compiler/csharp/csharp_message.h>
      49             : #include <google/protobuf/compiler/csharp/csharp_names.h>
      50             : 
      51             : using google::protobuf::internal::scoped_ptr;
      52             : 
      53             : namespace google {
      54             : namespace protobuf {
      55             : namespace compiler {
      56             : namespace csharp {
      57             : 
      58           0 : bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
      59           0 :   return d1->number() < d2->number();
      60             : }
      61             : 
      62           0 : MessageGenerator::MessageGenerator(const Descriptor* descriptor)
      63             :     : SourceGeneratorBase(descriptor->file()),
      64           0 :       descriptor_(descriptor) {
      65             : 
      66             :   // sorted field names
      67           0 :   for (int i = 0; i < descriptor_->field_count(); i++) {
      68           0 :     field_names_.push_back(descriptor_->field(i)->name());
      69             :   }
      70           0 :   std::sort(field_names_.begin(), field_names_.end());
      71             : 
      72             :   // fields by number
      73           0 :   for (int i = 0; i < descriptor_->field_count(); i++) {
      74           0 :     fields_by_number_.push_back(descriptor_->field(i));
      75             :   }
      76             :   std::sort(fields_by_number_.begin(), fields_by_number_.end(),
      77           0 :             CompareFieldNumbers);
      78           0 : }
      79             : 
      80           0 : MessageGenerator::~MessageGenerator() {
      81           0 : }
      82             : 
      83           0 : std::string MessageGenerator::class_name() {
      84           0 :   return descriptor_->name();
      85             : }
      86             : 
      87           0 : std::string MessageGenerator::full_class_name() {
      88           0 :   return GetClassName(descriptor_);
      89             : }
      90             : 
      91           0 : const std::vector<std::string>& MessageGenerator::field_names() {
      92           0 :   return field_names_;
      93             : }
      94             : 
      95           0 : const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
      96           0 :   return fields_by_number_;
      97             : }
      98             : 
      99           0 : void MessageGenerator::Generate(io::Printer* printer) {
     100             :   map<string, string> vars;
     101           0 :   vars["class_name"] = class_name();
     102           0 :   vars["access_level"] = class_access_level();
     103             : 
     104             :   printer->Print(
     105           0 :     "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
     106           0 :   WriteGeneratedCodeAttributes(printer);
     107             :   printer->Print(
     108             :     vars,
     109           0 :     "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n");
     110           0 :   printer->Indent();
     111             : 
     112             :   // All static fields and properties
     113             :   printer->Print(
     114             :       vars,
     115             :       "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n"
     116           0 :       "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
     117             : 
     118             :   // Access the message descriptor via the relevant file descriptor or containing message descriptor.
     119           0 :   if (!descriptor_->containing_type()) {
     120           0 :     vars["descriptor_accessor"] = GetUmbrellaClassName(descriptor_->file())
     121           0 :         + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]";
     122             :   } else {
     123           0 :     vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
     124           0 :         + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]";
     125             :   }
     126             : 
     127             :   printer->Print(
     128             :     vars,
     129             :     "public static pbr::MessageDescriptor Descriptor {\n"
     130             :     "  get { return $descriptor_accessor$; }\n"
     131             :     "}\n"
     132             :     "\n"
     133             :     "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
     134             :     "  get { return Descriptor; }\n"
     135             :     "}\n"
     136           0 :     "\n");
     137             : 
     138             :   // Parameterless constructor and partial OnConstruction method.
     139             :   printer->Print(
     140             :     vars,
     141             :     "public $class_name$() {\n"
     142             :     "  OnConstruction();\n"
     143             :     "}\n\n"
     144           0 :     "partial void OnConstruction();\n\n");
     145             : 
     146           0 :   GenerateCloningCode(printer);
     147           0 :   GenerateFreezingCode(printer);
     148             : 
     149             :   // Fields/properties
     150           0 :   for (int i = 0; i < descriptor_->field_count(); i++) {
     151           0 :     const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
     152             : 
     153             :     // Rats: we lose the debug comment here :(
     154             :     printer->Print(
     155             :       "public const int $field_constant_name$ = $index$;\n",
     156             :       "field_constant_name", GetFieldConstantName(fieldDescriptor),
     157           0 :       "index", SimpleItoa(fieldDescriptor->number()));
     158             :     scoped_ptr<FieldGeneratorBase> generator(
     159           0 :         CreateFieldGeneratorInternal(fieldDescriptor));
     160           0 :     generator->GenerateMembers(printer);
     161           0 :     printer->Print("\n");
     162             :   }
     163             : 
     164             :   // oneof properties
     165           0 :   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     166           0 :     vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
     167           0 :     vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
     168           0 :     vars["original_name"] = descriptor_->oneof_decl(i)->name();
     169             :     printer->Print(
     170             :       vars,
     171             :       "private object $name$_;\n"
     172           0 :       "public enum $property_name$OneofCase {\n");
     173           0 :     printer->Indent();
     174           0 :     printer->Print("None = 0,\n");
     175           0 :     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
     176           0 :       const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
     177             :       printer->Print("$field_property_name$ = $index$,\n",
     178             :                      "field_property_name", GetPropertyName(field),
     179           0 :                      "index", SimpleItoa(field->number()));
     180             :     }
     181           0 :     printer->Outdent();
     182           0 :     printer->Print("}\n");
     183             :     printer->Print(
     184             :       vars,
     185             :       "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n"
     186             :       "public $property_name$OneofCase $property_name$Case {\n"
     187             :       "  get { return $name$Case_; }\n"
     188             :       "}\n\n"
     189             :       "public void Clear$property_name$() {\n"
     190             :       "  $name$Case_ = $property_name$OneofCase.None;\n"
     191             :       "  $name$_ = null;\n"
     192           0 :       "}\n\n");
     193             :   }
     194             : 
     195             :   // Standard methods
     196           0 :   GenerateFrameworkMethods(printer);
     197           0 :   GenerateMessageSerializationMethods(printer);
     198           0 :   GenerateMergingMethods(printer);
     199             : 
     200             :   // Nested messages and enums
     201           0 :   if (HasNestedGeneratedTypes()) {
     202             :     printer->Print("#region Nested types\n"
     203           0 :                    "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
     204           0 :     WriteGeneratedCodeAttributes(printer);
     205           0 :     printer->Print("public static partial class Types {\n");
     206           0 :     printer->Indent();
     207           0 :     for (int i = 0; i < descriptor_->enum_type_count(); i++) {
     208           0 :       EnumGenerator enumGenerator(descriptor_->enum_type(i));
     209           0 :       enumGenerator.Generate(printer);
     210           0 :     }
     211           0 :     for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     212             :       // Don't generate nested types for maps...
     213           0 :       if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
     214           0 :         MessageGenerator messageGenerator(descriptor_->nested_type(i));
     215           0 :         messageGenerator.Generate(printer);
     216             :       }
     217             :     }
     218           0 :     printer->Outdent();
     219             :     printer->Print("}\n"
     220             :                    "#endregion\n"
     221           0 :                    "\n");
     222             :   }
     223             : 
     224           0 :   printer->Outdent();
     225           0 :   printer->Print("}\n");
     226           0 :   printer->Print("\n");
     227           0 : }
     228             : 
     229             : // Helper to work out whether we need to generate a class to hold nested types/enums.
     230             : // Only tricky because we don't want to generate map entry types.
     231           0 : bool MessageGenerator::HasNestedGeneratedTypes()
     232             : {
     233           0 :   if (descriptor_->enum_type_count() > 0) {
     234             :     return true;
     235             :   }
     236           0 :   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     237           0 :     if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
     238             :       return true;
     239             :     }
     240             :   }
     241             :   return false;
     242             : }
     243             : 
     244           0 : void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
     245             :   map<string, string> vars;
     246           0 :   vars["class_name"] = class_name();
     247             :     printer->Print(
     248             :     vars,
     249           0 :     "public $class_name$($class_name$ other) : this() {\n");
     250           0 :   printer->Indent();
     251             :   // Clone non-oneof fields first
     252           0 :   for (int i = 0; i < descriptor_->field_count(); i++) {
     253           0 :     if (!descriptor_->field(i)->containing_oneof()) {
     254             :       scoped_ptr<FieldGeneratorBase> generator(
     255           0 :         CreateFieldGeneratorInternal(descriptor_->field(i)));
     256           0 :       generator->GenerateCloningCode(printer);
     257             :     }
     258             :   }
     259             :   // Clone just the right field for each oneof
     260           0 :   for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
     261           0 :     vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
     262           0 :     vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
     263           0 :     printer->Print(vars, "switch (other.$property_name$Case) {\n");
     264           0 :     printer->Indent();
     265           0 :     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
     266           0 :       const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
     267           0 :       scoped_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
     268           0 :       vars["field_property_name"] = GetPropertyName(field);
     269             :       printer->Print(
     270             :           vars,
     271           0 :           "case $property_name$OneofCase.$field_property_name$:\n");
     272           0 :       printer->Indent();
     273           0 :       generator->GenerateCloningCode(printer);
     274           0 :       printer->Print("break;\n");
     275           0 :       printer->Outdent();
     276             :     }
     277           0 :     printer->Outdent();
     278           0 :     printer->Print("}\n\n");
     279             :   }
     280             : 
     281           0 :   printer->Outdent();
     282           0 :   printer->Print("}\n\n");
     283             : 
     284             :   printer->Print(
     285             :     vars,
     286             :     "public $class_name$ Clone() {\n"
     287             :     "  return new $class_name$(this);\n"
     288           0 :     "}\n\n");
     289           0 : }
     290             : 
     291           0 : void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
     292           0 : }
     293             : 
     294           0 : void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
     295             :     map<string, string> vars;
     296           0 :     vars["class_name"] = class_name();
     297             : 
     298             :     // Equality
     299             :     printer->Print(
     300             :         vars,
     301             :         "public override bool Equals(object other) {\n"
     302             :         "  return Equals(other as $class_name$);\n"
     303             :         "}\n\n"
     304             :         "public bool Equals($class_name$ other) {\n"
     305             :         "  if (ReferenceEquals(other, null)) {\n"
     306             :         "    return false;\n"
     307             :         "  }\n"
     308             :         "  if (ReferenceEquals(other, this)) {\n"
     309             :         "    return true;\n"
     310           0 :         "  }\n");
     311           0 :     printer->Indent();
     312           0 :     for (int i = 0; i < descriptor_->field_count(); i++) {
     313             :         scoped_ptr<FieldGeneratorBase> generator(
     314           0 :             CreateFieldGeneratorInternal(descriptor_->field(i)));
     315           0 :         generator->WriteEquals(printer);
     316             :     }
     317           0 :     printer->Outdent();
     318             :     printer->Print(
     319             :         "  return true;\n"
     320           0 :         "}\n\n");
     321             : 
     322             :     // GetHashCode
     323             :     // Start with a non-zero value to easily distinguish between null and "empty" messages.
     324             :     printer->Print(
     325             :         "public override int GetHashCode() {\n"
     326           0 :         "  int hash = 1;\n");
     327           0 :     printer->Indent();
     328           0 :     for (int i = 0; i < descriptor_->field_count(); i++) {
     329             :         scoped_ptr<FieldGeneratorBase> generator(
     330           0 :             CreateFieldGeneratorInternal(descriptor_->field(i)));
     331           0 :         generator->WriteHash(printer);
     332             :     }
     333           0 :     printer->Print("return hash;\n");
     334           0 :     printer->Outdent();
     335           0 :     printer->Print("}\n\n");
     336             : 
     337             :     printer->Print(
     338             :         "public override string ToString() {\n"
     339             :         "  return pb::JsonFormatter.Default.Format(this);\n"
     340           0 :         "}\n\n");
     341           0 : }
     342             : 
     343           0 : void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
     344             :   printer->Print(
     345           0 :       "public void WriteTo(pb::CodedOutputStream output) {\n");
     346           0 :   printer->Indent();
     347             : 
     348             :   // Serialize all the fields
     349           0 :   for (int i = 0; i < fields_by_number().size(); i++) {
     350             :     scoped_ptr<FieldGeneratorBase> generator(
     351           0 :       CreateFieldGeneratorInternal(fields_by_number()[i]));
     352           0 :     generator->GenerateSerializationCode(printer);
     353             :   }
     354             : 
     355             :   // TODO(jonskeet): Memoize size of frozen messages?
     356           0 :   printer->Outdent();
     357             :   printer->Print(
     358             :     "}\n"
     359             :     "\n"
     360           0 :     "public int CalculateSize() {\n");
     361           0 :   printer->Indent();
     362           0 :   printer->Print("int size = 0;\n");
     363           0 :   for (int i = 0; i < descriptor_->field_count(); i++) {
     364             :     scoped_ptr<FieldGeneratorBase> generator(
     365           0 :         CreateFieldGeneratorInternal(descriptor_->field(i)));
     366           0 :     generator->GenerateSerializedSizeCode(printer);
     367             :   }
     368           0 :   printer->Print("return size;\n");
     369           0 :   printer->Outdent();
     370           0 :   printer->Print("}\n\n");
     371           0 : }
     372             : 
     373           0 : void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
     374             :   // Note:  These are separate from GenerateMessageSerializationMethods()
     375             :   //   because they need to be generated even for messages that are optimized
     376             :   //   for code size.
     377             :   map<string, string> vars;
     378           0 :   vars["class_name"] = class_name();
     379             : 
     380             :   printer->Print(
     381             :     vars,
     382           0 :     "public void MergeFrom($class_name$ other) {\n");
     383           0 :   printer->Indent();
     384             :   printer->Print(
     385             :     "if (other == null) {\n"
     386             :     "  return;\n"
     387           0 :     "}\n");
     388             :   // Merge non-oneof fields
     389           0 :   for (int i = 0; i < descriptor_->field_count(); i++) {
     390           0 :     if (!descriptor_->field(i)->containing_oneof()) {      
     391             :       scoped_ptr<FieldGeneratorBase> generator(
     392           0 :           CreateFieldGeneratorInternal(descriptor_->field(i)));
     393           0 :       generator->GenerateMergingCode(printer);
     394             :     }
     395             :   }
     396             :   // Merge oneof fields
     397           0 :   for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
     398           0 :     vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
     399           0 :     vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
     400           0 :     printer->Print(vars, "switch (other.$property_name$Case) {\n");
     401           0 :     printer->Indent();
     402           0 :     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
     403           0 :       const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
     404           0 :       vars["field_property_name"] = GetPropertyName(field);
     405             :       printer->Print(
     406             :         vars,
     407             :         "case $property_name$OneofCase.$field_property_name$:\n"
     408             :         "  $field_property_name$ = other.$field_property_name$;\n"
     409           0 :         "  break;\n");
     410             :     }
     411           0 :     printer->Outdent();
     412           0 :     printer->Print("}\n\n");
     413             :   }
     414           0 :   printer->Outdent();
     415           0 :   printer->Print("}\n\n");
     416           0 :   printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
     417           0 :   printer->Indent();
     418             :   printer->Print(
     419             :     "uint tag;\n"
     420             :     "while ((tag = input.ReadTag()) != 0) {\n"
     421           0 :     "  switch(tag) {\n");
     422           0 :   printer->Indent();
     423           0 :   printer->Indent();
     424             :   printer->Print(
     425             :     "default:\n"
     426             :     "  input.SkipLastField();\n" // We're not storing the data, but we still need to consume it.
     427           0 :     "  break;\n");
     428           0 :   for (int i = 0; i < fields_by_number().size(); i++) {
     429           0 :     const FieldDescriptor* field = fields_by_number()[i];
     430             :     internal::WireFormatLite::WireType wt =
     431           0 :         internal::WireFormat::WireTypeForFieldType(field->type());
     432           0 :     uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
     433             :     // Handle both packed and unpacked repeated fields with the same Read*Array call;
     434             :     // the two generated cases are the packed and unpacked tags.
     435             :     // TODO(jonskeet): Check that is_packable is equivalent to is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
     436             :     // It looks like it is...
     437           0 :     if (field->is_packable()) {
     438             :       printer->Print(
     439             :         "case $packed_tag$:\n",
     440             :         "packed_tag",
     441             :         SimpleItoa(
     442             :             internal::WireFormatLite::MakeTag(
     443             :                 field->number(),
     444           0 :                 internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
     445             :     }
     446             : 
     447           0 :     printer->Print("case $tag$: {\n", "tag", SimpleItoa(tag));
     448           0 :     printer->Indent();
     449             :     scoped_ptr<FieldGeneratorBase> generator(
     450           0 :         CreateFieldGeneratorInternal(field));
     451           0 :     generator->GenerateParsingCode(printer);
     452           0 :     printer->Print("break;\n");
     453           0 :     printer->Outdent();
     454           0 :     printer->Print("}\n");
     455             :   }
     456           0 :   printer->Outdent();
     457           0 :   printer->Print("}\n"); // switch
     458           0 :   printer->Outdent();
     459           0 :   printer->Print("}\n"); // while
     460           0 :   printer->Outdent();
     461           0 :   printer->Print("}\n\n"); // method
     462           0 : }
     463             : 
     464           0 : int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
     465           0 :   for (int i = 0; i < field_names().size(); i++) {
     466           0 :     if (field_names()[i] == descriptor->name()) {
     467             :       return i;
     468             :     }
     469             :   }
     470           0 :   GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name();
     471           0 :   return -1;
     472             : }
     473             : 
     474           0 : FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
     475             :     const FieldDescriptor* descriptor) {
     476           0 :   return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor));
     477             : }
     478             : 
     479             : }  // namespace csharp
     480             : }  // namespace compiler
     481             : }  // namespace protobuf
     482             : }  // namespace google

Generated by: LCOV version 1.10