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 (SupportFieldPresence(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 // For repeated fields, one bit is used for whether the array is immutable
114 // in the parsing constructor.
115 (*variables)["get_mutable_bit_parser"] =
116 GenerateGetBitMutableLocal(builderBitIndex);
117 (*variables)["set_mutable_bit_parser"] =
118 GenerateSetBitMutableLocal(builderBitIndex);
119
120 (*variables)["get_has_field_bit_from_local"] =
121 GenerateGetBitFromLocal(builderBitIndex);
122 (*variables)["set_has_field_bit_to_local"] =
123 GenerateSetBitToLocal(messageBitIndex);
124
125 if (SupportUnknownEnumValue(descriptor->file())) {
126 (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
127 } else {
128 (*variables)["unknown"] = (*variables)["default"];
129 }
130 }
131
132 } // namespace
133
134 // ===================================================================
135
ImmutableEnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)136 ImmutableEnumFieldGenerator::ImmutableEnumFieldGenerator(
137 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
138 Context* context)
139 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
140 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
141 context->GetFieldGeneratorInfo(descriptor), name_resolver_,
142 &variables_);
143 }
144
~ImmutableEnumFieldGenerator()145 ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {}
146
GetNumBitsForMessage() const147 int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
148 return SupportFieldPresence(descriptor_) ? 1 : 0;
149 }
150
GetNumBitsForBuilder() const151 int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
152 return GetNumBitsForMessage();
153 }
154
GenerateInterfaceMembers(io::Printer * printer) const155 void ImmutableEnumFieldGenerator::GenerateInterfaceMembers(
156 io::Printer* printer) const {
157 if (SupportFieldPresence(descriptor_)) {
158 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
159 printer->Print(variables_,
160 "$deprecation$boolean has$capitalized_name$();\n");
161 }
162 if (SupportUnknownEnumValue(descriptor_->file())) {
163 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
164 printer->Print(variables_,
165 "$deprecation$int get$capitalized_name$Value();\n");
166 }
167 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
168 printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
169 }
170
GenerateMembers(io::Printer * printer) const171 void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const {
172 printer->Print(variables_, "private int $name$_;\n");
173 PrintExtraFieldInfo(variables_, printer);
174 if (SupportFieldPresence(descriptor_)) {
175 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
176 printer->Print(variables_,
177 "@java.lang.Override $deprecation$public boolean "
178 "${$has$capitalized_name$$}$() {\n"
179 " return $get_has_field_bit_message$;\n"
180 "}\n");
181 printer->Annotate("{", "}", descriptor_);
182 }
183 if (SupportUnknownEnumValue(descriptor_->file())) {
184 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
185 printer->Print(variables_,
186 "@java.lang.Override $deprecation$public int "
187 "${$get$capitalized_name$Value$}$() {\n"
188 " return $name$_;\n"
189 "}\n");
190 printer->Annotate("{", "}", descriptor_);
191 }
192 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
193 printer->Print(variables_,
194 "@java.lang.Override $deprecation$public $type$ "
195 "${$get$capitalized_name$$}$() {\n"
196 " @SuppressWarnings(\"deprecation\")\n"
197 " $type$ result = $type$.$for_number$($name$_);\n"
198 " return result == null ? $unknown$ : result;\n"
199 "}\n");
200 printer->Annotate("{", "}", descriptor_);
201 }
202
GenerateBuilderMembers(io::Printer * printer) const203 void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
204 io::Printer* printer) const {
205 printer->Print(variables_, "private int $name$_ = $default_number$;\n");
206 if (SupportFieldPresence(descriptor_)) {
207 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
208 printer->Print(variables_,
209 "@java.lang.Override $deprecation$public boolean "
210 "${$has$capitalized_name$$}$() {\n"
211 " return $get_has_field_bit_builder$;\n"
212 "}\n");
213 printer->Annotate("{", "}", descriptor_);
214 }
215 if (SupportUnknownEnumValue(descriptor_->file())) {
216 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
217 printer->Print(variables_,
218 "@java.lang.Override $deprecation$public int "
219 "${$get$capitalized_name$Value$}$() {\n"
220 " return $name$_;\n"
221 "}\n");
222 printer->Annotate("{", "}", descriptor_);
223 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
224 /* builder */ true);
225 printer->Print(variables_,
226 "$deprecation$public Builder "
227 "${$set$capitalized_name$Value$}$(int value) {\n"
228 " $set_has_field_bit_builder$\n"
229 " $name$_ = value;\n"
230 " $on_changed$\n"
231 " return this;\n"
232 "}\n");
233 printer->Annotate("{", "}", descriptor_);
234 }
235 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
236 printer->Print(variables_,
237 "@java.lang.Override\n"
238 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
239 " @SuppressWarnings(\"deprecation\")\n"
240 " $type$ result = $type$.$for_number$($name$_);\n"
241 " return result == null ? $unknown$ : result;\n"
242 "}\n");
243 printer->Annotate("{", "}", descriptor_);
244 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
245 /* builder */ true);
246 printer->Print(variables_,
247 "$deprecation$public Builder "
248 "${$set$capitalized_name$$}$($type$ value) {\n"
249 " if (value == null) {\n"
250 " throw new NullPointerException();\n"
251 " }\n"
252 " $set_has_field_bit_builder$\n"
253 " $name$_ = value.getNumber();\n"
254 " $on_changed$\n"
255 " return this;\n"
256 "}\n");
257 printer->Annotate("{", "}", descriptor_);
258 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
259 /* builder */ true);
260 printer->Print(
261 variables_,
262 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
263 " $clear_has_field_bit_builder$\n"
264 " $name$_ = $default_number$;\n"
265 " $on_changed$\n"
266 " return this;\n"
267 "}\n");
268 printer->Annotate("{", "}", descriptor_);
269 }
270
GenerateFieldBuilderInitializationCode(io::Printer * printer) const271 void ImmutableEnumFieldGenerator::GenerateFieldBuilderInitializationCode(
272 io::Printer* printer) const {
273 // noop for enums
274 }
275
GenerateInitializationCode(io::Printer * printer) const276 void ImmutableEnumFieldGenerator::GenerateInitializationCode(
277 io::Printer* printer) const {
278 printer->Print(variables_, "$name$_ = $default_number$;\n");
279 }
280
GenerateBuilderClearCode(io::Printer * printer) const281 void ImmutableEnumFieldGenerator::GenerateBuilderClearCode(
282 io::Printer* printer) const {
283 printer->Print(variables_,
284 "$name$_ = $default_number$;\n"
285 "$clear_has_field_bit_builder$\n");
286 }
287
GenerateMergingCode(io::Printer * printer) const288 void ImmutableEnumFieldGenerator::GenerateMergingCode(
289 io::Printer* printer) const {
290 if (SupportFieldPresence(descriptor_)) {
291 printer->Print(variables_,
292 "if (other.has$capitalized_name$()) {\n"
293 " set$capitalized_name$(other.get$capitalized_name$());\n"
294 "}\n");
295 } else if (SupportUnknownEnumValue(descriptor_->file())) {
296 printer->Print(
297 variables_,
298 "if (other.$name$_ != $default_number$) {\n"
299 " set$capitalized_name$Value(other.get$capitalized_name$Value());\n"
300 "}\n");
301 } else {
302 GOOGLE_LOG(FATAL) << "Can't reach here.";
303 }
304 }
305
GenerateBuildingCode(io::Printer * printer) const306 void ImmutableEnumFieldGenerator::GenerateBuildingCode(
307 io::Printer* printer) const {
308 if (SupportFieldPresence(descriptor_)) {
309 printer->Print(variables_,
310 "if ($get_has_field_bit_from_local$) {\n"
311 " $set_has_field_bit_to_local$;\n"
312 "}\n");
313 }
314 printer->Print(variables_, "result.$name$_ = $name$_;\n");
315 }
316
GenerateParsingCode(io::Printer * printer) const317 void ImmutableEnumFieldGenerator::GenerateParsingCode(
318 io::Printer* printer) const {
319 if (SupportUnknownEnumValue(descriptor_->file())) {
320 printer->Print(variables_,
321 "int rawValue = input.readEnum();\n"
322 "$set_has_field_bit_message$\n"
323 "$name$_ = rawValue;\n");
324 } else {
325 printer->Print(variables_,
326 "int rawValue = input.readEnum();\n"
327 " @SuppressWarnings(\"deprecation\")\n"
328 "$type$ value = $type$.$for_number$(rawValue);\n"
329 "if (value == null) {\n"
330 " unknownFields.mergeVarintField($number$, rawValue);\n"
331 "} else {\n"
332 " $set_has_field_bit_message$\n"
333 " $name$_ = rawValue;\n"
334 "}\n");
335 }
336 }
337
GenerateParsingDoneCode(io::Printer * printer) const338 void ImmutableEnumFieldGenerator::GenerateParsingDoneCode(
339 io::Printer* printer) const {
340 // noop for enums
341 }
342
GenerateSerializationCode(io::Printer * printer) const343 void ImmutableEnumFieldGenerator::GenerateSerializationCode(
344 io::Printer* printer) const {
345 printer->Print(variables_,
346 "if ($is_field_present_message$) {\n"
347 " output.writeEnum($number$, $name$_);\n"
348 "}\n");
349 }
350
GenerateSerializedSizeCode(io::Printer * printer) const351 void ImmutableEnumFieldGenerator::GenerateSerializedSizeCode(
352 io::Printer* printer) const {
353 printer->Print(variables_,
354 "if ($is_field_present_message$) {\n"
355 " size += com.google.protobuf.CodedOutputStream\n"
356 " .computeEnumSize($number$, $name$_);\n"
357 "}\n");
358 }
359
GenerateEqualsCode(io::Printer * printer) const360 void ImmutableEnumFieldGenerator::GenerateEqualsCode(
361 io::Printer* printer) const {
362 printer->Print(variables_, "if ($name$_ != other.$name$_) return false;\n");
363 }
364
GenerateHashCode(io::Printer * printer) const365 void ImmutableEnumFieldGenerator::GenerateHashCode(io::Printer* printer) const {
366 printer->Print(variables_,
367 "hash = (37 * hash) + $constant_name$;\n"
368 "hash = (53 * hash) + $name$_;\n");
369 }
370
GetBoxedType() const371 std::string ImmutableEnumFieldGenerator::GetBoxedType() const {
372 return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
373 }
374
375 // ===================================================================
376
ImmutableEnumOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)377 ImmutableEnumOneofFieldGenerator::ImmutableEnumOneofFieldGenerator(
378 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
379 Context* context)
380 : ImmutableEnumFieldGenerator(descriptor, messageBitIndex, builderBitIndex,
381 context) {
382 const OneofGeneratorInfo* info =
383 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
384 SetCommonOneofVariables(descriptor, info, &variables_);
385 }
386
~ImmutableEnumOneofFieldGenerator()387 ImmutableEnumOneofFieldGenerator::~ImmutableEnumOneofFieldGenerator() {}
388
GenerateMembers(io::Printer * printer) const389 void ImmutableEnumOneofFieldGenerator::GenerateMembers(
390 io::Printer* printer) const {
391 PrintExtraFieldInfo(variables_, printer);
392 if (SupportFieldPresence(descriptor_)) {
393 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
394 printer->Print(
395 variables_,
396 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
397 " return $has_oneof_case_message$;\n"
398 "}\n");
399 printer->Annotate("{", "}", descriptor_);
400 }
401 if (SupportUnknownEnumValue(descriptor_->file())) {
402 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
403 printer->Print(
404 variables_,
405 "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
406 " if ($has_oneof_case_message$) {\n"
407 " return (java.lang.Integer) $oneof_name$_;\n"
408 " }\n"
409 " return $default_number$;\n"
410 "}\n");
411 printer->Annotate("{", "}", descriptor_);
412 }
413 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
414 printer->Print(variables_,
415 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
416 " if ($has_oneof_case_message$) {\n"
417 " @SuppressWarnings(\"deprecation\")\n"
418 " $type$ result = $type$.$for_number$(\n"
419 " (java.lang.Integer) $oneof_name$_);\n"
420 " return result == null ? $unknown$ : result;\n"
421 " }\n"
422 " return $default$;\n"
423 "}\n");
424 printer->Annotate("{", "}", descriptor_);
425 }
426
GenerateBuilderMembers(io::Printer * printer) const427 void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
428 io::Printer* printer) const {
429 if (SupportFieldPresence(descriptor_)) {
430 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
431 printer->Print(
432 variables_,
433 "@java.lang.Override\n"
434 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
435 " return $has_oneof_case_message$;\n"
436 "}\n");
437 printer->Annotate("{", "}", descriptor_);
438 }
439 if (SupportUnknownEnumValue(descriptor_->file())) {
440 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
441 printer->Print(
442 variables_,
443 "@java.lang.Override\n"
444 "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
445 " if ($has_oneof_case_message$) {\n"
446 " return ((java.lang.Integer) $oneof_name$_).intValue();\n"
447 " }\n"
448 " return $default_number$;\n"
449 "}\n");
450 printer->Annotate("{", "}", descriptor_);
451 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
452 /* builder */ true);
453 printer->Print(variables_,
454 "$deprecation$public Builder "
455 "${$set$capitalized_name$Value$}$(int value) {\n"
456 " $set_oneof_case_message$;\n"
457 " $oneof_name$_ = value;\n"
458 " $on_changed$\n"
459 " return this;\n"
460 "}\n");
461 printer->Annotate("{", "}", descriptor_);
462 }
463 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
464 printer->Print(variables_,
465 "@java.lang.Override\n"
466 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
467 " if ($has_oneof_case_message$) {\n"
468 " @SuppressWarnings(\"deprecation\")\n"
469 " $type$ result = $type$.$for_number$(\n"
470 " (java.lang.Integer) $oneof_name$_);\n"
471 " return result == null ? $unknown$ : result;\n"
472 " }\n"
473 " return $default$;\n"
474 "}\n");
475 printer->Annotate("{", "}", descriptor_);
476 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
477 /* builder */ true);
478 printer->Print(variables_,
479 "$deprecation$public Builder "
480 "${$set$capitalized_name$$}$($type$ value) {\n"
481 " if (value == null) {\n"
482 " throw new NullPointerException();\n"
483 " }\n"
484 " $set_oneof_case_message$;\n"
485 " $oneof_name$_ = value.getNumber();\n"
486 " $on_changed$\n"
487 " return this;\n"
488 "}\n");
489 printer->Annotate("{", "}", descriptor_);
490 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
491 /* builder */ true);
492 printer->Print(
493 variables_,
494 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
495 " if ($has_oneof_case_message$) {\n"
496 " $clear_oneof_case_message$;\n"
497 " $oneof_name$_ = null;\n"
498 " $on_changed$\n"
499 " }\n"
500 " return this;\n"
501 "}\n");
502 printer->Annotate("{", "}", descriptor_);
503 }
504
GenerateBuildingCode(io::Printer * printer) const505 void ImmutableEnumOneofFieldGenerator::GenerateBuildingCode(
506 io::Printer* printer) const {
507 printer->Print(variables_,
508 "if ($has_oneof_case_message$) {\n"
509 " result.$oneof_name$_ = $oneof_name$_;\n"
510 "}\n");
511 }
512
GenerateMergingCode(io::Printer * printer) const513 void ImmutableEnumOneofFieldGenerator::GenerateMergingCode(
514 io::Printer* printer) const {
515 if (SupportUnknownEnumValue(descriptor_->file())) {
516 printer->Print(
517 variables_,
518 "set$capitalized_name$Value(other.get$capitalized_name$Value());\n");
519 } else {
520 printer->Print(variables_,
521 "set$capitalized_name$(other.get$capitalized_name$());\n");
522 }
523 }
524
GenerateParsingCode(io::Printer * printer) const525 void ImmutableEnumOneofFieldGenerator::GenerateParsingCode(
526 io::Printer* printer) const {
527 if (SupportUnknownEnumValue(descriptor_->file())) {
528 printer->Print(variables_,
529 "int rawValue = input.readEnum();\n"
530 "$set_oneof_case_message$;\n"
531 "$oneof_name$_ = rawValue;\n");
532 } else {
533 printer->Print(variables_,
534 "int rawValue = input.readEnum();\n"
535 "@SuppressWarnings(\"deprecation\")\n"
536 "$type$ value = $type$.$for_number$(rawValue);\n"
537 "if (value == null) {\n"
538 " unknownFields.mergeVarintField($number$, rawValue);\n"
539 "} else {\n"
540 " $set_oneof_case_message$;\n"
541 " $oneof_name$_ = rawValue;\n"
542 "}\n");
543 }
544 }
545
GenerateSerializationCode(io::Printer * printer) const546 void ImmutableEnumOneofFieldGenerator::GenerateSerializationCode(
547 io::Printer* printer) const {
548 printer->Print(
549 variables_,
550 "if ($has_oneof_case_message$) {\n"
551 " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
552 "}\n");
553 }
554
GenerateSerializedSizeCode(io::Printer * printer) const555 void ImmutableEnumOneofFieldGenerator::GenerateSerializedSizeCode(
556 io::Printer* printer) const {
557 printer->Print(
558 variables_,
559 "if ($has_oneof_case_message$) {\n"
560 " size += com.google.protobuf.CodedOutputStream\n"
561 " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
562 "}\n");
563 }
564
GenerateEqualsCode(io::Printer * printer) const565 void ImmutableEnumOneofFieldGenerator::GenerateEqualsCode(
566 io::Printer* printer) const {
567 if (SupportUnknownEnumValue(descriptor_->file())) {
568 printer->Print(
569 variables_,
570 "if (get$capitalized_name$Value()\n"
571 " != other.get$capitalized_name$Value()) return false;\n");
572 } else {
573 printer->Print(
574 variables_,
575 "if (!get$capitalized_name$()\n"
576 " .equals(other.get$capitalized_name$())) return false;\n");
577 }
578 }
579
GenerateHashCode(io::Printer * printer) const580 void ImmutableEnumOneofFieldGenerator::GenerateHashCode(
581 io::Printer* printer) const {
582 if (SupportUnknownEnumValue(descriptor_->file())) {
583 printer->Print(variables_,
584 "hash = (37 * hash) + $constant_name$;\n"
585 "hash = (53 * hash) + get$capitalized_name$Value();\n");
586 } else {
587 printer->Print(
588 variables_,
589 "hash = (37 * hash) + $constant_name$;\n"
590 "hash = (53 * hash) + get$capitalized_name$().getNumber();\n");
591 }
592 }
593
594 // ===================================================================
595
RepeatedImmutableEnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)596 RepeatedImmutableEnumFieldGenerator::RepeatedImmutableEnumFieldGenerator(
597 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
598 Context* context)
599 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
600 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
601 context->GetFieldGeneratorInfo(descriptor), name_resolver_,
602 &variables_);
603 }
604
~RepeatedImmutableEnumFieldGenerator()605 RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {}
606
GetNumBitsForMessage() const607 int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
608 return 0;
609 }
610
GetNumBitsForBuilder() const611 int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
612 return 1;
613 }
614
GenerateInterfaceMembers(io::Printer * printer) const615 void RepeatedImmutableEnumFieldGenerator::GenerateInterfaceMembers(
616 io::Printer* printer) const {
617 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
618 printer->Print(
619 variables_,
620 "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
621 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
622 printer->Print(variables_,
623 "$deprecation$int get$capitalized_name$Count();\n");
624 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
625 printer->Print(variables_,
626 "$deprecation$$type$ get$capitalized_name$(int index);\n");
627 if (SupportUnknownEnumValue(descriptor_->file())) {
628 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
629 printer->Print(variables_,
630 "$deprecation$java.util.List<java.lang.Integer>\n"
631 "get$capitalized_name$ValueList();\n");
632 WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
633 LIST_INDEXED_GETTER);
634 printer->Print(variables_,
635 "$deprecation$int get$capitalized_name$Value(int index);\n");
636 }
637 }
638
GenerateMembers(io::Printer * printer) const639 void RepeatedImmutableEnumFieldGenerator::GenerateMembers(
640 io::Printer* printer) const {
641 printer->Print(
642 variables_,
643 "private java.util.List<java.lang.Integer> $name$_;\n"
644 "private static final "
645 "com.google.protobuf.Internal.ListAdapter.Converter<\n"
646 " java.lang.Integer, $type$> $name$_converter_ =\n"
647 " new com.google.protobuf.Internal.ListAdapter.Converter<\n"
648 " java.lang.Integer, $type$>() {\n"
649 " public $type$ convert(java.lang.Integer from) {\n"
650 " @SuppressWarnings(\"deprecation\")\n"
651 " $type$ result = $type$.$for_number$(from);\n"
652 " return result == null ? $unknown$ : result;\n"
653 " }\n"
654 " };\n");
655 PrintExtraFieldInfo(variables_, printer);
656 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
657 printer->Print(
658 variables_,
659 "@java.lang.Override\n"
660 "$deprecation$public java.util.List<$type$> "
661 "${$get$capitalized_name$List$}$() {\n"
662 " return new com.google.protobuf.Internal.ListAdapter<\n"
663 " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
664 "}\n");
665 printer->Annotate("{", "}", descriptor_);
666 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
667 printer->Print(
668 variables_,
669 "@java.lang.Override\n"
670 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
671 " return $name$_.size();\n"
672 "}\n");
673 printer->Annotate("{", "}", descriptor_);
674 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
675 printer->Print(
676 variables_,
677 "@java.lang.Override\n"
678 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
679 " return $name$_converter_.convert($name$_.get(index));\n"
680 "}\n");
681 printer->Annotate("{", "}", descriptor_);
682 if (SupportUnknownEnumValue(descriptor_->file())) {
683 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
684 printer->Print(variables_,
685 "@java.lang.Override\n"
686 "$deprecation$public java.util.List<java.lang.Integer>\n"
687 "${$get$capitalized_name$ValueList$}$() {\n"
688 " return $name$_;\n"
689 "}\n");
690 printer->Annotate("{", "}", descriptor_);
691 WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
692 LIST_INDEXED_GETTER);
693 printer->Print(variables_,
694 "@java.lang.Override\n"
695 "$deprecation$public int "
696 "${$get$capitalized_name$Value$}$(int index) {\n"
697 " return $name$_.get(index);\n"
698 "}\n");
699 printer->Annotate("{", "}", descriptor_);
700 }
701
702 if (descriptor_->is_packed()) {
703 printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n");
704 }
705 }
706
GenerateBuilderMembers(io::Printer * printer) const707 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers(
708 io::Printer* printer) const {
709 printer->Print(
710 variables_,
711 // One field is the list and the other field keeps track of whether the
712 // list is immutable. If it's immutable, the invariant is that it must
713 // either an instance of Collections.emptyList() or it's an ArrayList
714 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
715 // a refererence to the underlying ArrayList. This invariant allows us to
716 // share instances of lists between protocol buffers avoiding expensive
717 // memory allocations. Note, immutable is a strong guarantee here -- not
718 // just that the list cannot be modified via the reference but that the
719 // list can never be modified.
720 "private java.util.List<java.lang.Integer> $name$_ =\n"
721 " java.util.Collections.emptyList();\n"
722
723 "private void ensure$capitalized_name$IsMutable() {\n"
724 " if (!$get_mutable_bit_builder$) {\n"
725 " $name$_ = new java.util.ArrayList<java.lang.Integer>($name$_);\n"
726 " $set_mutable_bit_builder$;\n"
727 " }\n"
728 "}\n");
729
730 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
731 printer->Print(
732 variables_,
733 // Note: We return an unmodifiable list because otherwise the caller
734 // could hold on to the returned list and modify it after the message
735 // has been built, thus mutating the message which is supposed to be
736 // immutable.
737 "$deprecation$public java.util.List<$type$> "
738 "${$get$capitalized_name$List$}$() {\n"
739 " return new com.google.protobuf.Internal.ListAdapter<\n"
740 " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
741 "}\n");
742 printer->Annotate("{", "}", descriptor_);
743 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
744 printer->Print(
745 variables_,
746 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
747 " return $name$_.size();\n"
748 "}\n");
749 printer->Annotate("{", "}", descriptor_);
750 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
751 printer->Print(
752 variables_,
753 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
754 " return $name$_converter_.convert($name$_.get(index));\n"
755 "}\n");
756 printer->Annotate("{", "}", descriptor_);
757 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
758 /* builder */ true);
759 printer->Print(variables_,
760 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
761 " int index, $type$ value) {\n"
762 " if (value == null) {\n"
763 " throw new NullPointerException();\n"
764 " }\n"
765 " ensure$capitalized_name$IsMutable();\n"
766 " $name$_.set(index, value.getNumber());\n"
767 " $on_changed$\n"
768 " return this;\n"
769 "}\n");
770 printer->Annotate("{", "}", descriptor_);
771 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
772 /* builder */ true);
773 printer->Print(variables_,
774 "$deprecation$public Builder "
775 "${$add$capitalized_name$$}$($type$ value) {\n"
776 " if (value == null) {\n"
777 " throw new NullPointerException();\n"
778 " }\n"
779 " ensure$capitalized_name$IsMutable();\n"
780 " $name$_.add(value.getNumber());\n"
781 " $on_changed$\n"
782 " return this;\n"
783 "}\n");
784 printer->Annotate("{", "}", descriptor_);
785 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
786 /* builder */ true);
787 printer->Print(variables_,
788 "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
789 " java.lang.Iterable<? extends $type$> values) {\n"
790 " ensure$capitalized_name$IsMutable();\n"
791 " for ($type$ value : values) {\n"
792 " $name$_.add(value.getNumber());\n"
793 " }\n"
794 " $on_changed$\n"
795 " return this;\n"
796 "}\n");
797 printer->Annotate("{", "}", descriptor_);
798 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
799 /* builder */ true);
800 printer->Print(
801 variables_,
802 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
803 " $name$_ = java.util.Collections.emptyList();\n"
804 " $clear_mutable_bit_builder$;\n"
805 " $on_changed$\n"
806 " return this;\n"
807 "}\n");
808 printer->Annotate("{", "}", descriptor_);
809
810 if (SupportUnknownEnumValue(descriptor_->file())) {
811 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
812 printer->Print(variables_,
813 "$deprecation$public java.util.List<java.lang.Integer>\n"
814 "${$get$capitalized_name$ValueList$}$() {\n"
815 " return java.util.Collections.unmodifiableList($name$_);\n"
816 "}\n");
817 printer->Annotate("{", "}", descriptor_);
818 WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
819 LIST_INDEXED_GETTER);
820 printer->Print(variables_,
821 "$deprecation$public int "
822 "${$get$capitalized_name$Value$}$(int index) {\n"
823 " return $name$_.get(index);\n"
824 "}\n");
825 printer->Annotate("{", "}", descriptor_);
826 WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
827 LIST_INDEXED_GETTER,
828 /* builder */ true);
829 printer->Print(
830 variables_,
831 "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
832 " int index, int value) {\n"
833 " ensure$capitalized_name$IsMutable();\n"
834 " $name$_.set(index, value);\n"
835 " $on_changed$\n"
836 " return this;\n"
837 "}\n");
838 printer->Annotate("{", "}", descriptor_);
839 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER,
840 /* builder */ true);
841 printer->Print(variables_,
842 "$deprecation$public Builder "
843 "${$add$capitalized_name$Value$}$(int value) {\n"
844 " ensure$capitalized_name$IsMutable();\n"
845 " $name$_.add(value);\n"
846 " $on_changed$\n"
847 " return this;\n"
848 "}\n");
849 printer->Annotate("{", "}", descriptor_);
850 WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
851 LIST_MULTI_ADDER, /* builder */ true);
852 printer->Print(
853 variables_,
854 "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
855 " java.lang.Iterable<java.lang.Integer> values) {\n"
856 " ensure$capitalized_name$IsMutable();\n"
857 " for (int value : values) {\n"
858 " $name$_.add(value);\n"
859 " }\n"
860 " $on_changed$\n"
861 " return this;\n"
862 "}\n");
863 printer->Annotate("{", "}", descriptor_);
864 }
865 }
866
867 void RepeatedImmutableEnumFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const868 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
869 // noop for enums
870 }
871
GenerateInitializationCode(io::Printer * printer) const872 void RepeatedImmutableEnumFieldGenerator::GenerateInitializationCode(
873 io::Printer* printer) const {
874 printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
875 }
876
GenerateBuilderClearCode(io::Printer * printer) const877 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderClearCode(
878 io::Printer* printer) const {
879 printer->Print(variables_,
880 "$name$_ = java.util.Collections.emptyList();\n"
881 "$clear_mutable_bit_builder$;\n");
882 }
883
GenerateMergingCode(io::Printer * printer) const884 void RepeatedImmutableEnumFieldGenerator::GenerateMergingCode(
885 io::Printer* printer) const {
886 // The code below does two optimizations:
887 // 1. If the other list is empty, there's nothing to do. This ensures we
888 // don't allocate a new array if we already have an immutable one.
889 // 2. If the other list is non-empty and our current list is empty, we can
890 // reuse the other list which is guaranteed to be immutable.
891 printer->Print(variables_,
892 "if (!other.$name$_.isEmpty()) {\n"
893 " if ($name$_.isEmpty()) {\n"
894 " $name$_ = other.$name$_;\n"
895 " $clear_mutable_bit_builder$;\n"
896 " } else {\n"
897 " ensure$capitalized_name$IsMutable();\n"
898 " $name$_.addAll(other.$name$_);\n"
899 " }\n"
900 " $on_changed$\n"
901 "}\n");
902 }
903
GenerateBuildingCode(io::Printer * printer) const904 void RepeatedImmutableEnumFieldGenerator::GenerateBuildingCode(
905 io::Printer* printer) const {
906 // The code below ensures that the result has an immutable list. If our
907 // list is immutable, we can just reuse it. If not, we make it immutable.
908 printer->Print(
909 variables_,
910 "if ($get_mutable_bit_builder$) {\n"
911 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
912 " $clear_mutable_bit_builder$;\n"
913 "}\n"
914 "result.$name$_ = $name$_;\n");
915 }
916
GenerateParsingCode(io::Printer * printer) const917 void RepeatedImmutableEnumFieldGenerator::GenerateParsingCode(
918 io::Printer* printer) const {
919 // Read and store the enum
920 if (SupportUnknownEnumValue(descriptor_->file())) {
921 printer->Print(variables_,
922 "int rawValue = input.readEnum();\n"
923 "if (!$get_mutable_bit_parser$) {\n"
924 " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
925 " $set_mutable_bit_parser$;\n"
926 "}\n"
927 "$name$_.add(rawValue);\n");
928 } else {
929 printer->Print(
930 variables_,
931 "int rawValue = input.readEnum();\n"
932 "@SuppressWarnings(\"deprecation\")\n"
933 "$type$ value = $type$.$for_number$(rawValue);\n"
934 "if (value == null) {\n"
935 " unknownFields.mergeVarintField($number$, rawValue);\n"
936 "} else {\n"
937 " if (!$get_mutable_bit_parser$) {\n"
938 " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
939 " $set_mutable_bit_parser$;\n"
940 " }\n"
941 " $name$_.add(rawValue);\n"
942 "}\n");
943 }
944 }
945
GenerateParsingCodeFromPacked(io::Printer * printer) const946 void RepeatedImmutableEnumFieldGenerator::GenerateParsingCodeFromPacked(
947 io::Printer* printer) const {
948 // Wrap GenerateParsingCode's contents with a while loop.
949
950 printer->Print(variables_,
951 "int length = input.readRawVarint32();\n"
952 "int oldLimit = input.pushLimit(length);\n"
953 "while(input.getBytesUntilLimit() > 0) {\n");
954 printer->Indent();
955
956 GenerateParsingCode(printer);
957
958 printer->Outdent();
959 printer->Print(variables_,
960 "}\n"
961 "input.popLimit(oldLimit);\n");
962 }
963
GenerateParsingDoneCode(io::Printer * printer) const964 void RepeatedImmutableEnumFieldGenerator::GenerateParsingDoneCode(
965 io::Printer* printer) const {
966 printer->Print(
967 variables_,
968 "if ($get_mutable_bit_parser$) {\n"
969 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
970 "}\n");
971 }
972
GenerateSerializationCode(io::Printer * printer) const973 void RepeatedImmutableEnumFieldGenerator::GenerateSerializationCode(
974 io::Printer* printer) const {
975 if (descriptor_->is_packed()) {
976 printer->Print(variables_,
977 "if (get$capitalized_name$List().size() > 0) {\n"
978 " output.writeUInt32NoTag($tag$);\n"
979 " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
980 "}\n"
981 "for (int i = 0; i < $name$_.size(); i++) {\n"
982 " output.writeEnumNoTag($name$_.get(i));\n"
983 "}\n");
984 } else {
985 printer->Print(variables_,
986 "for (int i = 0; i < $name$_.size(); i++) {\n"
987 " output.writeEnum($number$, $name$_.get(i));\n"
988 "}\n");
989 }
990 }
991
GenerateSerializedSizeCode(io::Printer * printer) const992 void RepeatedImmutableEnumFieldGenerator::GenerateSerializedSizeCode(
993 io::Printer* printer) const {
994 printer->Print(variables_,
995 "{\n"
996 " int dataSize = 0;\n");
997 printer->Indent();
998
999 printer->Print(variables_,
1000 "for (int i = 0; i < $name$_.size(); i++) {\n"
1001 " dataSize += com.google.protobuf.CodedOutputStream\n"
1002 " .computeEnumSizeNoTag($name$_.get(i));\n"
1003 "}\n");
1004 printer->Print("size += dataSize;\n");
1005 if (descriptor_->is_packed()) {
1006 printer->Print(variables_,
1007 "if (!get$capitalized_name$List().isEmpty()) {"
1008 " size += $tag_size$;\n"
1009 " size += com.google.protobuf.CodedOutputStream\n"
1010 " .computeUInt32SizeNoTag(dataSize);\n"
1011 "}");
1012 } else {
1013 printer->Print(variables_, "size += $tag_size$ * $name$_.size();\n");
1014 }
1015
1016 // cache the data size for packed fields.
1017 if (descriptor_->is_packed()) {
1018 printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
1019 }
1020
1021 printer->Outdent();
1022 printer->Print("}\n");
1023 }
1024
GenerateEqualsCode(io::Printer * printer) const1025 void RepeatedImmutableEnumFieldGenerator::GenerateEqualsCode(
1026 io::Printer* printer) const {
1027 printer->Print(variables_,
1028 "if (!$name$_.equals(other.$name$_)) return false;\n");
1029 }
1030
GenerateHashCode(io::Printer * printer) const1031 void RepeatedImmutableEnumFieldGenerator::GenerateHashCode(
1032 io::Printer* printer) const {
1033 printer->Print(variables_,
1034 "if (get$capitalized_name$Count() > 0) {\n"
1035 " hash = (37 * hash) + $constant_name$;\n"
1036 " hash = (53 * hash) + $name$_.hashCode();\n"
1037 "}\n");
1038 }
1039
GetBoxedType() const1040 std::string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const {
1041 return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
1042 }
1043
1044 } // namespace java
1045 } // namespace compiler
1046 } // namespace protobuf
1047 } // namespace google
1048