• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/descriptor.h>
35 #include <google/protobuf/descriptor.pb.h>
36 #include <google/protobuf/io/printer.h>
37 #include <google/protobuf/io/zero_copy_stream.h>
38 #include <google/protobuf/stubs/strutil.h>
39 #include <google/protobuf/wire_format.h>
40 #include <google/protobuf/wire_format_lite.h>
41 
42 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
43 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
44 #include <google/protobuf/compiler/csharp/csharp_message_field.h>
45 #include <google/protobuf/compiler/csharp/csharp_options.h>
46 
47 namespace google {
48 namespace protobuf {
49 namespace compiler {
50 namespace csharp {
51 
MessageFieldGenerator(const FieldDescriptor * descriptor,int presenceIndex,const Options * options)52 MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
53                                              int presenceIndex,
54                                              const Options *options)
55     : FieldGeneratorBase(descriptor, presenceIndex, options) {
56   if (!IsProto2(descriptor_->file())) {
57     variables_["has_property_check"] = name() + "_ != null";
58     variables_["has_not_property_check"] = name() + "_ == null";
59   }
60 }
61 
~MessageFieldGenerator()62 MessageFieldGenerator::~MessageFieldGenerator() {
63 
64 }
65 
GenerateMembers(io::Printer * printer)66 void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
67   printer->Print(
68     variables_,
69     "private $type_name$ $name$_;\n");
70   WritePropertyDocComment(printer, descriptor_);
71   AddPublicMemberAttributes(printer);
72   printer->Print(
73     variables_,
74     "$access_level$ $type_name$ $property_name$ {\n"
75     "  get { return $name$_; }\n"
76     "  set {\n"
77     "    $name$_ = value;\n"
78     "  }\n"
79     "}\n");
80   if (IsProto2(descriptor_->file())) {
81     printer->Print(
82       variables_,
83       "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
84     AddPublicMemberAttributes(printer);
85     printer->Print(
86       variables_,
87       "$access_level$ bool Has$property_name$ {\n"
88       "  get { return $name$_ != null; }\n"
89       "}\n");
90     printer->Print(
91       variables_,
92       "/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
93     AddPublicMemberAttributes(printer);
94     printer->Print(
95       variables_,
96       "$access_level$ void Clear$property_name$() {\n"
97       "  $name$_ = null;\n"
98       "}\n");
99   }
100 }
101 
GenerateMergingCode(io::Printer * printer)102 void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
103   printer->Print(
104     variables_,
105     "if (other.$has_property_check$) {\n"
106     "  if ($has_not_property_check$) {\n"
107     "    $property_name$ = new $type_name$();\n"
108     "  }\n"
109     "  $property_name$.MergeFrom(other.$property_name$);\n"
110     "}\n");
111 }
112 
GenerateParsingCode(io::Printer * printer)113 void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
114   printer->Print(
115     variables_,
116     "if ($has_not_property_check$) {\n"
117     "  $property_name$ = new $type_name$();\n"
118     "}\n");
119   if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
120     printer->Print(variables_, "input.ReadMessage($property_name$);\n");
121   } else {
122     printer->Print(variables_, "input.ReadGroup($property_name$);\n");
123   }
124 }
125 
GenerateSerializationCode(io::Printer * printer)126 void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
127   if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
128     printer->Print(
129       variables_,
130       "if ($has_property_check$) {\n"
131       "  output.WriteRawTag($tag_bytes$);\n"
132       "  output.WriteMessage($property_name$);\n"
133       "}\n");
134   } else {
135     printer->Print(
136       variables_,
137       "if ($has_property_check$) {\n"
138       "  output.WriteRawTag($tag_bytes$);\n"
139       "  output.WriteGroup($property_name$);\n"
140       "  output.WriteRawTag($end_tag_bytes$);\n"
141       "}\n");
142   }
143 }
144 
GenerateSerializedSizeCode(io::Printer * printer)145 void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
146   if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
147     printer->Print(
148       variables_,
149       "if ($has_property_check$) {\n"
150       "  size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
151       "}\n");
152   } else {
153     printer->Print(
154       variables_,
155       "if ($has_property_check$) {\n"
156       "  size += $tag_size$ + pb::CodedOutputStream.ComputeGroupSize($property_name$);\n"
157       "}\n");
158   }
159 }
160 
WriteHash(io::Printer * printer)161 void MessageFieldGenerator::WriteHash(io::Printer* printer) {
162   printer->Print(
163     variables_,
164     "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
165 }
WriteEquals(io::Printer * printer)166 void MessageFieldGenerator::WriteEquals(io::Printer* printer) {
167   printer->Print(
168     variables_,
169     "if (!object.Equals($property_name$, other.$property_name$)) return false;\n");
170 }
WriteToString(io::Printer * printer)171 void MessageFieldGenerator::WriteToString(io::Printer* printer) {
172   variables_["field_name"] = GetFieldName(descriptor_);
173   printer->Print(
174     variables_,
175     "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
176 }
GenerateExtensionCode(io::Printer * printer)177 void MessageFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
178   WritePropertyDocComment(printer, descriptor_);
179   AddDeprecatedFlag(printer);
180   printer->Print(
181     variables_,
182     "$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
183     "  new pb::Extension<$extended_type$, $type_name$>($number$, ");
184   GenerateCodecCode(printer);
185   printer->Print(");\n");
186 }
GenerateCloningCode(io::Printer * printer)187 void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
188   printer->Print(variables_,
189     "$name$_ = other.$has_property_check$ ? other.$name$_.Clone() : null;\n");
190 }
191 
GenerateFreezingCode(io::Printer * printer)192 void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
193 }
194 
GenerateCodecCode(io::Printer * printer)195 void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
196   if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
197     printer->Print(
198       variables_,
199       "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
200   } else {
201     printer->Print(
202       variables_,
203       "pb::FieldCodec.ForGroup($tag$, $end_tag$, $type_name$.Parser)");
204   }
205 }
206 
MessageOneofFieldGenerator(const FieldDescriptor * descriptor,int presenceIndex,const Options * options)207 MessageOneofFieldGenerator::MessageOneofFieldGenerator(
208     const FieldDescriptor* descriptor,
209 	  int presenceIndex,
210     const Options *options)
211     : MessageFieldGenerator(descriptor, presenceIndex, options) {
212   SetCommonOneofFieldVariables(&variables_);
213 }
214 
~MessageOneofFieldGenerator()215 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {
216 
217 }
218 
GenerateMembers(io::Printer * printer)219 void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
220   WritePropertyDocComment(printer, descriptor_);
221   AddPublicMemberAttributes(printer);
222   printer->Print(
223     variables_,
224     "$access_level$ $type_name$ $property_name$ {\n"
225     "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
226     "  set {\n"
227     "    $oneof_name$_ = value;\n"
228     "    $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
229     "  }\n"
230     "}\n");
231   if (IsProto2(descriptor_->file())) {
232     printer->Print(
233       variables_,
234       "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
235     AddPublicMemberAttributes(printer);
236     printer->Print(
237       variables_,
238       "$access_level$ bool Has$property_name$ {\n"
239       "  get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
240       "}\n");
241     printer->Print(
242       variables_,
243       "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
244     AddPublicMemberAttributes(printer);
245     printer->Print(
246       variables_,
247       "$access_level$ void Clear$property_name$() {\n"
248       "  if ($has_property_check$) {\n"
249       "    Clear$oneof_property_name$();\n"
250       "  }\n"
251       "}\n");
252   }
253 }
254 
GenerateMergingCode(io::Printer * printer)255 void MessageOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
256   printer->Print(variables_,
257     "if ($property_name$ == null) {\n"
258     "  $property_name$ = new $type_name$();\n"
259     "}\n"
260     "$property_name$.MergeFrom(other.$property_name$);\n");
261 }
262 
GenerateParsingCode(io::Printer * printer)263 void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
264   // TODO(jonskeet): We may be able to do better than this
265   printer->Print(
266     variables_,
267     "$type_name$ subBuilder = new $type_name$();\n"
268     "if ($has_property_check$) {\n"
269     "  subBuilder.MergeFrom($property_name$);\n"
270     "}\n");
271   if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
272     printer->Print("input.ReadMessage(subBuilder);\n");
273   } else {
274     printer->Print("input.ReadGroup(subBuilder);\n");
275   }
276   printer->Print(variables_, "$property_name$ = subBuilder;\n");
277 }
278 
WriteToString(io::Printer * printer)279 void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) {
280   printer->Print(
281     variables_,
282     "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
283 }
284 
GenerateCloningCode(io::Printer * printer)285 void MessageOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
286   printer->Print(variables_,
287     "$property_name$ = other.$property_name$.Clone();\n");
288 }
289 
290 }  // namespace csharp
291 }  // namespace compiler
292 }  // namespace protobuf
293 }  // namespace google
294