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 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34
35 #include <map>
36 #include <string>
37
38 #include <google/protobuf/stubs/logging.h>
39 #include <google/protobuf/stubs/common.h>
40 #include <google/protobuf/compiler/java/java_context.h>
41 #include <google/protobuf/compiler/java/java_doc_comment.h>
42 #include <google/protobuf/compiler/java/java_enum_field.h>
43 #include <google/protobuf/compiler/java/java_helpers.h>
44 #include <google/protobuf/compiler/java/java_name_resolver.h>
45 #include <google/protobuf/io/printer.h>
46 #include <google/protobuf/wire_format.h>
47 #include <google/protobuf/stubs/strutil.h>
48
49 namespace google {
50 namespace protobuf {
51 namespace compiler {
52 namespace java {
53
54 namespace {
55
SetEnumVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,map<string,string> * variables)56 void SetEnumVariables(const FieldDescriptor* descriptor,
57 int messageBitIndex,
58 int builderBitIndex,
59 const FieldGeneratorInfo* info,
60 ClassNameResolver* name_resolver,
61 map<string, string>* variables) {
62 SetCommonFieldVariables(descriptor, info, variables);
63
64 (*variables)["type"] =
65 name_resolver->GetImmutableClassName(descriptor->enum_type());
66 (*variables)["mutable_type"] =
67 name_resolver->GetMutableClassName(descriptor->enum_type());
68 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
69 (*variables)["default_number"] = SimpleItoa(
70 descriptor->default_value_enum()->number());
71 (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
72 (*variables)["tag_size"] = SimpleItoa(
73 internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
74 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
75 // by the proto compiler
76 (*variables)["deprecation"] = descriptor->options().deprecated()
77 ? "@java.lang.Deprecated " : "";
78 (*variables)["on_changed"] = "onChanged();";
79
80 if (SupportFieldPresence(descriptor->file())) {
81 // For singular messages and builders, one bit is used for the hasField bit.
82 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
83 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
84
85 // Note that these have a trailing ";".
86 (*variables)["set_has_field_bit_message"] =
87 GenerateSetBit(messageBitIndex) + ";";
88 (*variables)["set_has_field_bit_builder"] =
89 GenerateSetBit(builderBitIndex) + ";";
90 (*variables)["clear_has_field_bit_builder"] =
91 GenerateClearBit(builderBitIndex) + ";";
92
93 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
94 } else {
95 (*variables)["set_has_field_bit_message"] = "";
96 (*variables)["set_has_field_bit_builder"] = "";
97 (*variables)["clear_has_field_bit_builder"] = "";
98
99 (*variables)["is_field_present_message"] =
100 (*variables)["name"] + "_ != " +
101 (*variables)["default"] + ".getNumber()";
102 }
103
104 // For repated builders, one bit is used for whether the array is immutable.
105 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
106 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
107 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
108
109 // For repeated fields, one bit is used for whether the array is immutable
110 // in the parsing constructor.
111 (*variables)["get_mutable_bit_parser"] =
112 GenerateGetBitMutableLocal(builderBitIndex);
113 (*variables)["set_mutable_bit_parser"] =
114 GenerateSetBitMutableLocal(builderBitIndex);
115
116 (*variables)["get_has_field_bit_from_local"] =
117 GenerateGetBitFromLocal(builderBitIndex);
118 (*variables)["set_has_field_bit_to_local"] =
119 GenerateSetBitToLocal(messageBitIndex);
120
121 if (SupportUnknownEnumValue(descriptor->file())) {
122 (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
123 } else {
124 (*variables)["unknown"] = (*variables)["default"];
125 }
126 }
127
128 } // namespace
129
130 // ===================================================================
131
132 ImmutableEnumFieldGenerator::
ImmutableEnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)133 ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor,
134 int messageBitIndex,
135 int builderBitIndex,
136 Context* context)
137 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
138 builderBitIndex_(builderBitIndex),
139 name_resolver_(context->GetNameResolver()) {
140 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
141 context->GetFieldGeneratorInfo(descriptor),
142 name_resolver_, &variables_);
143 }
144
~ImmutableEnumFieldGenerator()145 ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {}
146
GetNumBitsForMessage() const147 int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
148 return 1;
149 }
150
GetNumBitsForBuilder() const151 int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
152 return 1;
153 }
154
155 void ImmutableEnumFieldGenerator::
GenerateInterfaceMembers(io::Printer * printer) const156 GenerateInterfaceMembers(io::Printer* printer) const {
157 if (SupportFieldPresence(descriptor_->file())) {
158 WriteFieldDocComment(printer, descriptor_);
159 printer->Print(variables_,
160 "$deprecation$boolean has$capitalized_name$();\n");
161 }
162 if (SupportUnknownEnumValue(descriptor_->file())) {
163 WriteFieldDocComment(printer, descriptor_);
164 printer->Print(variables_,
165 "$deprecation$int get$capitalized_name$Value();\n");
166 }
167 WriteFieldDocComment(printer, descriptor_);
168 printer->Print(variables_,
169 "$deprecation$$type$ get$capitalized_name$();\n");
170 }
171
172 void ImmutableEnumFieldGenerator::
GenerateMembers(io::Printer * printer) const173 GenerateMembers(io::Printer* printer) const {
174 printer->Print(variables_,
175 "private int $name$_;\n");
176 PrintExtraFieldInfo(variables_, printer);
177 if (SupportFieldPresence(descriptor_->file())) {
178 WriteFieldDocComment(printer, descriptor_);
179 printer->Print(variables_,
180 "$deprecation$public boolean has$capitalized_name$() {\n"
181 " return $get_has_field_bit_message$;\n"
182 "}\n");
183 }
184 if (SupportUnknownEnumValue(descriptor_->file())) {
185 WriteFieldDocComment(printer, descriptor_);
186 printer->Print(variables_,
187 "$deprecation$public int get$capitalized_name$Value() {\n"
188 " return $name$_;\n"
189 "}\n");
190 }
191 WriteFieldDocComment(printer, descriptor_);
192 printer->Print(variables_,
193 "$deprecation$public $type$ get$capitalized_name$() {\n"
194 " $type$ result = $type$.forNumber($name$_);\n"
195 " return result == null ? $unknown$ : result;\n"
196 "}\n");
197 }
198
199 void ImmutableEnumFieldGenerator::
GenerateBuilderMembers(io::Printer * printer) const200 GenerateBuilderMembers(io::Printer* printer) const {
201 printer->Print(variables_,
202 "private int $name$_ = $default_number$;\n");
203 if (SupportFieldPresence(descriptor_->file())) {
204 WriteFieldDocComment(printer, descriptor_);
205 printer->Print(variables_,
206 "$deprecation$public boolean has$capitalized_name$() {\n"
207 " return $get_has_field_bit_builder$;\n"
208 "}\n");
209 }
210 if (SupportUnknownEnumValue(descriptor_->file())) {
211 WriteFieldDocComment(printer, descriptor_);
212 printer->Print(variables_,
213 "$deprecation$public int get$capitalized_name$Value() {\n"
214 " return $name$_;\n"
215 "}\n");
216 WriteFieldDocComment(printer, descriptor_);
217 printer->Print(variables_,
218 "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
219 " $name$_ = value;\n"
220 " $on_changed$\n"
221 " return this;\n"
222 "}\n");
223 }
224 WriteFieldDocComment(printer, descriptor_);
225 printer->Print(variables_,
226 "$deprecation$public $type$ get$capitalized_name$() {\n"
227 " $type$ result = $type$.forNumber($name$_);\n"
228 " return result == null ? $unknown$ : result;\n"
229 "}\n");
230 WriteFieldDocComment(printer, descriptor_);
231 printer->Print(variables_,
232 "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
233 " if (value == null) {\n"
234 " throw new NullPointerException();\n"
235 " }\n"
236 " $set_has_field_bit_builder$\n"
237 " $name$_ = value.getNumber();\n"
238 " $on_changed$\n"
239 " return this;\n"
240 "}\n");
241 WriteFieldDocComment(printer, descriptor_);
242 printer->Print(variables_,
243 "$deprecation$public Builder clear$capitalized_name$() {\n"
244 " $clear_has_field_bit_builder$\n"
245 " $name$_ = $default_number$;\n"
246 " $on_changed$\n"
247 " return this;\n"
248 "}\n");
249 }
250
251 void ImmutableEnumFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const252 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
253 // noop for enums
254 }
255
256 void ImmutableEnumFieldGenerator::
GenerateInitializationCode(io::Printer * printer) const257 GenerateInitializationCode(io::Printer* printer) const {
258 printer->Print(variables_, "$name$_ = $default_number$;\n");
259 }
260
261 void ImmutableEnumFieldGenerator::
GenerateBuilderClearCode(io::Printer * printer) const262 GenerateBuilderClearCode(io::Printer* printer) const {
263 printer->Print(variables_,
264 "$name$_ = $default_number$;\n"
265 "$clear_has_field_bit_builder$\n");
266 }
267
268 void ImmutableEnumFieldGenerator::
GenerateMergingCode(io::Printer * printer) const269 GenerateMergingCode(io::Printer* printer) const {
270 if (SupportFieldPresence(descriptor_->file())) {
271 printer->Print(variables_,
272 "if (other.has$capitalized_name$()) {\n"
273 " set$capitalized_name$(other.get$capitalized_name$());\n"
274 "}\n");
275 } else if (SupportUnknownEnumValue(descriptor_->file())) {
276 printer->Print(variables_,
277 "if (other.$name$_ != $default_number$) {\n"
278 " set$capitalized_name$Value(other.get$capitalized_name$Value());\n"
279 "}\n");
280 } else {
281 GOOGLE_LOG(FATAL) << "Can't reach here.";
282 }
283 }
284
285 void ImmutableEnumFieldGenerator::
GenerateBuildingCode(io::Printer * printer) const286 GenerateBuildingCode(io::Printer* printer) const {
287 if (SupportFieldPresence(descriptor_->file())) {
288 printer->Print(variables_,
289 "if ($get_has_field_bit_from_local$) {\n"
290 " $set_has_field_bit_to_local$;\n"
291 "}\n");
292 }
293 printer->Print(variables_,
294 "result.$name$_ = $name$_;\n");
295 }
296
297 void ImmutableEnumFieldGenerator::
GenerateParsingCode(io::Printer * printer) const298 GenerateParsingCode(io::Printer* printer) const {
299 if (SupportUnknownEnumValue(descriptor_->file())) {
300 printer->Print(variables_,
301 "int rawValue = input.readEnum();\n"
302 "$set_has_field_bit_message$\n"
303 "$name$_ = rawValue;\n");
304 } else {
305 printer->Print(variables_,
306 "int rawValue = input.readEnum();\n"
307 "$type$ value = $type$.forNumber(rawValue);\n"
308 "if (value == null) {\n");
309 if (PreserveUnknownFields(descriptor_->containing_type())) {
310 printer->Print(variables_,
311 " unknownFields.mergeVarintField($number$, rawValue);\n");
312 }
313 printer->Print(variables_,
314 "} else {\n"
315 " $set_has_field_bit_message$\n"
316 " $name$_ = rawValue;\n"
317 "}\n");
318 }
319 }
320
321 void ImmutableEnumFieldGenerator::
GenerateParsingDoneCode(io::Printer * printer) const322 GenerateParsingDoneCode(io::Printer* printer) const {
323 // noop for enums
324 }
325
326 void ImmutableEnumFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const327 GenerateSerializationCode(io::Printer* printer) const {
328 printer->Print(variables_,
329 "if ($is_field_present_message$) {\n"
330 " output.writeEnum($number$, $name$_);\n"
331 "}\n");
332 }
333
334 void ImmutableEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const335 GenerateSerializedSizeCode(io::Printer* printer) const {
336 printer->Print(variables_,
337 "if ($is_field_present_message$) {\n"
338 " size += com.google.protobuf.CodedOutputStream\n"
339 " .computeEnumSize($number$, $name$_);\n"
340 "}\n");
341 }
342
343 void ImmutableEnumFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const344 GenerateEqualsCode(io::Printer* printer) const {
345 printer->Print(variables_,
346 "result = result && $name$_ == other.$name$_;\n");
347 }
348
349 void ImmutableEnumFieldGenerator::
GenerateHashCode(io::Printer * printer) const350 GenerateHashCode(io::Printer* printer) const {
351 printer->Print(variables_,
352 "hash = (37 * hash) + $constant_name$;\n"
353 "hash = (53 * hash) + $name$_;\n");
354 }
355
GetBoxedType() const356 string ImmutableEnumFieldGenerator::GetBoxedType() const {
357 return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
358 }
359
360 // ===================================================================
361
362 ImmutableEnumOneofFieldGenerator::
ImmutableEnumOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)363 ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor,
364 int messageBitIndex,
365 int builderBitIndex,
366 Context* context)
367 : ImmutableEnumFieldGenerator(
368 descriptor, messageBitIndex, builderBitIndex, context) {
369 const OneofGeneratorInfo* info =
370 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
371 SetCommonOneofVariables(descriptor, info, &variables_);
372 }
373
374 ImmutableEnumOneofFieldGenerator::
~ImmutableEnumOneofFieldGenerator()375 ~ImmutableEnumOneofFieldGenerator() {}
376
377 void ImmutableEnumOneofFieldGenerator::
GenerateMembers(io::Printer * printer) const378 GenerateMembers(io::Printer* printer) const {
379 PrintExtraFieldInfo(variables_, printer);
380 if (SupportFieldPresence(descriptor_->file())) {
381 WriteFieldDocComment(printer, descriptor_);
382 printer->Print(variables_,
383 "$deprecation$public boolean has$capitalized_name$() {\n"
384 " return $has_oneof_case_message$;\n"
385 "}\n");
386 }
387 if (SupportUnknownEnumValue(descriptor_->file())) {
388 WriteFieldDocComment(printer, descriptor_);
389 printer->Print(variables_,
390 "$deprecation$public int get$capitalized_name$Value() {\n"
391 " if ($has_oneof_case_message$) {\n"
392 " return (java.lang.Integer) $oneof_name$_;\n"
393 " }\n"
394 " return $default_number$;\n"
395 "}\n");
396 }
397 WriteFieldDocComment(printer, descriptor_);
398 printer->Print(variables_,
399 "$deprecation$public $type$ get$capitalized_name$() {\n"
400 " if ($has_oneof_case_message$) {\n"
401 " $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
402 " return result == null ? $unknown$ : result;\n"
403 " }\n"
404 " return $default$;\n"
405 "}\n");
406 }
407
408 void ImmutableEnumOneofFieldGenerator::
GenerateBuilderMembers(io::Printer * printer) const409 GenerateBuilderMembers(io::Printer* printer) const {
410 if (SupportFieldPresence(descriptor_->file())) {
411 WriteFieldDocComment(printer, descriptor_);
412 printer->Print(variables_,
413 "$deprecation$public boolean has$capitalized_name$() {\n"
414 " return $has_oneof_case_message$;\n"
415 "}\n");
416 }
417 if (SupportUnknownEnumValue(descriptor_->file())) {
418 WriteFieldDocComment(printer, descriptor_);
419 printer->Print(variables_,
420 "$deprecation$public int get$capitalized_name$Value() {\n"
421 " if ($has_oneof_case_message$) {\n"
422 " return ((java.lang.Integer) $oneof_name$_).intValue();\n"
423 " }\n"
424 " return $default_number$;\n"
425 "}\n");
426 WriteFieldDocComment(printer, descriptor_);
427 printer->Print(variables_,
428 "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
429 " $set_oneof_case_message$;\n"
430 " $oneof_name$_ = value;\n"
431 " $on_changed$\n"
432 " return this;\n"
433 "}\n");
434 }
435 WriteFieldDocComment(printer, descriptor_);
436 printer->Print(variables_,
437 "$deprecation$public $type$ get$capitalized_name$() {\n"
438 " if ($has_oneof_case_message$) {\n"
439 " $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
440 " return result == null ? $unknown$ : result;\n"
441 " }\n"
442 " return $default$;\n"
443 "}\n");
444 WriteFieldDocComment(printer, descriptor_);
445 printer->Print(variables_,
446 "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
447 " if (value == null) {\n"
448 " throw new NullPointerException();\n"
449 " }\n"
450 " $set_oneof_case_message$;\n"
451 " $oneof_name$_ = value.getNumber();\n"
452 " $on_changed$\n"
453 " return this;\n"
454 "}\n");
455 WriteFieldDocComment(printer, descriptor_);
456 printer->Print(variables_,
457 "$deprecation$public Builder clear$capitalized_name$() {\n"
458 " if ($has_oneof_case_message$) {\n"
459 " $clear_oneof_case_message$;\n"
460 " $oneof_name$_ = null;\n"
461 " $on_changed$\n"
462 " }\n"
463 " return this;\n"
464 "}\n");
465 }
466
467 void ImmutableEnumOneofFieldGenerator::
GenerateBuildingCode(io::Printer * printer) const468 GenerateBuildingCode(io::Printer* printer) const {
469 printer->Print(variables_,
470 "if ($has_oneof_case_message$) {\n"
471 " result.$oneof_name$_ = $oneof_name$_;\n"
472 "}\n");
473 }
474
475 void ImmutableEnumOneofFieldGenerator::
GenerateMergingCode(io::Printer * printer) const476 GenerateMergingCode(io::Printer* printer) const {
477 if (SupportUnknownEnumValue(descriptor_->file())) {
478 printer->Print(variables_,
479 "set$capitalized_name$Value(other.get$capitalized_name$Value());\n");
480 } else {
481 printer->Print(variables_,
482 "set$capitalized_name$(other.get$capitalized_name$());\n");
483 }
484 }
485
486 void ImmutableEnumOneofFieldGenerator::
GenerateParsingCode(io::Printer * printer) const487 GenerateParsingCode(io::Printer* printer) const {
488 if (SupportUnknownEnumValue(descriptor_->file())) {
489 printer->Print(variables_,
490 "int rawValue = input.readEnum();\n"
491 "$set_oneof_case_message$;\n"
492 "$oneof_name$_ = rawValue;\n");
493 } else {
494 printer->Print(variables_,
495 "int rawValue = input.readEnum();\n"
496 "$type$ value = $type$.forNumber(rawValue);\n"
497 "if (value == null) {\n");
498 if (PreserveUnknownFields(descriptor_->containing_type())) {
499 printer->Print(variables_,
500 " unknownFields.mergeVarintField($number$, rawValue);\n");
501 }
502 printer->Print(variables_,
503 "} else {\n"
504 " $set_oneof_case_message$;\n"
505 " $oneof_name$_ = rawValue;\n"
506 "}\n");
507 }
508 }
509
510 void ImmutableEnumOneofFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const511 GenerateSerializationCode(io::Printer* printer) const {
512 printer->Print(variables_,
513 "if ($has_oneof_case_message$) {\n"
514 " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
515 "}\n");
516 }
517
518 void ImmutableEnumOneofFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const519 GenerateSerializedSizeCode(io::Printer* printer) const {
520 printer->Print(variables_,
521 "if ($has_oneof_case_message$) {\n"
522 " size += com.google.protobuf.CodedOutputStream\n"
523 " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
524 "}\n");
525 }
526
527 void ImmutableEnumOneofFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const528 GenerateEqualsCode(io::Printer* printer) const {
529 if (SupportUnknownEnumValue(descriptor_->file())) {
530 printer->Print(variables_,
531 "result = result && get$capitalized_name$Value()\n"
532 " == other.get$capitalized_name$Value();\n");
533 } else {
534 printer->Print(variables_,
535 "result = result && get$capitalized_name$()\n"
536 " .equals(other.get$capitalized_name$());\n");
537 }
538 }
539
540 void ImmutableEnumOneofFieldGenerator::
GenerateHashCode(io::Printer * printer) const541 GenerateHashCode(io::Printer* printer) const {
542 if (SupportUnknownEnumValue(descriptor_->file())) {
543 printer->Print(variables_,
544 "hash = (37 * hash) + $constant_name$;\n"
545 "hash = (53 * hash) + get$capitalized_name$Value();\n");
546 } else {
547 printer->Print(variables_,
548 "hash = (37 * hash) + $constant_name$;\n"
549 "hash = (53 * hash) + get$capitalized_name$().getNumber();\n");
550 }
551 }
552
553 // ===================================================================
554
555 RepeatedImmutableEnumFieldGenerator::
RepeatedImmutableEnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)556 RepeatedImmutableEnumFieldGenerator(const FieldDescriptor* descriptor,
557 int messageBitIndex,
558 int builderBitIndex,
559 Context* context)
560 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
561 builderBitIndex_(builderBitIndex), context_(context),
562 name_resolver_(context->GetNameResolver()) {
563 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
564 context->GetFieldGeneratorInfo(descriptor),
565 name_resolver_, &variables_);
566 }
567
~RepeatedImmutableEnumFieldGenerator()568 RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {}
569
GetNumBitsForMessage() const570 int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
571 return 0;
572 }
573
GetNumBitsForBuilder() const574 int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
575 return 1;
576 }
577
578 void RepeatedImmutableEnumFieldGenerator::
GenerateInterfaceMembers(io::Printer * printer) const579 GenerateInterfaceMembers(io::Printer* printer) const {
580 WriteFieldDocComment(printer, descriptor_);
581 printer->Print(variables_,
582 "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
583 WriteFieldDocComment(printer, descriptor_);
584 printer->Print(variables_,
585 "$deprecation$int get$capitalized_name$Count();\n");
586 WriteFieldDocComment(printer, descriptor_);
587 printer->Print(variables_,
588 "$deprecation$$type$ get$capitalized_name$(int index);\n");
589 if (SupportUnknownEnumValue(descriptor_->file())) {
590 WriteFieldDocComment(printer, descriptor_);
591 printer->Print(variables_,
592 "$deprecation$java.util.List<java.lang.Integer>\n"
593 "get$capitalized_name$ValueList();\n");
594 WriteFieldDocComment(printer, descriptor_);
595 printer->Print(variables_,
596 "$deprecation$int get$capitalized_name$Value(int index);\n");
597 }
598 }
599
600 void RepeatedImmutableEnumFieldGenerator::
GenerateMembers(io::Printer * printer) const601 GenerateMembers(io::Printer* printer) const {
602 printer->Print(variables_,
603 "private java.util.List<java.lang.Integer> $name$_;\n"
604 "private static final com.google.protobuf.Internal.ListAdapter.Converter<\n"
605 " java.lang.Integer, $type$> $name$_converter_ =\n"
606 " new com.google.protobuf.Internal.ListAdapter.Converter<\n"
607 " java.lang.Integer, $type$>() {\n"
608 " public $type$ convert(java.lang.Integer from) {\n"
609 " $type$ result = $type$.forNumber(from);\n"
610 " return result == null ? $unknown$ : result;\n"
611 " }\n"
612 " };\n");
613 PrintExtraFieldInfo(variables_, printer);
614 WriteFieldDocComment(printer, descriptor_);
615 printer->Print(variables_,
616 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
617 " return new com.google.protobuf.Internal.ListAdapter<\n"
618 " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
619 "}\n");
620 WriteFieldDocComment(printer, descriptor_);
621 printer->Print(variables_,
622 "$deprecation$public int get$capitalized_name$Count() {\n"
623 " return $name$_.size();\n"
624 "}\n");
625 WriteFieldDocComment(printer, descriptor_);
626 printer->Print(variables_,
627 "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
628 " return $name$_converter_.convert($name$_.get(index));\n"
629 "}\n");
630 if (SupportUnknownEnumValue(descriptor_->file())) {
631 WriteFieldDocComment(printer, descriptor_);
632 printer->Print(variables_,
633 "$deprecation$public java.util.List<java.lang.Integer>\n"
634 "get$capitalized_name$ValueList() {\n"
635 " return $name$_;\n"
636 "}\n");
637 WriteFieldDocComment(printer, descriptor_);
638 printer->Print(variables_,
639 "$deprecation$public int get$capitalized_name$Value(int index) {\n"
640 " return $name$_.get(index);\n"
641 "}\n");
642 }
643
644 if (descriptor_->is_packed() &&
645 context_->HasGeneratedMethods(descriptor_->containing_type())) {
646 printer->Print(variables_,
647 "private int $name$MemoizedSerializedSize;\n");
648 }
649 }
650
651 void RepeatedImmutableEnumFieldGenerator::
GenerateBuilderMembers(io::Printer * printer) const652 GenerateBuilderMembers(io::Printer* printer) const {
653 printer->Print(variables_,
654 // One field is the list and the other field keeps track of whether the
655 // list is immutable. If it's immutable, the invariant is that it must
656 // either an instance of Collections.emptyList() or it's an ArrayList
657 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
658 // a refererence to the underlying ArrayList. This invariant allows us to
659 // share instances of lists between protocol buffers avoiding expensive
660 // memory allocations. Note, immutable is a strong guarantee here -- not
661 // just that the list cannot be modified via the reference but that the
662 // list can never be modified.
663 "private java.util.List<java.lang.Integer> $name$_ =\n"
664 " java.util.Collections.emptyList();\n"
665
666 "private void ensure$capitalized_name$IsMutable() {\n"
667 " if (!$get_mutable_bit_builder$) {\n"
668 " $name$_ = new java.util.ArrayList<java.lang.Integer>($name$_);\n"
669 " $set_mutable_bit_builder$;\n"
670 " }\n"
671 "}\n");
672
673 WriteFieldDocComment(printer, descriptor_);
674 printer->Print(variables_,
675 // Note: We return an unmodifiable list because otherwise the caller
676 // could hold on to the returned list and modify it after the message
677 // has been built, thus mutating the message which is supposed to be
678 // immutable.
679 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
680 " return new com.google.protobuf.Internal.ListAdapter<\n"
681 " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
682 "}\n");
683 WriteFieldDocComment(printer, descriptor_);
684 printer->Print(variables_,
685 "$deprecation$public int get$capitalized_name$Count() {\n"
686 " return $name$_.size();\n"
687 "}\n");
688 WriteFieldDocComment(printer, descriptor_);
689 printer->Print(variables_,
690 "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
691 " return $name$_converter_.convert($name$_.get(index));\n"
692 "}\n");
693 WriteFieldDocComment(printer, descriptor_);
694 printer->Print(variables_,
695 "$deprecation$public Builder set$capitalized_name$(\n"
696 " int index, $type$ value) {\n"
697 " if (value == null) {\n"
698 " throw new NullPointerException();\n"
699 " }\n"
700 " ensure$capitalized_name$IsMutable();\n"
701 " $name$_.set(index, value.getNumber());\n"
702 " $on_changed$\n"
703 " return this;\n"
704 "}\n");
705 WriteFieldDocComment(printer, descriptor_);
706 printer->Print(variables_,
707 "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
708 " if (value == null) {\n"
709 " throw new NullPointerException();\n"
710 " }\n"
711 " ensure$capitalized_name$IsMutable();\n"
712 " $name$_.add(value.getNumber());\n"
713 " $on_changed$\n"
714 " return this;\n"
715 "}\n");
716 WriteFieldDocComment(printer, descriptor_);
717 printer->Print(variables_,
718 "$deprecation$public Builder addAll$capitalized_name$(\n"
719 " java.lang.Iterable<? extends $type$> values) {\n"
720 " ensure$capitalized_name$IsMutable();\n"
721 " for ($type$ value : values) {\n"
722 " $name$_.add(value.getNumber());\n"
723 " }\n"
724 " $on_changed$\n"
725 " return this;\n"
726 "}\n");
727 WriteFieldDocComment(printer, descriptor_);
728 printer->Print(variables_,
729 "$deprecation$public Builder clear$capitalized_name$() {\n"
730 " $name$_ = java.util.Collections.emptyList();\n"
731 " $clear_mutable_bit_builder$;\n"
732 " $on_changed$\n"
733 " return this;\n"
734 "}\n");
735
736 if (SupportUnknownEnumValue(descriptor_->file())) {
737 WriteFieldDocComment(printer, descriptor_);
738 printer->Print(variables_,
739 "$deprecation$public java.util.List<java.lang.Integer>\n"
740 "get$capitalized_name$ValueList() {\n"
741 " return java.util.Collections.unmodifiableList($name$_);\n"
742 "}\n");
743 WriteFieldDocComment(printer, descriptor_);
744 printer->Print(variables_,
745 "$deprecation$public int get$capitalized_name$Value(int index) {\n"
746 " return $name$_.get(index);\n"
747 "}\n");
748 WriteFieldDocComment(printer, descriptor_);
749 printer->Print(variables_,
750 "$deprecation$public Builder set$capitalized_name$Value(\n"
751 " int index, int value) {\n"
752 " ensure$capitalized_name$IsMutable();\n"
753 " $name$_.set(index, value);\n"
754 " $on_changed$\n"
755 " return this;\n"
756 "}\n");
757 WriteFieldDocComment(printer, descriptor_);
758 printer->Print(variables_,
759 "$deprecation$public Builder add$capitalized_name$Value(int value) {\n"
760 " ensure$capitalized_name$IsMutable();\n"
761 " $name$_.add(value);\n"
762 " $on_changed$\n"
763 " return this;\n"
764 "}\n");
765 WriteFieldDocComment(printer, descriptor_);
766 printer->Print(variables_,
767 "$deprecation$public Builder addAll$capitalized_name$Value(\n"
768 " java.lang.Iterable<java.lang.Integer> values) {\n"
769 " ensure$capitalized_name$IsMutable();\n"
770 " for (int value : values) {\n"
771 " $name$_.add(value);\n"
772 " }\n"
773 " $on_changed$\n"
774 " return this;\n"
775 "}\n");
776 }
777 }
778
779 void RepeatedImmutableEnumFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const780 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
781 // noop for enums
782 }
783
784 void RepeatedImmutableEnumFieldGenerator::
GenerateInitializationCode(io::Printer * printer) const785 GenerateInitializationCode(io::Printer* printer) const {
786 printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
787 }
788
789 void RepeatedImmutableEnumFieldGenerator::
GenerateBuilderClearCode(io::Printer * printer) const790 GenerateBuilderClearCode(io::Printer* printer) const {
791 printer->Print(variables_,
792 "$name$_ = java.util.Collections.emptyList();\n"
793 "$clear_mutable_bit_builder$;\n");
794 }
795
796 void RepeatedImmutableEnumFieldGenerator::
GenerateMergingCode(io::Printer * printer) const797 GenerateMergingCode(io::Printer* printer) const {
798 // The code below does two optimizations:
799 // 1. If the other list is empty, there's nothing to do. This ensures we
800 // don't allocate a new array if we already have an immutable one.
801 // 2. If the other list is non-empty and our current list is empty, we can
802 // reuse the other list which is guaranteed to be immutable.
803 printer->Print(variables_,
804 "if (!other.$name$_.isEmpty()) {\n"
805 " if ($name$_.isEmpty()) {\n"
806 " $name$_ = other.$name$_;\n"
807 " $clear_mutable_bit_builder$;\n"
808 " } else {\n"
809 " ensure$capitalized_name$IsMutable();\n"
810 " $name$_.addAll(other.$name$_);\n"
811 " }\n"
812 " $on_changed$\n"
813 "}\n");
814 }
815
816 void RepeatedImmutableEnumFieldGenerator::
GenerateBuildingCode(io::Printer * printer) const817 GenerateBuildingCode(io::Printer* printer) const {
818 // The code below ensures that the result has an immutable list. If our
819 // list is immutable, we can just reuse it. If not, we make it immutable.
820 printer->Print(variables_,
821 "if ($get_mutable_bit_builder$) {\n"
822 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
823 " $clear_mutable_bit_builder$;\n"
824 "}\n"
825 "result.$name$_ = $name$_;\n");
826 }
827
828 void RepeatedImmutableEnumFieldGenerator::
GenerateParsingCode(io::Printer * printer) const829 GenerateParsingCode(io::Printer* printer) const {
830 // Read and store the enum
831 if (SupportUnknownEnumValue(descriptor_->file())) {
832 printer->Print(variables_,
833 "int rawValue = input.readEnum();\n"
834 "if (!$get_mutable_bit_parser$) {\n"
835 " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
836 " $set_mutable_bit_parser$;\n"
837 "}\n"
838 "$name$_.add(rawValue);\n");
839 } else {
840 printer->Print(variables_,
841 "int rawValue = input.readEnum();\n"
842 "$type$ value = $type$.forNumber(rawValue);\n"
843 "if (value == null) {\n");
844 if (PreserveUnknownFields(descriptor_->containing_type())) {
845 printer->Print(variables_,
846 " unknownFields.mergeVarintField($number$, rawValue);\n");
847 }
848 printer->Print(variables_,
849 "} else {\n"
850 " if (!$get_mutable_bit_parser$) {\n"
851 " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
852 " $set_mutable_bit_parser$;\n"
853 " }\n"
854 " $name$_.add(rawValue);\n"
855 "}\n");
856 }
857 }
858
859 void RepeatedImmutableEnumFieldGenerator::
GenerateParsingCodeFromPacked(io::Printer * printer) const860 GenerateParsingCodeFromPacked(io::Printer* printer) const {
861 // Wrap GenerateParsingCode's contents with a while loop.
862
863 printer->Print(variables_,
864 "int length = input.readRawVarint32();\n"
865 "int oldLimit = input.pushLimit(length);\n"
866 "while(input.getBytesUntilLimit() > 0) {\n");
867 printer->Indent();
868
869 GenerateParsingCode(printer);
870
871 printer->Outdent();
872 printer->Print(variables_,
873 "}\n"
874 "input.popLimit(oldLimit);\n");
875 }
876
877 void RepeatedImmutableEnumFieldGenerator::
GenerateParsingDoneCode(io::Printer * printer) const878 GenerateParsingDoneCode(io::Printer* printer) const {
879 printer->Print(variables_,
880 "if ($get_mutable_bit_parser$) {\n"
881 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
882 "}\n");
883 }
884
885 void RepeatedImmutableEnumFieldGenerator::
GenerateSerializationCode(io::Printer * printer) const886 GenerateSerializationCode(io::Printer* printer) const {
887 if (descriptor_->is_packed()) {
888 printer->Print(variables_,
889 "if (get$capitalized_name$List().size() > 0) {\n"
890 " output.writeRawVarint32($tag$);\n"
891 " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
892 "}\n"
893 "for (int i = 0; i < $name$_.size(); i++) {\n"
894 " output.writeEnumNoTag($name$_.get(i));\n"
895 "}\n");
896 } else {
897 printer->Print(variables_,
898 "for (int i = 0; i < $name$_.size(); i++) {\n"
899 " output.writeEnum($number$, $name$_.get(i));\n"
900 "}\n");
901 }
902 }
903
904 void RepeatedImmutableEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer * printer) const905 GenerateSerializedSizeCode(io::Printer* printer) const {
906 printer->Print(variables_,
907 "{\n"
908 " int dataSize = 0;\n");
909 printer->Indent();
910
911 printer->Print(variables_,
912 "for (int i = 0; i < $name$_.size(); i++) {\n"
913 " dataSize += com.google.protobuf.CodedOutputStream\n"
914 " .computeEnumSizeNoTag($name$_.get(i));\n"
915 "}\n");
916 printer->Print(
917 "size += dataSize;\n");
918 if (descriptor_->is_packed()) {
919 printer->Print(variables_,
920 "if (!get$capitalized_name$List().isEmpty()) {"
921 " size += $tag_size$;\n"
922 " size += com.google.protobuf.CodedOutputStream\n"
923 " .computeRawVarint32Size(dataSize);\n"
924 "}");
925 } else {
926 printer->Print(variables_,
927 "size += $tag_size$ * $name$_.size();\n");
928 }
929
930 // cache the data size for packed fields.
931 if (descriptor_->is_packed()) {
932 printer->Print(variables_,
933 "$name$MemoizedSerializedSize = dataSize;\n");
934 }
935
936 printer->Outdent();
937 printer->Print("}\n");
938 }
939
940 void RepeatedImmutableEnumFieldGenerator::
GenerateEqualsCode(io::Printer * printer) const941 GenerateEqualsCode(io::Printer* printer) const {
942 printer->Print(variables_,
943 "result = result && $name$_.equals(other.$name$_);\n");
944 }
945
946 void RepeatedImmutableEnumFieldGenerator::
GenerateHashCode(io::Printer * printer) const947 GenerateHashCode(io::Printer* printer) const {
948 printer->Print(variables_,
949 "if (get$capitalized_name$Count() > 0) {\n"
950 " hash = (37 * hash) + $constant_name$;\n"
951 " hash = (53 * hash) + $name$_.hashCode();\n"
952 "}\n");
953 }
954
GetBoxedType() const955 string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const {
956 return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
957 }
958
959 } // namespace java
960 } // namespace compiler
961 } // namespace protobuf
962 } // namespace google
963