• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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