1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "google/protobuf/compiler/csharp/csharp_message_field.h"
9
10 #include <sstream>
11
12 #include "google/protobuf/compiler/code_generator.h"
13 #include "google/protobuf/descriptor.h"
14 #include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
15 #include "google/protobuf/compiler/csharp/csharp_helpers.h"
16 #include "google/protobuf/compiler/csharp/csharp_options.h"
17 #include "google/protobuf/descriptor.pb.h"
18 #include "google/protobuf/io/printer.h"
19
20 namespace google {
21 namespace protobuf {
22 namespace compiler {
23 namespace csharp {
24
MessageFieldGenerator(const FieldDescriptor * descriptor,int presenceIndex,const Options * options)25 MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
26 int presenceIndex,
27 const Options *options)
28 : FieldGeneratorBase(descriptor, presenceIndex, options) {
29 if (!SupportsPresenceApi(descriptor_)) {
30 variables_["has_property_check"] = absl::StrCat(name(), "_ != null");
31 variables_["has_not_property_check"] = absl::StrCat(name(), "_ == null");
32 }
33 }
34
~MessageFieldGenerator()35 MessageFieldGenerator::~MessageFieldGenerator() {
36
37 }
38
GenerateMembers(io::Printer * printer)39 void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
40 printer->Print(
41 variables_,
42 "private $type_name$ $name$_;\n");
43 WritePropertyDocComment(printer, options(), descriptor_);
44 AddPublicMemberAttributes(printer);
45 printer->Print(
46 variables_,
47 "$access_level$ $type_name$ $property_name$ {\n"
48 " get { return $name$_; }\n"
49 " set {\n"
50 " $name$_ = value;\n"
51 " }\n"
52 "}\n");
53 if (SupportsPresenceApi(descriptor_)) {
54 printer->Print(
55 variables_,
56 "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
57 AddPublicMemberAttributes(printer);
58 printer->Print(
59 variables_,
60 "$access_level$ bool Has$property_name$ {\n"
61 " get { return $name$_ != null; }\n"
62 "}\n");
63 printer->Print(
64 variables_,
65 "/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
66 AddPublicMemberAttributes(printer);
67 printer->Print(
68 variables_,
69 "$access_level$ void Clear$property_name$() {\n"
70 " $name$_ = null;\n"
71 "}\n");
72 }
73 }
74
GenerateMergingCode(io::Printer * printer)75 void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
76 printer->Print(
77 variables_,
78 "if (other.$has_property_check$) {\n"
79 " if ($has_not_property_check$) {\n"
80 " $property_name$ = new $type_name$();\n"
81 " }\n"
82 " $property_name$.MergeFrom(other.$property_name$);\n"
83 "}\n");
84 }
85
GenerateParsingCode(io::Printer * printer)86 void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
87 printer->Print(
88 variables_,
89 "if ($has_not_property_check$) {\n"
90 " $property_name$ = new $type_name$();\n"
91 "}\n");
92 if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
93 printer->Print(variables_, "input.ReadMessage($property_name$);\n");
94 } else {
95 printer->Print(variables_, "input.ReadGroup($property_name$);\n");
96 }
97 }
98
GenerateSerializationCode(io::Printer * printer)99 void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
100 if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
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 } else {
108 printer->Print(
109 variables_,
110 "if ($has_property_check$) {\n"
111 " output.WriteRawTag($tag_bytes$);\n"
112 " output.WriteGroup($property_name$);\n"
113 " output.WriteRawTag($end_tag_bytes$);\n"
114 "}\n");
115 }
116 }
117
GenerateSerializedSizeCode(io::Printer * printer)118 void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
119 if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
120 printer->Print(
121 variables_,
122 "if ($has_property_check$) {\n"
123 " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n"
124 "}\n");
125 } else {
126 printer->Print(
127 variables_,
128 "if ($has_property_check$) {\n"
129 " size += $tag_size$ + pb::CodedOutputStream.ComputeGroupSize($property_name$);\n"
130 "}\n");
131 }
132 }
133
WriteHash(io::Printer * printer)134 void MessageFieldGenerator::WriteHash(io::Printer* printer) {
135 printer->Print(
136 variables_,
137 "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
138 }
WriteEquals(io::Printer * printer)139 void MessageFieldGenerator::WriteEquals(io::Printer* printer) {
140 printer->Print(
141 variables_,
142 "if (!object.Equals($property_name$, other.$property_name$)) return false;\n");
143 }
WriteToString(io::Printer * printer)144 void MessageFieldGenerator::WriteToString(io::Printer* printer) {
145 variables_["field_name"] = GetFieldName(descriptor_);
146 printer->Print(
147 variables_,
148 "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
149 }
GenerateExtensionCode(io::Printer * printer)150 void MessageFieldGenerator::GenerateExtensionCode(io::Printer* printer) {
151 WritePropertyDocComment(printer, options(), descriptor_);
152 AddDeprecatedFlag(printer);
153 printer->Print(
154 variables_,
155 "$access_level$ static readonly pb::Extension<$extended_type$, $type_name$> $property_name$ =\n"
156 " new pb::Extension<$extended_type$, $type_name$>($number$, ");
157 GenerateCodecCode(printer);
158 printer->Print(");\n");
159 }
GenerateCloningCode(io::Printer * printer)160 void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
161 printer->Print(variables_,
162 "$name$_ = other.$has_property_check$ ? other.$name$_.Clone() : null;\n");
163 }
164
GenerateFreezingCode(io::Printer * printer)165 void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
166 }
167
GenerateCodecCode(io::Printer * printer)168 void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
169 if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
170 printer->Print(
171 variables_,
172 "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
173 } else {
174 printer->Print(
175 variables_,
176 "pb::FieldCodec.ForGroup($tag$, $end_tag$, $type_name$.Parser)");
177 }
178 }
179
MessageOneofFieldGenerator(const FieldDescriptor * descriptor,int presenceIndex,const Options * options)180 MessageOneofFieldGenerator::MessageOneofFieldGenerator(
181 const FieldDescriptor* descriptor,
182 int presenceIndex,
183 const Options *options)
184 : MessageFieldGenerator(descriptor, presenceIndex, options) {
185 SetCommonOneofFieldVariables(&variables_);
186 }
187
~MessageOneofFieldGenerator()188 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {
189
190 }
191
GenerateMembers(io::Printer * printer)192 void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
193 WritePropertyDocComment(printer, options(), descriptor_);
194 AddPublicMemberAttributes(printer);
195 printer->Print(
196 variables_,
197 "$access_level$ $type_name$ $property_name$ {\n"
198 " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
199 " set {\n"
200 " $oneof_name$_ = value;\n"
201 " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$oneof_case_name$;\n"
202 " }\n"
203 "}\n");
204 if (SupportsPresenceApi(descriptor_)) {
205 printer->Print(
206 variables_,
207 "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
208 AddPublicMemberAttributes(printer);
209 printer->Print(
210 variables_,
211 "$access_level$ bool Has$property_name$ {\n"
212 " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$oneof_case_name$; }\n"
213 "}\n");
214 printer->Print(
215 variables_,
216 "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
217 AddPublicMemberAttributes(printer);
218 printer->Print(
219 variables_,
220 "$access_level$ void Clear$property_name$() {\n"
221 " if ($has_property_check$) {\n"
222 " Clear$oneof_property_name$();\n"
223 " }\n"
224 "}\n");
225 }
226 }
227
GenerateMergingCode(io::Printer * printer)228 void MessageOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
229 printer->Print(variables_,
230 "if ($property_name$ == null) {\n"
231 " $property_name$ = new $type_name$();\n"
232 "}\n"
233 "$property_name$.MergeFrom(other.$property_name$);\n");
234 }
235
GenerateParsingCode(io::Printer * printer)236 void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
237 // TODO: We may be able to do better than this
238 printer->Print(
239 variables_,
240 "$type_name$ subBuilder = new $type_name$();\n"
241 "if ($has_property_check$) {\n"
242 " subBuilder.MergeFrom($property_name$);\n"
243 "}\n");
244 if (descriptor_->type() == FieldDescriptor::Type::TYPE_MESSAGE) {
245 printer->Print("input.ReadMessage(subBuilder);\n");
246 } else {
247 printer->Print("input.ReadGroup(subBuilder);\n");
248 }
249 printer->Print(variables_, "$property_name$ = subBuilder;\n");
250 }
251
WriteToString(io::Printer * printer)252 void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) {
253 printer->Print(
254 variables_,
255 "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
256 }
257
GenerateCloningCode(io::Printer * printer)258 void MessageOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
259 printer->Print(variables_,
260 "$property_name$ = other.$property_name$.Clone();\n");
261 }
262
263 } // namespace csharp
264 } // namespace compiler
265 } // namespace protobuf
266 } // namespace google
267