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,std::map<std::string,std::string> * variables)56 void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
57 int builderBitIndex, const FieldGeneratorInfo* info,
58 ClassNameResolver* name_resolver,
59 std::map<std::string, std::string>* variables) {
60 SetCommonFieldVariables(descriptor, info, variables);
61
62 (*variables)["type"] =
63 name_resolver->GetImmutableClassName(descriptor->enum_type());
64 (*variables)["mutable_type"] =
65 name_resolver->GetMutableClassName(descriptor->enum_type());
66 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
67 (*variables)["default_number"] =
68 StrCat(descriptor->default_value_enum()->number());
69 (*variables)["tag"] = StrCat(
70 static_cast<int32>(internal::WireFormat::MakeTag(descriptor)));
71 (*variables)["tag_size"] = StrCat(
72 internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
73 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
74 // by the proto compiler
75 (*variables)["deprecation"] =
76 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
77 (*variables)["on_changed"] = "onChanged();";
78 // Use deprecated valueOf() method to be compatible with old generated code
79 // for v2.5.0/v2.6.1.
80 // TODO(xiaofeng): Use "forNumber" when we no longer support compatibility
81 // with v2.5.0/v2.6.1, and remove the @SuppressWarnings annotations.
82 (*variables)["for_number"] = "valueOf";
83
84 if (HasHasbit(descriptor)) {
85 // For singular messages and builders, one bit is used for the hasField bit.
86 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
87 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
88
89 // Note that these have a trailing ";".
90 (*variables)["set_has_field_bit_message"] =
91 GenerateSetBit(messageBitIndex) + ";";
92 (*variables)["set_has_field_bit_builder"] =
93 GenerateSetBit(builderBitIndex) + ";";
94 (*variables)["clear_has_field_bit_builder"] =
95 GenerateClearBit(builderBitIndex) + ";";
96
97 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
98 } else {
99 (*variables)["set_has_field_bit_message"] = "";
100 (*variables)["set_has_field_bit_builder"] = "";
101 (*variables)["clear_has_field_bit_builder"] = "";
102
103 (*variables)["is_field_present_message"] =
104 (*variables)["name"] + "_ != " + (*variables)["default"] +
105 ".getNumber()";
106 }
107
108 // For repeated builders, one bit is used for whether the array is immutable.
109 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
110 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
111 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
112
113 (*variables)["get_has_field_bit_from_local"] =
114 GenerateGetBitFromLocal(builderBitIndex);
115 (*variables)["set_has_field_bit_to_local"] =
116 GenerateSetBitToLocal(messageBitIndex);
117
118 if (SupportUnknownEnumValue(descriptor->file())) {
119 (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
120 } else {
121 (*variables)["unknown"] = (*variables)["default"];
122 }
123 }
124
125 } // namespace
126
127 // ===================================================================
128
ImmutableEnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)129 ImmutableEnumFieldGenerator::ImmutableEnumFieldGenerator(
130 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
131 Context* context)
132 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
133 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
134 context->GetFieldGeneratorInfo(descriptor), name_resolver_,
135 &variables_);
136 }
137
~ImmutableEnumFieldGenerator()138 ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {}
139
GetNumBitsForMessage() const140 int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
141 return HasHasbit(descriptor_) ? 1 : 0;
142 }
143
GetNumBitsForBuilder() const144 int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
145 return GetNumBitsForMessage();
146 }
147
GenerateInterfaceMembers(io::Printer * printer) const148 void ImmutableEnumFieldGenerator::GenerateInterfaceMembers(
149 io::Printer* printer) const {
150 if (SupportFieldPresence(descriptor_)) {
151 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
152 printer->Print(variables_,
153 "$deprecation$boolean has$capitalized_name$();\n");
154 }
155 if (SupportUnknownEnumValue(descriptor_->file())) {
156 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
157 printer->Print(variables_,
158 "$deprecation$int get$capitalized_name$Value();\n");
159 }
160 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
161 printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
162 }
163
GenerateMembers(io::Printer * printer) const164 void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const {
165 printer->Print(variables_, "private int $name$_;\n");
166 PrintExtraFieldInfo(variables_, printer);
167 if (SupportFieldPresence(descriptor_)) {
168 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
169 printer->Print(variables_,
170 "@java.lang.Override $deprecation$public boolean "
171 "${$has$capitalized_name$$}$() {\n"
172 " return $get_has_field_bit_message$;\n"
173 "}\n");
174 printer->Annotate("{", "}", descriptor_);
175 }
176 if (SupportUnknownEnumValue(descriptor_->file())) {
177 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
178 printer->Print(variables_,
179 "@java.lang.Override $deprecation$public int "
180 "${$get$capitalized_name$Value$}$() {\n"
181 " return $name$_;\n"
182 "}\n");
183 printer->Annotate("{", "}", descriptor_);
184 }
185 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
186 printer->Print(variables_,
187 "@java.lang.Override $deprecation$public $type$ "
188 "${$get$capitalized_name$$}$() {\n"
189 " @SuppressWarnings(\"deprecation\")\n"
190 " $type$ result = $type$.$for_number$($name$_);\n"
191 " return result == null ? $unknown$ : result;\n"
192 "}\n");
193 printer->Annotate("{", "}", descriptor_);
194 }
195
GenerateBuilderMembers(io::Printer * printer) const196 void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
197 io::Printer* printer) const {
198 printer->Print(variables_, "private int $name$_ = $default_number$;\n");
199 if (SupportFieldPresence(descriptor_)) {
200 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
201 printer->Print(variables_,
202 "@java.lang.Override $deprecation$public boolean "
203 "${$has$capitalized_name$$}$() {\n"
204 " return $get_has_field_bit_builder$;\n"
205 "}\n");
206 printer->Annotate("{", "}", descriptor_);
207 }
208 if (SupportUnknownEnumValue(descriptor_->file())) {
209 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
210 printer->Print(variables_,
211 "@java.lang.Override $deprecation$public int "
212 "${$get$capitalized_name$Value$}$() {\n"
213 " return $name$_;\n"
214 "}\n");
215 printer->Annotate("{", "}", descriptor_);
216 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
217 /* builder */ true);
218 printer->Print(variables_,
219 "$deprecation$public Builder "
220 "${$set$capitalized_name$Value$}$(int value) {\n"
221 " $set_has_field_bit_builder$\n"
222 " $name$_ = value;\n"
223 " $on_changed$\n"
224 " return this;\n"
225 "}\n");
226 printer->Annotate("{", "}", descriptor_);
227 }
228 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
229 printer->Print(variables_,
230 "@java.lang.Override\n"
231 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
232 " @SuppressWarnings(\"deprecation\")\n"
233 " $type$ result = $type$.$for_number$($name$_);\n"
234 " return result == null ? $unknown$ : result;\n"
235 "}\n");
236 printer->Annotate("{", "}", descriptor_);
237 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
238 /* builder */ true);
239 printer->Print(variables_,
240 "$deprecation$public Builder "
241 "${$set$capitalized_name$$}$($type$ value) {\n"
242 " if (value == null) {\n"
243 " throw new NullPointerException();\n"
244 " }\n"
245 " $set_has_field_bit_builder$\n"
246 " $name$_ = value.getNumber();\n"
247 " $on_changed$\n"
248 " return this;\n"
249 "}\n");
250 printer->Annotate("{", "}", descriptor_);
251 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
252 /* builder */ true);
253 printer->Print(
254 variables_,
255 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
256 " $clear_has_field_bit_builder$\n"
257 " $name$_ = $default_number$;\n"
258 " $on_changed$\n"
259 " return this;\n"
260 "}\n");
261 printer->Annotate("{", "}", descriptor_);
262 }
263
GenerateFieldBuilderInitializationCode(io::Printer * printer) const264 void ImmutableEnumFieldGenerator::GenerateFieldBuilderInitializationCode(
265 io::Printer* printer) const {
266 // noop for enums
267 }
268
GenerateInitializationCode(io::Printer * printer) const269 void ImmutableEnumFieldGenerator::GenerateInitializationCode(
270 io::Printer* printer) const {
271 printer->Print(variables_, "$name$_ = $default_number$;\n");
272 }
273
GenerateBuilderClearCode(io::Printer * printer) const274 void ImmutableEnumFieldGenerator::GenerateBuilderClearCode(
275 io::Printer* printer) const {
276 printer->Print(variables_,
277 "$name$_ = $default_number$;\n"
278 "$clear_has_field_bit_builder$\n");
279 }
280
GenerateMergingCode(io::Printer * printer) const281 void ImmutableEnumFieldGenerator::GenerateMergingCode(
282 io::Printer* printer) const {
283 if (SupportFieldPresence(descriptor_)) {
284 printer->Print(variables_,
285 "if (other.has$capitalized_name$()) {\n"
286 " set$capitalized_name$(other.get$capitalized_name$());\n"
287 "}\n");
288 } else if (SupportUnknownEnumValue(descriptor_->file())) {
289 printer->Print(
290 variables_,
291 "if (other.$name$_ != $default_number$) {\n"
292 " set$capitalized_name$Value(other.get$capitalized_name$Value());\n"
293 "}\n");
294 } else {
295 GOOGLE_LOG(FATAL) << "Can't reach here.";
296 }
297 }
298
GenerateBuildingCode(io::Printer * printer) const299 void ImmutableEnumFieldGenerator::GenerateBuildingCode(
300 io::Printer* printer) const {
301 if (SupportFieldPresence(descriptor_)) {
302 printer->Print(variables_,
303 "if ($get_has_field_bit_from_local$) {\n"
304 " $set_has_field_bit_to_local$;\n"
305 "}\n");
306 }
307 printer->Print(variables_, "result.$name$_ = $name$_;\n");
308 }
309
GenerateBuilderParsingCode(io::Printer * printer) const310 void ImmutableEnumFieldGenerator::GenerateBuilderParsingCode(
311 io::Printer* printer) const {
312 if (SupportUnknownEnumValue(descriptor_->file())) {
313 printer->Print(variables_,
314 "$name$_ = input.readEnum();\n"
315 "$set_has_field_bit_builder$\n");
316 } else {
317 printer->Print(variables_,
318 "int tmpRaw = input.readEnum();\n"
319 "$type$ tmpValue =\n"
320 " $type$.forNumber(tmpRaw);\n"
321 "if (tmpValue == null) {\n"
322 " mergeUnknownVarintField($number$, tmpRaw);\n"
323 "} else {\n"
324 " $name$_ = tmpRaw;\n"
325 " $set_has_field_bit_builder$\n"
326 "}\n");
327 }
328 }
329
GenerateSerializationCode(io::Printer * printer) const330 void ImmutableEnumFieldGenerator::GenerateSerializationCode(
331 io::Printer* printer) const {
332 printer->Print(variables_,
333 "if ($is_field_present_message$) {\n"
334 " output.writeEnum($number$, $name$_);\n"
335 "}\n");
336 }
337
GenerateSerializedSizeCode(io::Printer * printer) const338 void ImmutableEnumFieldGenerator::GenerateSerializedSizeCode(
339 io::Printer* printer) const {
340 printer->Print(variables_,
341 "if ($is_field_present_message$) {\n"
342 " size += com.google.protobuf.CodedOutputStream\n"
343 " .computeEnumSize($number$, $name$_);\n"
344 "}\n");
345 }
346
GenerateEqualsCode(io::Printer * printer) const347 void ImmutableEnumFieldGenerator::GenerateEqualsCode(
348 io::Printer* printer) const {
349 printer->Print(variables_, "if ($name$_ != other.$name$_) return false;\n");
350 }
351
GenerateHashCode(io::Printer * printer) const352 void ImmutableEnumFieldGenerator::GenerateHashCode(io::Printer* printer) const {
353 printer->Print(variables_,
354 "hash = (37 * hash) + $constant_name$;\n"
355 "hash = (53 * hash) + $name$_;\n");
356 }
357
GetBoxedType() const358 std::string ImmutableEnumFieldGenerator::GetBoxedType() const {
359 return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
360 }
361
362 // ===================================================================
363
ImmutableEnumOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)364 ImmutableEnumOneofFieldGenerator::ImmutableEnumOneofFieldGenerator(
365 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
366 Context* context)
367 : ImmutableEnumFieldGenerator(descriptor, messageBitIndex, builderBitIndex,
368 context) {
369 const OneofGeneratorInfo* info =
370 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
371 SetCommonOneofVariables(descriptor, info, &variables_);
372 }
373
~ImmutableEnumOneofFieldGenerator()374 ImmutableEnumOneofFieldGenerator::~ImmutableEnumOneofFieldGenerator() {}
375
GenerateMembers(io::Printer * printer) const376 void ImmutableEnumOneofFieldGenerator::GenerateMembers(
377 io::Printer* printer) const {
378 PrintExtraFieldInfo(variables_, printer);
379 if (SupportFieldPresence(descriptor_)) {
380 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
381 printer->Print(
382 variables_,
383 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
384 " return $has_oneof_case_message$;\n"
385 "}\n");
386 printer->Annotate("{", "}", descriptor_);
387 }
388 if (SupportUnknownEnumValue(descriptor_->file())) {
389 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
390 printer->Print(
391 variables_,
392 "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
393 " if ($has_oneof_case_message$) {\n"
394 " return (java.lang.Integer) $oneof_name$_;\n"
395 " }\n"
396 " return $default_number$;\n"
397 "}\n");
398 printer->Annotate("{", "}", descriptor_);
399 }
400 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
401 printer->Print(variables_,
402 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
403 " if ($has_oneof_case_message$) {\n"
404 " @SuppressWarnings(\"deprecation\")\n"
405 " $type$ result = $type$.$for_number$(\n"
406 " (java.lang.Integer) $oneof_name$_);\n"
407 " return result == null ? $unknown$ : result;\n"
408 " }\n"
409 " return $default$;\n"
410 "}\n");
411 printer->Annotate("{", "}", descriptor_);
412 }
413
GenerateBuilderMembers(io::Printer * printer) const414 void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
415 io::Printer* printer) const {
416 if (SupportFieldPresence(descriptor_)) {
417 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
418 printer->Print(
419 variables_,
420 "@java.lang.Override\n"
421 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
422 " return $has_oneof_case_message$;\n"
423 "}\n");
424 printer->Annotate("{", "}", descriptor_);
425 }
426 if (SupportUnknownEnumValue(descriptor_->file())) {
427 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
428 printer->Print(
429 variables_,
430 "@java.lang.Override\n"
431 "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
432 " if ($has_oneof_case_message$) {\n"
433 " return ((java.lang.Integer) $oneof_name$_).intValue();\n"
434 " }\n"
435 " return $default_number$;\n"
436 "}\n");
437 printer->Annotate("{", "}", descriptor_);
438 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
439 /* builder */ true);
440 printer->Print(variables_,
441 "$deprecation$public Builder "
442 "${$set$capitalized_name$Value$}$(int value) {\n"
443 " $set_oneof_case_message$;\n"
444 " $oneof_name$_ = value;\n"
445 " $on_changed$\n"
446 " return this;\n"
447 "}\n");
448 printer->Annotate("{", "}", descriptor_);
449 }
450 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
451 printer->Print(variables_,
452 "@java.lang.Override\n"
453 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
454 " if ($has_oneof_case_message$) {\n"
455 " @SuppressWarnings(\"deprecation\")\n"
456 " $type$ result = $type$.$for_number$(\n"
457 " (java.lang.Integer) $oneof_name$_);\n"
458 " return result == null ? $unknown$ : result;\n"
459 " }\n"
460 " return $default$;\n"
461 "}\n");
462 printer->Annotate("{", "}", descriptor_);
463 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
464 /* builder */ true);
465 printer->Print(variables_,
466 "$deprecation$public Builder "
467 "${$set$capitalized_name$$}$($type$ value) {\n"
468 " if (value == null) {\n"
469 " throw new NullPointerException();\n"
470 " }\n"
471 " $set_oneof_case_message$;\n"
472 " $oneof_name$_ = value.getNumber();\n"
473 " $on_changed$\n"
474 " return this;\n"
475 "}\n");
476 printer->Annotate("{", "}", descriptor_);
477 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
478 /* builder */ true);
479 printer->Print(
480 variables_,
481 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
482 " if ($has_oneof_case_message$) {\n"
483 " $clear_oneof_case_message$;\n"
484 " $oneof_name$_ = null;\n"
485 " $on_changed$\n"
486 " }\n"
487 " return this;\n"
488 "}\n");
489 printer->Annotate("{", "}", descriptor_);
490 }
491
GenerateBuilderClearCode(io::Printer * printer) const492 void ImmutableEnumOneofFieldGenerator::GenerateBuilderClearCode(
493 io::Printer* printer) const {
494 // No-op: Enum fields in oneofs are correctly cleared by clearing the oneof
495 }
496
GenerateBuildingCode(io::Printer * printer) const497 void ImmutableEnumOneofFieldGenerator::GenerateBuildingCode(
498 io::Printer* printer) const {
499 printer->Print(variables_,
500 "if ($has_oneof_case_message$) {\n"
501 " result.$oneof_name$_ = $oneof_name$_;\n"
502 "}\n");
503 }
504
GenerateMergingCode(io::Printer * printer) const505 void ImmutableEnumOneofFieldGenerator::GenerateMergingCode(
506 io::Printer* printer) const {
507 if (SupportUnknownEnumValue(descriptor_->file())) {
508 printer->Print(
509 variables_,
510 "set$capitalized_name$Value(other.get$capitalized_name$Value());\n");
511 } else {
512 printer->Print(variables_,
513 "set$capitalized_name$(other.get$capitalized_name$());\n");
514 }
515 }
516
GenerateBuilderParsingCode(io::Printer * printer) const517 void ImmutableEnumOneofFieldGenerator::GenerateBuilderParsingCode(
518 io::Printer* printer) const {
519 if (SupportUnknownEnumValue(descriptor_->file())) {
520 printer->Print(variables_,
521 "int rawValue = input.readEnum();\n"
522 "$set_oneof_case_message$;\n"
523 "$oneof_name$_ = rawValue;\n");
524 } else {
525 printer->Print(variables_,
526 "int rawValue = input.readEnum();\n"
527 "$type$ value =\n"
528 " $type$.forNumber(rawValue);\n"
529 "if (value == null) {\n"
530 " mergeUnknownVarintField($number$, rawValue);\n"
531 "} else {\n"
532 " $set_oneof_case_message$;\n"
533 " $oneof_name$_ = rawValue;\n"
534 "}\n");
535 }
536 }
537
GenerateSerializationCode(io::Printer * printer) const538 void ImmutableEnumOneofFieldGenerator::GenerateSerializationCode(
539 io::Printer* printer) const {
540 printer->Print(
541 variables_,
542 "if ($has_oneof_case_message$) {\n"
543 " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
544 "}\n");
545 }
546
GenerateSerializedSizeCode(io::Printer * printer) const547 void ImmutableEnumOneofFieldGenerator::GenerateSerializedSizeCode(
548 io::Printer* printer) const {
549 printer->Print(
550 variables_,
551 "if ($has_oneof_case_message$) {\n"
552 " size += com.google.protobuf.CodedOutputStream\n"
553 " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
554 "}\n");
555 }
556
GenerateEqualsCode(io::Printer * printer) const557 void ImmutableEnumOneofFieldGenerator::GenerateEqualsCode(
558 io::Printer* printer) const {
559 if (SupportUnknownEnumValue(descriptor_->file())) {
560 printer->Print(
561 variables_,
562 "if (get$capitalized_name$Value()\n"
563 " != other.get$capitalized_name$Value()) return false;\n");
564 } else {
565 printer->Print(
566 variables_,
567 "if (!get$capitalized_name$()\n"
568 " .equals(other.get$capitalized_name$())) return false;\n");
569 }
570 }
571
GenerateHashCode(io::Printer * printer) const572 void ImmutableEnumOneofFieldGenerator::GenerateHashCode(
573 io::Printer* printer) const {
574 if (SupportUnknownEnumValue(descriptor_->file())) {
575 printer->Print(variables_,
576 "hash = (37 * hash) + $constant_name$;\n"
577 "hash = (53 * hash) + get$capitalized_name$Value();\n");
578 } else {
579 printer->Print(
580 variables_,
581 "hash = (37 * hash) + $constant_name$;\n"
582 "hash = (53 * hash) + get$capitalized_name$().getNumber();\n");
583 }
584 }
585
586 // ===================================================================
587
RepeatedImmutableEnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)588 RepeatedImmutableEnumFieldGenerator::RepeatedImmutableEnumFieldGenerator(
589 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
590 Context* context)
591 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
592 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
593 context->GetFieldGeneratorInfo(descriptor), name_resolver_,
594 &variables_);
595 }
596
~RepeatedImmutableEnumFieldGenerator()597 RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {}
598
GetNumBitsForMessage() const599 int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
600 return 0;
601 }
602
GetNumBitsForBuilder() const603 int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
604 return 1;
605 }
606
GenerateInterfaceMembers(io::Printer * printer) const607 void RepeatedImmutableEnumFieldGenerator::GenerateInterfaceMembers(
608 io::Printer* printer) const {
609 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
610 printer->Print(
611 variables_,
612 "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
613 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
614 printer->Print(variables_,
615 "$deprecation$int get$capitalized_name$Count();\n");
616 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
617 printer->Print(variables_,
618 "$deprecation$$type$ get$capitalized_name$(int index);\n");
619 if (SupportUnknownEnumValue(descriptor_->file())) {
620 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
621 printer->Print(variables_,
622 "$deprecation$java.util.List<java.lang.Integer>\n"
623 "get$capitalized_name$ValueList();\n");
624 WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
625 LIST_INDEXED_GETTER);
626 printer->Print(variables_,
627 "$deprecation$int get$capitalized_name$Value(int index);\n");
628 }
629 }
630
GenerateMembers(io::Printer * printer) const631 void RepeatedImmutableEnumFieldGenerator::GenerateMembers(
632 io::Printer* printer) const {
633 printer->Print(
634 variables_,
635 "private java.util.List<java.lang.Integer> $name$_;\n"
636 "private static final "
637 "com.google.protobuf.Internal.ListAdapter.Converter<\n"
638 " java.lang.Integer, $type$> $name$_converter_ =\n"
639 " new com.google.protobuf.Internal.ListAdapter.Converter<\n"
640 " java.lang.Integer, $type$>() {\n"
641 " public $type$ convert(java.lang.Integer from) {\n"
642 " @SuppressWarnings(\"deprecation\")\n"
643 " $type$ result = $type$.$for_number$(from);\n"
644 " return result == null ? $unknown$ : result;\n"
645 " }\n"
646 " };\n");
647 PrintExtraFieldInfo(variables_, printer);
648 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
649 printer->Print(
650 variables_,
651 "@java.lang.Override\n"
652 "$deprecation$public java.util.List<$type$> "
653 "${$get$capitalized_name$List$}$() {\n"
654 " return new com.google.protobuf.Internal.ListAdapter<\n"
655 " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
656 "}\n");
657 printer->Annotate("{", "}", descriptor_);
658 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
659 printer->Print(
660 variables_,
661 "@java.lang.Override\n"
662 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
663 " return $name$_.size();\n"
664 "}\n");
665 printer->Annotate("{", "}", descriptor_);
666 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
667 printer->Print(
668 variables_,
669 "@java.lang.Override\n"
670 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
671 " return $name$_converter_.convert($name$_.get(index));\n"
672 "}\n");
673 printer->Annotate("{", "}", descriptor_);
674 if (SupportUnknownEnumValue(descriptor_->file())) {
675 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
676 printer->Print(variables_,
677 "@java.lang.Override\n"
678 "$deprecation$public java.util.List<java.lang.Integer>\n"
679 "${$get$capitalized_name$ValueList$}$() {\n"
680 " return $name$_;\n"
681 "}\n");
682 printer->Annotate("{", "}", descriptor_);
683 WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
684 LIST_INDEXED_GETTER);
685 printer->Print(variables_,
686 "@java.lang.Override\n"
687 "$deprecation$public int "
688 "${$get$capitalized_name$Value$}$(int index) {\n"
689 " return $name$_.get(index);\n"
690 "}\n");
691 printer->Annotate("{", "}", descriptor_);
692 }
693
694 if (descriptor_->is_packed()) {
695 printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n");
696 }
697 }
698
GenerateBuilderMembers(io::Printer * printer) const699 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers(
700 io::Printer* printer) const {
701 printer->Print(
702 variables_,
703 // One field is the list and the other field keeps track of whether the
704 // list is immutable. If it's immutable, the invariant is that it must
705 // either an instance of Collections.emptyList() or it's an ArrayList
706 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
707 // a reference to the underlying ArrayList. This invariant allows us to
708 // share instances of lists between protocol buffers avoiding expensive
709 // memory allocations. Note, immutable is a strong guarantee here -- not
710 // just that the list cannot be modified via the reference but that the
711 // list can never be modified.
712 "private java.util.List<java.lang.Integer> $name$_ =\n"
713 " java.util.Collections.emptyList();\n"
714
715 "private void ensure$capitalized_name$IsMutable() {\n"
716 " if (!$get_mutable_bit_builder$) {\n"
717 " $name$_ = new java.util.ArrayList<java.lang.Integer>($name$_);\n"
718 " $set_mutable_bit_builder$;\n"
719 " }\n"
720 "}\n");
721
722 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
723 printer->Print(
724 variables_,
725 // Note: We return an unmodifiable list because otherwise the caller
726 // could hold on to the returned list and modify it after the message
727 // has been built, thus mutating the message which is supposed to be
728 // immutable.
729 "$deprecation$public java.util.List<$type$> "
730 "${$get$capitalized_name$List$}$() {\n"
731 " return new com.google.protobuf.Internal.ListAdapter<\n"
732 " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
733 "}\n");
734 printer->Annotate("{", "}", descriptor_);
735 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
736 printer->Print(
737 variables_,
738 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
739 " return $name$_.size();\n"
740 "}\n");
741 printer->Annotate("{", "}", descriptor_);
742 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
743 printer->Print(
744 variables_,
745 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
746 " return $name$_converter_.convert($name$_.get(index));\n"
747 "}\n");
748 printer->Annotate("{", "}", descriptor_);
749 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
750 /* builder */ true);
751 printer->Print(variables_,
752 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
753 " int index, $type$ value) {\n"
754 " if (value == null) {\n"
755 " throw new NullPointerException();\n"
756 " }\n"
757 " ensure$capitalized_name$IsMutable();\n"
758 " $name$_.set(index, value.getNumber());\n"
759 " $on_changed$\n"
760 " return this;\n"
761 "}\n");
762 printer->Annotate("{", "}", descriptor_);
763 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
764 /* builder */ true);
765 printer->Print(variables_,
766 "$deprecation$public Builder "
767 "${$add$capitalized_name$$}$($type$ value) {\n"
768 " if (value == null) {\n"
769 " throw new NullPointerException();\n"
770 " }\n"
771 " ensure$capitalized_name$IsMutable();\n"
772 " $name$_.add(value.getNumber());\n"
773 " $on_changed$\n"
774 " return this;\n"
775 "}\n");
776 printer->Annotate("{", "}", descriptor_);
777 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
778 /* builder */ true);
779 printer->Print(variables_,
780 "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
781 " java.lang.Iterable<? extends $type$> values) {\n"
782 " ensure$capitalized_name$IsMutable();\n"
783 " for ($type$ value : values) {\n"
784 " $name$_.add(value.getNumber());\n"
785 " }\n"
786 " $on_changed$\n"
787 " return this;\n"
788 "}\n");
789 printer->Annotate("{", "}", descriptor_);
790 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
791 /* builder */ true);
792 printer->Print(
793 variables_,
794 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
795 " $name$_ = java.util.Collections.emptyList();\n"
796 " $clear_mutable_bit_builder$;\n"
797 " $on_changed$\n"
798 " return this;\n"
799 "}\n");
800 printer->Annotate("{", "}", descriptor_);
801
802 if (SupportUnknownEnumValue(descriptor_->file())) {
803 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
804 printer->Print(variables_,
805 "$deprecation$public java.util.List<java.lang.Integer>\n"
806 "${$get$capitalized_name$ValueList$}$() {\n"
807 " return java.util.Collections.unmodifiableList($name$_);\n"
808 "}\n");
809 printer->Annotate("{", "}", descriptor_);
810 WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
811 LIST_INDEXED_GETTER);
812 printer->Print(variables_,
813 "$deprecation$public int "
814 "${$get$capitalized_name$Value$}$(int index) {\n"
815 " return $name$_.get(index);\n"
816 "}\n");
817 printer->Annotate("{", "}", descriptor_);
818 WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
819 LIST_INDEXED_GETTER,
820 /* builder */ true);
821 printer->Print(
822 variables_,
823 "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
824 " int index, int value) {\n"
825 " ensure$capitalized_name$IsMutable();\n"
826 " $name$_.set(index, value);\n"
827 " $on_changed$\n"
828 " return this;\n"
829 "}\n");
830 printer->Annotate("{", "}", descriptor_);
831 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER,
832 /* builder */ true);
833 printer->Print(variables_,
834 "$deprecation$public Builder "
835 "${$add$capitalized_name$Value$}$(int value) {\n"
836 " ensure$capitalized_name$IsMutable();\n"
837 " $name$_.add(value);\n"
838 " $on_changed$\n"
839 " return this;\n"
840 "}\n");
841 printer->Annotate("{", "}", descriptor_);
842 WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
843 LIST_MULTI_ADDER, /* builder */ true);
844 printer->Print(
845 variables_,
846 "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
847 " java.lang.Iterable<java.lang.Integer> values) {\n"
848 " ensure$capitalized_name$IsMutable();\n"
849 " for (int value : values) {\n"
850 " $name$_.add(value);\n"
851 " }\n"
852 " $on_changed$\n"
853 " return this;\n"
854 "}\n");
855 printer->Annotate("{", "}", descriptor_);
856 }
857 }
858
859 void RepeatedImmutableEnumFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const860 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
861 // noop for enums
862 }
863
GenerateInitializationCode(io::Printer * printer) const864 void RepeatedImmutableEnumFieldGenerator::GenerateInitializationCode(
865 io::Printer* printer) const {
866 printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
867 }
868
GenerateBuilderClearCode(io::Printer * printer) const869 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderClearCode(
870 io::Printer* printer) const {
871 printer->Print(variables_,
872 "$name$_ = java.util.Collections.emptyList();\n"
873 "$clear_mutable_bit_builder$;\n");
874 }
875
GenerateMergingCode(io::Printer * printer) const876 void RepeatedImmutableEnumFieldGenerator::GenerateMergingCode(
877 io::Printer* printer) const {
878 // The code below does two optimizations:
879 // 1. If the other list is empty, there's nothing to do. This ensures we
880 // don't allocate a new array if we already have an immutable one.
881 // 2. If the other list is non-empty and our current list is empty, we can
882 // reuse the other list which is guaranteed to be immutable.
883 printer->Print(variables_,
884 "if (!other.$name$_.isEmpty()) {\n"
885 " if ($name$_.isEmpty()) {\n"
886 " $name$_ = other.$name$_;\n"
887 " $clear_mutable_bit_builder$;\n"
888 " } else {\n"
889 " ensure$capitalized_name$IsMutable();\n"
890 " $name$_.addAll(other.$name$_);\n"
891 " }\n"
892 " $on_changed$\n"
893 "}\n");
894 }
895
GenerateBuildingCode(io::Printer * printer) const896 void RepeatedImmutableEnumFieldGenerator::GenerateBuildingCode(
897 io::Printer* printer) const {
898 // The code below ensures that the result has an immutable list. If our
899 // list is immutable, we can just reuse it. If not, we make it immutable.
900 printer->Print(
901 variables_,
902 "if ($get_mutable_bit_builder$) {\n"
903 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
904 " $clear_mutable_bit_builder$;\n"
905 "}\n"
906 "result.$name$_ = $name$_;\n");
907 }
908
GenerateBuilderParsingCode(io::Printer * printer) const909 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderParsingCode(
910 io::Printer* printer) const {
911 // Read and store the enum
912 if (SupportUnknownEnumValue(descriptor_->file())) {
913 printer->Print(variables_,
914 "int tmpRaw = input.readEnum();\n"
915 "ensure$capitalized_name$IsMutable();\n"
916 "$name$_.add(tmpRaw);\n");
917 } else {
918 printer->Print(variables_,
919 "int tmpRaw = input.readEnum();\n"
920 "$type$ tmpValue =\n"
921 " $type$.forNumber(tmpRaw);\n"
922 "if (tmpValue == null) {\n"
923 " mergeUnknownVarintField($number$, tmpRaw);\n"
924 "} else {\n"
925 " ensure$capitalized_name$IsMutable();\n"
926 " $name$_.add(tmpRaw);\n"
927 "}\n");
928 }
929 }
930
GenerateBuilderParsingCodeFromPacked(io::Printer * printer) const931 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderParsingCodeFromPacked(
932 io::Printer* printer) const {
933 // Wrap GenerateParsingCode's contents with a while loop.
934
935 printer->Print(variables_,
936 "int length = input.readRawVarint32();\n"
937 "int oldLimit = input.pushLimit(length);\n"
938 "while(input.getBytesUntilLimit() > 0) {\n");
939 printer->Indent();
940
941 GenerateBuilderParsingCode(printer);
942
943 printer->Outdent();
944 printer->Print(variables_,
945 "}\n"
946 "input.popLimit(oldLimit);\n");
947 }
948
GenerateSerializationCode(io::Printer * printer) const949 void RepeatedImmutableEnumFieldGenerator::GenerateSerializationCode(
950 io::Printer* printer) const {
951 if (descriptor_->is_packed()) {
952 printer->Print(variables_,
953 "if (get$capitalized_name$List().size() > 0) {\n"
954 " output.writeUInt32NoTag($tag$);\n"
955 " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
956 "}\n"
957 "for (int i = 0; i < $name$_.size(); i++) {\n"
958 " output.writeEnumNoTag($name$_.get(i));\n"
959 "}\n");
960 } else {
961 printer->Print(variables_,
962 "for (int i = 0; i < $name$_.size(); i++) {\n"
963 " output.writeEnum($number$, $name$_.get(i));\n"
964 "}\n");
965 }
966 }
967
GenerateSerializedSizeCode(io::Printer * printer) const968 void RepeatedImmutableEnumFieldGenerator::GenerateSerializedSizeCode(
969 io::Printer* printer) const {
970 printer->Print(variables_,
971 "{\n"
972 " int dataSize = 0;\n");
973 printer->Indent();
974
975 printer->Print(variables_,
976 "for (int i = 0; i < $name$_.size(); i++) {\n"
977 " dataSize += com.google.protobuf.CodedOutputStream\n"
978 " .computeEnumSizeNoTag($name$_.get(i));\n"
979 "}\n");
980 printer->Print("size += dataSize;\n");
981 if (descriptor_->is_packed()) {
982 printer->Print(variables_,
983 "if (!get$capitalized_name$List().isEmpty()) {"
984 " size += $tag_size$;\n"
985 " size += com.google.protobuf.CodedOutputStream\n"
986 " .computeUInt32SizeNoTag(dataSize);\n"
987 "}");
988 } else {
989 printer->Print(variables_, "size += $tag_size$ * $name$_.size();\n");
990 }
991
992 // cache the data size for packed fields.
993 if (descriptor_->is_packed()) {
994 printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
995 }
996
997 printer->Outdent();
998 printer->Print("}\n");
999 }
1000
GenerateEqualsCode(io::Printer * printer) const1001 void RepeatedImmutableEnumFieldGenerator::GenerateEqualsCode(
1002 io::Printer* printer) const {
1003 printer->Print(variables_,
1004 "if (!$name$_.equals(other.$name$_)) return false;\n");
1005 }
1006
GenerateHashCode(io::Printer * printer) const1007 void RepeatedImmutableEnumFieldGenerator::GenerateHashCode(
1008 io::Printer* printer) const {
1009 printer->Print(variables_,
1010 "if (get$capitalized_name$Count() > 0) {\n"
1011 " hash = (37 * hash) + $constant_name$;\n"
1012 " hash = (53 * hash) + $name$_.hashCode();\n"
1013 "}\n");
1014 }
1015
GetBoxedType() const1016 std::string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const {
1017 return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
1018 }
1019
1020 } // namespace java
1021 } // namespace compiler
1022 } // namespace protobuf
1023 } // namespace google
1024