Home | History | Annotate | Download | only in csharp
      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 
     33 #include <google/protobuf/compiler/code_generator.h>
     34 #include <google/protobuf/compiler/plugin.h>
     35 #include <google/protobuf/descriptor.h>
     36 #include <google/protobuf/descriptor.pb.h>
     37 #include <google/protobuf/io/printer.h>
     38 #include <google/protobuf/io/zero_copy_stream.h>
     39 #include <google/protobuf/stubs/strutil.h>
     40 
     41 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
     42 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
     43 #include <google/protobuf/compiler/csharp/csharp_message_field.h>
     44 #include <google/protobuf/compiler/csharp/csharp_options.h>
     45 
     46 namespace google {
     47 namespace protobuf {
     48 namespace compiler {
     49 namespace csharp {
     50 
     51 MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
     52                                              int fieldOrdinal,
     53                                              const Options *options)
     54     : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
     55   variables_["has_property_check"] = name() + "_ != null";
     56   variables_["has_not_property_check"] = name() + "_ == null";
     57 }
     58 
     59 MessageFieldGenerator::~MessageFieldGenerator() {
     60 
     61 }
     62 
     63 void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
     64   printer->Print(
     65     variables_,
     66     "private $type_name$ $name$_;\n");
     67   WritePropertyDocComment(printer, descriptor_);
     68   AddDeprecatedFlag(printer);
     69   printer->Print(
     70     variables_,
     71     "$access_level$ $type_name$ $property_name$ {\n"
     72     "  get { return $name$_; }\n"
     73     "  set {\n"
     74     "    $name$_ = value;\n"
     75     "  }\n"
     76     "}\n");
     77 }
     78 
     79 void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
     80   printer->Print(
     81     variables_,
     82     "if (other.$has_property_check$) {\n"
     83     "  if ($has_not_property_check$) {\n"
     84     "    $name$_ = new $type_name$();\n"
     85     "  }\n"
     86     "  $property_name$.MergeFrom(other.$property_name$);\n"
     87     "}\n");
     88 }
     89 
     90 void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
     91   printer->Print(
     92     variables_,
     93     "if ($has_not_property_check$) {\n"
     94     "  $name$_ = new $type_name$();\n"
     95     "}\n"
     96     // TODO(jonskeet): Do we really need merging behaviour like this?
     97     "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP...
     98 }
     99 
    100 void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
    101   printer->Print(
    102     variables_,
    103     "if ($has_property_check$) {\n"
    104     "  output.WriteRawTag($tag_bytes$);\n"
    105     "  output.WriteMessage($property_name$);\n"
    106     "}\n");
    107 }
    108 
    109 void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
    110   printer->Print(
    111     variables_,
    112     "if ($has_property_check$) {\n"
    113     "  size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
    114     "}\n");
    115 }
    116 
    117 void MessageFieldGenerator::WriteHash(io::Printer* printer) {
    118   printer->Print(
    119     variables_,
    120     "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
    121 }
    122 void MessageFieldGenerator::WriteEquals(io::Printer* printer) {
    123   printer->Print(
    124     variables_,
    125     "if (!object.Equals($property_name$, other.$property_name$)) return false;\n");
    126 }
    127 void MessageFieldGenerator::WriteToString(io::Printer* printer) {
    128   variables_["field_name"] = GetFieldName(descriptor_);
    129   printer->Print(
    130     variables_,
    131     "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
    132 }
    133 
    134 void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
    135   printer->Print(variables_,
    136     "$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n");
    137 }
    138 
    139 void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
    140 }
    141 
    142 void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
    143   printer->Print(
    144     variables_,
    145     "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
    146 }
    147 
    148 MessageOneofFieldGenerator::MessageOneofFieldGenerator(
    149     const FieldDescriptor* descriptor,
    150 	  int fieldOrdinal,
    151     const Options *options)
    152     : MessageFieldGenerator(descriptor, fieldOrdinal, options) {
    153   SetCommonOneofFieldVariables(&variables_);
    154 }
    155 
    156 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {
    157 
    158 }
    159 
    160 void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
    161   WritePropertyDocComment(printer, descriptor_);
    162   AddDeprecatedFlag(printer);
    163   printer->Print(
    164     variables_,
    165     "$access_level$ $type_name$ $property_name$ {\n"
    166     "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
    167     "  set {\n"
    168     "    $oneof_name$_ = value;\n"
    169     "    $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
    170     "  }\n"
    171     "}\n");
    172 }
    173 
    174 void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
    175   // TODO(jonskeet): We may be able to do better than this
    176   printer->Print(
    177     variables_,
    178     "$type_name$ subBuilder = new $type_name$();\n"
    179     "if ($has_property_check$) {\n"
    180     "  subBuilder.MergeFrom($property_name$);\n"
    181     "}\n"
    182     "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP
    183     "$property_name$ = subBuilder;\n");
    184 }
    185 
    186 void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) {
    187   printer->Print(
    188     variables_,
    189     "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
    190 }
    191 
    192 void MessageOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
    193   printer->Print(variables_,
    194     "$property_name$ = other.$property_name$.Clone();\n");
    195 }
    196 
    197 }  // namespace csharp
    198 }  // namespace compiler
    199 }  // namespace protobuf
    200 }  // namespace google
    201