blob: 3b88954c64e9b69cd656fe0e2dbdf6f15ff8ce84 [file] [log] [blame]
Jan Tattermusch685ae362015-03-16 19:07:16 -07001// 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 <limits>
32#include <sstream>
33
34#include <google/protobuf/compiler/code_generator.h>
35#include <google/protobuf/compiler/plugin.h>
36#include <google/protobuf/descriptor.h>
37#include <google/protobuf/descriptor.pb.h>
Jon Skeet828b7e62015-06-17 14:59:10 +010038#include <google/protobuf/io/coded_stream.h>
Jan Tattermusch685ae362015-03-16 19:07:16 -070039#include <google/protobuf/io/printer.h>
40#include <google/protobuf/io/zero_copy_stream.h>
Karol Ostrovskyee354022015-06-29 16:13:33 +020041#include <google/protobuf/stubs/mathlimits.h>
Jan Tattermusch685ae362015-03-16 19:07:16 -070042#include <google/protobuf/stubs/strutil.h>
Jon Skeete38294a2015-06-09 19:30:44 +010043#include <google/protobuf/wire_format.h>
Jan Tattermusch685ae362015-03-16 19:07:16 -070044
45#include <google/protobuf/compiler/csharp/csharp_field_base.h>
46#include <google/protobuf/compiler/csharp/csharp_helpers.h>
Jan Tattermuschcacbedf2015-07-10 13:40:34 -070047#include <google/protobuf/compiler/csharp/csharp_names.h>
Jan Tattermusch685ae362015-03-16 19:07:16 -070048
49using google::protobuf::internal::scoped_ptr;
50
51namespace google {
52namespace protobuf {
53namespace compiler {
54namespace csharp {
55
Jie Luo90da3512015-06-03 18:02:17 -070056void FieldGeneratorBase::SetCommonFieldVariables(
57 map<string, string>* variables) {
Jon Skeete38294a2015-06-09 19:30:44 +010058 // Note: this will be valid even though the tag emitted for packed and unpacked versions of
59 // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
60 // never effects the tag size.
Jon Skeet828b7e62015-06-17 14:59:10 +010061 int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
Jon Skeet93bdf362015-08-07 13:43:05 +010062 uint tag = internal::WireFormat::MakeTag(descriptor_);
Jon Skeet828b7e62015-06-17 14:59:10 +010063 uint8 tag_array[5];
64 io::CodedOutputStream::WriteTagToArray(tag, tag_array);
65 string tag_bytes = SimpleItoa(tag_array[0]);
66 for (int i = 1; i < tag_size; i++) {
67 tag_bytes += ", " + SimpleItoa(tag_array[i]);
68 }
69
Jan Tattermuschfa2fe352015-08-14 13:38:34 -070070 (*variables)["access_level"] = "public";
Jon Skeet0d684d32015-06-24 17:21:55 +010071 (*variables)["tag"] = SimpleItoa(tag);
Jon Skeet828b7e62015-06-17 14:59:10 +010072 (*variables)["tag_size"] = SimpleItoa(tag_size);
73 (*variables)["tag_bytes"] = tag_bytes;
74
Jie Luo90da3512015-06-03 18:02:17 -070075 (*variables)["property_name"] = property_name();
76 (*variables)["type_name"] = type_name();
77 (*variables)["name"] = name();
78 (*variables)["descriptor_name"] = descriptor_->name();
79 (*variables)["default_value"] = default_value();
80 if (has_default_value()) {
81 (*variables)["name_def_message"] =
82 (*variables)["name"] + "_ = " + (*variables)["default_value"];
83 } else {
84 (*variables)["name_def_message"] = (*variables)["name"] + "_";
85 }
86 (*variables)["capitalized_type_name"] = capitalized_type_name();
87 (*variables)["number"] = number();
Jon Skeete38294a2015-06-09 19:30:44 +010088 (*variables)["has_property_check"] =
89 (*variables)["property_name"] + " != " + (*variables)["default_value"];
90 (*variables)["other_has_property_check"] = "other." +
91 (*variables)["property_name"] + " != " + (*variables)["default_value"];
Jie Luo90da3512015-06-03 18:02:17 -070092}
93
94void FieldGeneratorBase::SetCommonOneofFieldVariables(
95 map<string, string>* variables) {
96 (*variables)["oneof_name"] = oneof_name();
Jon Skeetbfd1c842016-04-06 10:17:13 +010097 (*variables)["has_property_check"] =
98 oneof_name() + "Case_ == " + oneof_property_name() +
Jie Luo90da3512015-06-03 18:02:17 -070099 "OneofCase." + property_name();
100 (*variables)["oneof_property_name"] = oneof_property_name();
101}
102
Jan Tattermusch685ae362015-03-16 19:07:16 -0700103FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
Gaurav Vaish74d8b0b2016-03-24 11:44:56 -0700104 int fieldOrdinal, const Options* options)
105 : SourceGeneratorBase(descriptor->file(), options),
Jan Tattermusch685ae362015-03-16 19:07:16 -0700106 descriptor_(descriptor),
107 fieldOrdinal_(fieldOrdinal) {
Jie Luo90da3512015-06-03 18:02:17 -0700108 SetCommonFieldVariables(&variables_);
Jan Tattermusch685ae362015-03-16 19:07:16 -0700109}
110
111FieldGeneratorBase::~FieldGeneratorBase() {
112}
113
Jon Skeetbfee2df2015-06-23 16:09:27 +0100114void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) {
115 // No-op: only message fields and repeated fields need
116 // special handling for freezing, so default to not generating any code.
117}
118
Jon Skeet0d684d32015-06-24 17:21:55 +0100119void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) {
120 // No-op: expect this to be overridden by appropriate types.
121 // Could fail if we get called here though...
122}
123
Jie Luo90da3512015-06-03 18:02:17 -0700124void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
Jan Tattermusch8cec65e2015-04-13 14:21:33 -0700125 if (descriptor_->options().deprecated())
126 {
Jie Luo90da3512015-06-03 18:02:17 -0700127 printer->Print("[global::System.ObsoleteAttribute()]\n");
Jan Tattermusch8cec65e2015-04-13 14:21:33 -0700128 }
Jan Tattermusch685ae362015-03-16 19:07:16 -0700129}
130
Jie Luo90da3512015-06-03 18:02:17 -0700131void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) {
132 AddDeprecatedFlag(printer);
Jan Tattermusch685ae362015-03-16 19:07:16 -0700133}
134
Jie Luof7b417d2015-05-29 12:48:25 -0700135std::string FieldGeneratorBase::oneof_property_name() {
136 return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true);
137}
138
139std::string FieldGeneratorBase::oneof_name() {
140 return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false);
141}
142
Jan Tattermusch685ae362015-03-16 19:07:16 -0700143std::string FieldGeneratorBase::property_name() {
144 return GetPropertyName(descriptor_);
145}
146
147std::string FieldGeneratorBase::name() {
148 return UnderscoresToCamelCase(GetFieldName(descriptor_), false);
149}
150
151std::string FieldGeneratorBase::type_name() {
Jon Skeet0d684d32015-06-24 17:21:55 +0100152 return type_name(descriptor_);
153}
154
155std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
156 switch (descriptor->type()) {
Jan Tattermusch685ae362015-03-16 19:07:16 -0700157 case FieldDescriptor::TYPE_ENUM:
Jon Skeet0d684d32015-06-24 17:21:55 +0100158 return GetClassName(descriptor->enum_type());
Jan Tattermusch685ae362015-03-16 19:07:16 -0700159 case FieldDescriptor::TYPE_MESSAGE:
160 case FieldDescriptor::TYPE_GROUP:
Jon Skeetb2ac8682015-07-15 13:17:42 +0100161 if (IsWrapperType(descriptor)) {
Jon Skeetbfd1c842016-04-06 10:17:13 +0100162 const FieldDescriptor* wrapped_field =
163 descriptor->message_type()->field(0);
Jon Skeetb2ac8682015-07-15 13:17:42 +0100164 string wrapped_field_type_name = type_name(wrapped_field);
Jon Skeetbfd1c842016-04-06 10:17:13 +0100165 // String and ByteString go to the same type; other wrapped types
166 // go to the nullable equivalent.
Jon Skeetb2ac8682015-07-15 13:17:42 +0100167 if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
168 wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
169 return wrapped_field_type_name;
170 } else {
171 return wrapped_field_type_name + "?";
172 }
173 }
Jon Skeet0d684d32015-06-24 17:21:55 +0100174 return GetClassName(descriptor->message_type());
Jan Tattermusch685ae362015-03-16 19:07:16 -0700175 case FieldDescriptor::TYPE_DOUBLE:
176 return "double";
177 case FieldDescriptor::TYPE_FLOAT:
178 return "float";
179 case FieldDescriptor::TYPE_INT64:
180 return "long";
181 case FieldDescriptor::TYPE_UINT64:
182 return "ulong";
183 case FieldDescriptor::TYPE_INT32:
184 return "int";
185 case FieldDescriptor::TYPE_FIXED64:
186 return "ulong";
187 case FieldDescriptor::TYPE_FIXED32:
188 return "uint";
189 case FieldDescriptor::TYPE_BOOL:
190 return "bool";
191 case FieldDescriptor::TYPE_STRING:
192 return "string";
193 case FieldDescriptor::TYPE_BYTES:
194 return "pb::ByteString";
195 case FieldDescriptor::TYPE_UINT32:
196 return "uint";
197 case FieldDescriptor::TYPE_SFIXED32:
198 return "int";
199 case FieldDescriptor::TYPE_SFIXED64:
200 return "long";
201 case FieldDescriptor::TYPE_SINT32:
202 return "int";
203 case FieldDescriptor::TYPE_SINT64:
204 return "long";
205 default:
206 GOOGLE_LOG(FATAL)<< "Unknown field type.";
207 return "";
208 }
209}
210
211bool FieldGeneratorBase::has_default_value() {
212 switch (descriptor_->type()) {
213 case FieldDescriptor::TYPE_ENUM:
214 case FieldDescriptor::TYPE_MESSAGE:
215 case FieldDescriptor::TYPE_GROUP:
216 return true;
217 case FieldDescriptor::TYPE_DOUBLE:
218 return descriptor_->default_value_double() != 0.0;
219 case FieldDescriptor::TYPE_FLOAT:
220 return descriptor_->default_value_float() != 0.0;
221 case FieldDescriptor::TYPE_INT64:
222 return descriptor_->default_value_int64() != 0L;
223 case FieldDescriptor::TYPE_UINT64:
224 return descriptor_->default_value_uint64() != 0L;
225 case FieldDescriptor::TYPE_INT32:
226 return descriptor_->default_value_int32() != 0;
227 case FieldDescriptor::TYPE_FIXED64:
228 return descriptor_->default_value_uint64() != 0L;
229 case FieldDescriptor::TYPE_FIXED32:
230 return descriptor_->default_value_uint32() != 0;
231 case FieldDescriptor::TYPE_BOOL:
232 return descriptor_->default_value_bool();
233 case FieldDescriptor::TYPE_STRING:
234 return true;
235 case FieldDescriptor::TYPE_BYTES:
236 return true;
237 case FieldDescriptor::TYPE_UINT32:
238 return descriptor_->default_value_uint32() != 0;
239 case FieldDescriptor::TYPE_SFIXED32:
240 return descriptor_->default_value_int32() != 0;
241 case FieldDescriptor::TYPE_SFIXED64:
242 return descriptor_->default_value_int64() != 0L;
243 case FieldDescriptor::TYPE_SINT32:
244 return descriptor_->default_value_int32() != 0;
245 case FieldDescriptor::TYPE_SINT64:
246 return descriptor_->default_value_int64() != 0L;
247 default:
248 GOOGLE_LOG(FATAL)<< "Unknown field type.";
249 return true;
250 }
251}
252
253bool FieldGeneratorBase::is_nullable_type() {
254 switch (descriptor_->type()) {
255 case FieldDescriptor::TYPE_ENUM:
256 case FieldDescriptor::TYPE_DOUBLE:
257 case FieldDescriptor::TYPE_FLOAT:
258 case FieldDescriptor::TYPE_INT64:
259 case FieldDescriptor::TYPE_UINT64:
260 case FieldDescriptor::TYPE_INT32:
261 case FieldDescriptor::TYPE_FIXED64:
262 case FieldDescriptor::TYPE_FIXED32:
263 case FieldDescriptor::TYPE_BOOL:
264 case FieldDescriptor::TYPE_UINT32:
265 case FieldDescriptor::TYPE_SFIXED32:
266 case FieldDescriptor::TYPE_SFIXED64:
267 case FieldDescriptor::TYPE_SINT32:
268 case FieldDescriptor::TYPE_SINT64:
269 return false;
270
271 case FieldDescriptor::TYPE_MESSAGE:
272 case FieldDescriptor::TYPE_GROUP:
273 case FieldDescriptor::TYPE_STRING:
274 case FieldDescriptor::TYPE_BYTES:
275 return true;
276
277 default:
278 GOOGLE_LOG(FATAL)<< "Unknown field type.";
279 return true;
280 }
281}
282
Jan Tattermusch685ae362015-03-16 19:07:16 -0700283bool AllPrintableAscii(const std::string& text) {
284 for(int i = 0; i < text.size(); i++) {
285 if (text[i] < 0x20 || text[i] > 0x7e) {
286 return false;
287 }
288 }
289 return true;
290}
291
292std::string FieldGeneratorBase::GetStringDefaultValueInternal() {
Jon Skeetf5242682015-06-05 20:44:05 +0100293 // No other default values needed for proto3...
294 return "\"\"";
Jan Tattermusch685ae362015-03-16 19:07:16 -0700295}
296
297std::string FieldGeneratorBase::GetBytesDefaultValueInternal() {
Jon Skeetf5242682015-06-05 20:44:05 +0100298 // No other default values needed for proto3...
299 return "pb::ByteString.Empty";
Jan Tattermusch685ae362015-03-16 19:07:16 -0700300}
301
302std::string FieldGeneratorBase::default_value() {
Jon Skeet8a0312b2015-07-16 17:03:06 +0100303 return default_value(descriptor_);
304}
305
306std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
307 switch (descriptor->type()) {
Jan Tattermusch685ae362015-03-16 19:07:16 -0700308 case FieldDescriptor::TYPE_ENUM:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100309 return type_name() + "." + descriptor->default_value_enum()->name();
Jan Tattermusch685ae362015-03-16 19:07:16 -0700310 case FieldDescriptor::TYPE_MESSAGE:
311 case FieldDescriptor::TYPE_GROUP:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100312 if (IsWrapperType(descriptor)) {
313 const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
314 return default_value(wrapped_field);
315 } else {
316 return "null";
317 }
Jan Tattermusch685ae362015-03-16 19:07:16 -0700318 case FieldDescriptor::TYPE_DOUBLE: {
Jon Skeet8a0312b2015-07-16 17:03:06 +0100319 double value = descriptor->default_value_double();
Jan Tattermusch685ae362015-03-16 19:07:16 -0700320 if (value == numeric_limits<double>::infinity()) {
321 return "double.PositiveInfinity";
322 } else if (value == -numeric_limits<double>::infinity()) {
323 return "double.NegativeInfinity";
Karol Ostrovskyee354022015-06-29 16:13:33 +0200324 } else if (MathLimits<double>::IsNaN(value)) {
Jan Tattermusch685ae362015-03-16 19:07:16 -0700325 return "double.NaN";
326 }
327 return SimpleDtoa(value) + "D";
328 }
329 case FieldDescriptor::TYPE_FLOAT: {
Jon Skeet8a0312b2015-07-16 17:03:06 +0100330 float value = descriptor->default_value_float();
Jan Tattermusch685ae362015-03-16 19:07:16 -0700331 if (value == numeric_limits<float>::infinity()) {
332 return "float.PositiveInfinity";
333 } else if (value == -numeric_limits<float>::infinity()) {
334 return "float.NegativeInfinity";
Karol Ostrovskyee354022015-06-29 16:13:33 +0200335 } else if (MathLimits<float>::IsNaN(value)) {
Jan Tattermusch685ae362015-03-16 19:07:16 -0700336 return "float.NaN";
337 }
338 return SimpleFtoa(value) + "F";
339 }
340 case FieldDescriptor::TYPE_INT64:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100341 return SimpleItoa(descriptor->default_value_int64()) + "L";
Jan Tattermusch685ae362015-03-16 19:07:16 -0700342 case FieldDescriptor::TYPE_UINT64:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100343 return SimpleItoa(descriptor->default_value_uint64()) + "UL";
Jan Tattermusch685ae362015-03-16 19:07:16 -0700344 case FieldDescriptor::TYPE_INT32:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100345 return SimpleItoa(descriptor->default_value_int32());
Jan Tattermusch685ae362015-03-16 19:07:16 -0700346 case FieldDescriptor::TYPE_FIXED64:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100347 return SimpleItoa(descriptor->default_value_uint64()) + "UL";
Jan Tattermusch685ae362015-03-16 19:07:16 -0700348 case FieldDescriptor::TYPE_FIXED32:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100349 return SimpleItoa(descriptor->default_value_uint32());
Jan Tattermusch685ae362015-03-16 19:07:16 -0700350 case FieldDescriptor::TYPE_BOOL:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100351 if (descriptor->default_value_bool()) {
Jan Tattermusch685ae362015-03-16 19:07:16 -0700352 return "true";
353 } else {
354 return "false";
355 }
356 case FieldDescriptor::TYPE_STRING:
357 return GetStringDefaultValueInternal();
358 case FieldDescriptor::TYPE_BYTES:
359 return GetBytesDefaultValueInternal();
360 case FieldDescriptor::TYPE_UINT32:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100361 return SimpleItoa(descriptor->default_value_uint32());
Jan Tattermusch685ae362015-03-16 19:07:16 -0700362 case FieldDescriptor::TYPE_SFIXED32:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100363 return SimpleItoa(descriptor->default_value_int32());
Jan Tattermusch685ae362015-03-16 19:07:16 -0700364 case FieldDescriptor::TYPE_SFIXED64:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100365 return SimpleItoa(descriptor->default_value_int64()) + "L";
Jan Tattermusch685ae362015-03-16 19:07:16 -0700366 case FieldDescriptor::TYPE_SINT32:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100367 return SimpleItoa(descriptor->default_value_int32());
Jan Tattermusch685ae362015-03-16 19:07:16 -0700368 case FieldDescriptor::TYPE_SINT64:
Jon Skeet8a0312b2015-07-16 17:03:06 +0100369 return SimpleItoa(descriptor->default_value_int64()) + "L";
Jan Tattermusch685ae362015-03-16 19:07:16 -0700370 default:
371 GOOGLE_LOG(FATAL)<< "Unknown field type.";
372 return "";
373 }
374}
375
376std::string FieldGeneratorBase::number() {
377 return SimpleItoa(descriptor_->number());
378}
379
Jan Tattermusch685ae362015-03-16 19:07:16 -0700380std::string FieldGeneratorBase::capitalized_type_name() {
381 switch (descriptor_->type()) {
382 case FieldDescriptor::TYPE_ENUM:
383 return "Enum";
384 case FieldDescriptor::TYPE_MESSAGE:
385 return "Message";
386 case FieldDescriptor::TYPE_GROUP:
387 return "Group";
388 case FieldDescriptor::TYPE_DOUBLE:
389 return "Double";
390 case FieldDescriptor::TYPE_FLOAT:
391 return "Float";
392 case FieldDescriptor::TYPE_INT64:
393 return "Int64";
394 case FieldDescriptor::TYPE_UINT64:
395 return "UInt64";
396 case FieldDescriptor::TYPE_INT32:
397 return "Int32";
398 case FieldDescriptor::TYPE_FIXED64:
399 return "Fixed64";
400 case FieldDescriptor::TYPE_FIXED32:
401 return "Fixed32";
402 case FieldDescriptor::TYPE_BOOL:
403 return "Bool";
404 case FieldDescriptor::TYPE_STRING:
405 return "String";
406 case FieldDescriptor::TYPE_BYTES:
407 return "Bytes";
408 case FieldDescriptor::TYPE_UINT32:
409 return "UInt32";
410 case FieldDescriptor::TYPE_SFIXED32:
411 return "SFixed32";
412 case FieldDescriptor::TYPE_SFIXED64:
413 return "SFixed64";
414 case FieldDescriptor::TYPE_SINT32:
415 return "SInt32";
416 case FieldDescriptor::TYPE_SINT64:
417 return "SInt64";
418 default:
419 GOOGLE_LOG(FATAL)<< "Unknown field type.";
420 return "";
421 }
422}
423
Jan Tattermusch685ae362015-03-16 19:07:16 -0700424} // namespace csharp
425} // namespace compiler
426} // namespace protobuf
427} // namespace google