• 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,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