- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / protobuf / src / google / protobuf / compiler / java / java_enum_field.cc
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // http://code.google.com/p/protobuf/
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/compiler/java/java_enum_field.h>
39 #include <google/protobuf/compiler/java/java_doc_comment.h>
40 #include <google/protobuf/stubs/common.h>
41 #include <google/protobuf/compiler/java/java_helpers.h>
42 #include <google/protobuf/io/printer.h>
43 #include <google/protobuf/wire_format.h>
44 #include <google/protobuf/stubs/strutil.h>
45
46 namespace google {
47 namespace protobuf {
48 namespace compiler {
49 namespace java {
50
51 namespace {
52
53 // TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
54 //   repeat code between this and the other field types.
55 void SetEnumVariables(const FieldDescriptor* descriptor,
56                       int messageBitIndex,
57                       int builderBitIndex,
58                       map<string, string>* variables) {
59   (*variables)["name"] =
60     UnderscoresToCamelCase(descriptor);
61   (*variables)["capitalized_name"] =
62     UnderscoresToCapitalizedCamelCase(descriptor);
63   (*variables)["constant_name"] = FieldConstantName(descriptor);
64   (*variables)["number"] = SimpleItoa(descriptor->number());
65   (*variables)["type"] = ClassName(descriptor->enum_type());
66   (*variables)["default"] = DefaultValue(descriptor);
67   (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
68   (*variables)["tag_size"] = SimpleItoa(
69       internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
70   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
71   // by the proto compiler
72   (*variables)["deprecation"] = descriptor->options().deprecated()
73       ? "@java.lang.Deprecated " : "";
74   (*variables)["on_changed"] =
75       HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
76
77   // For singular messages and builders, one bit is used for the hasField bit.
78   (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
79   (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
80
81   (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
82   (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
83   (*variables)["clear_has_field_bit_builder"] =
84       GenerateClearBit(builderBitIndex);
85
86   // For repated builders, one bit is used for whether the array is immutable.
87   (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
88   (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
89   (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
90
91   // For repeated fields, one bit is used for whether the array is immutable
92   // in the parsing constructor.
93   (*variables)["get_mutable_bit_parser"] =
94       GenerateGetBitMutableLocal(builderBitIndex);
95   (*variables)["set_mutable_bit_parser"] =
96       GenerateSetBitMutableLocal(builderBitIndex);
97
98   (*variables)["get_has_field_bit_from_local"] =
99       GenerateGetBitFromLocal(builderBitIndex);
100   (*variables)["set_has_field_bit_to_local"] =
101       GenerateSetBitToLocal(messageBitIndex);
102 }
103
104 }  // namespace
105
106 // ===================================================================
107
108 EnumFieldGenerator::
109 EnumFieldGenerator(const FieldDescriptor* descriptor,
110                       int messageBitIndex,
111                       int builderBitIndex)
112   : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
113     builderBitIndex_(builderBitIndex) {
114   SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
115 }
116
117 EnumFieldGenerator::~EnumFieldGenerator() {}
118
119 int EnumFieldGenerator::GetNumBitsForMessage() const {
120   return 1;
121 }
122
123 int EnumFieldGenerator::GetNumBitsForBuilder() const {
124   return 1;
125 }
126
127 void EnumFieldGenerator::
128 GenerateInterfaceMembers(io::Printer* printer) const {
129   WriteFieldDocComment(printer, descriptor_);
130   printer->Print(variables_,
131     "$deprecation$boolean has$capitalized_name$();\n");
132   WriteFieldDocComment(printer, descriptor_);
133   printer->Print(variables_,
134     "$deprecation$$type$ get$capitalized_name$();\n");
135 }
136
137 void EnumFieldGenerator::
138 GenerateMembers(io::Printer* printer) const {
139   printer->Print(variables_,
140     "private $type$ $name$_;\n");
141   WriteFieldDocComment(printer, descriptor_);
142   printer->Print(variables_,
143     "$deprecation$public boolean has$capitalized_name$() {\n"
144     "  return $get_has_field_bit_message$;\n"
145     "}\n");
146   WriteFieldDocComment(printer, descriptor_);
147   printer->Print(variables_,
148     "$deprecation$public $type$ get$capitalized_name$() {\n"
149     "  return $name$_;\n"
150     "}\n");
151 }
152
153 void EnumFieldGenerator::
154 GenerateBuilderMembers(io::Printer* printer) const {
155   printer->Print(variables_,
156     "private $type$ $name$_ = $default$;\n");
157   WriteFieldDocComment(printer, descriptor_);
158   printer->Print(variables_,
159     "$deprecation$public boolean has$capitalized_name$() {\n"
160     "  return $get_has_field_bit_builder$;\n"
161     "}\n");
162   WriteFieldDocComment(printer, descriptor_);
163   printer->Print(variables_,
164     "$deprecation$public $type$ get$capitalized_name$() {\n"
165     "  return $name$_;\n"
166     "}\n");
167   WriteFieldDocComment(printer, descriptor_);
168   printer->Print(variables_,
169     "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
170     "  if (value == null) {\n"
171     "    throw new NullPointerException();\n"
172     "  }\n"
173     "  $set_has_field_bit_builder$;\n"
174     "  $name$_ = value;\n"
175     "  $on_changed$\n"
176     "  return this;\n"
177     "}\n");
178   WriteFieldDocComment(printer, descriptor_);
179   printer->Print(variables_,
180     "$deprecation$public Builder clear$capitalized_name$() {\n"
181     "  $clear_has_field_bit_builder$;\n"
182     "  $name$_ = $default$;\n"
183     "  $on_changed$\n"
184     "  return this;\n"
185     "}\n");
186 }
187
188 void EnumFieldGenerator::
189 GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
190   // noop for enums
191 }
192
193 void EnumFieldGenerator::
194 GenerateInitializationCode(io::Printer* printer) const {
195   printer->Print(variables_, "$name$_ = $default$;\n");
196 }
197
198 void EnumFieldGenerator::
199 GenerateBuilderClearCode(io::Printer* printer) const {
200   printer->Print(variables_,
201       "$name$_ = $default$;\n"
202       "$clear_has_field_bit_builder$;\n");
203 }
204
205 void EnumFieldGenerator::
206 GenerateMergingCode(io::Printer* printer) const {
207   printer->Print(variables_,
208     "if (other.has$capitalized_name$()) {\n"
209     "  set$capitalized_name$(other.get$capitalized_name$());\n"
210     "}\n");
211 }
212
213 void EnumFieldGenerator::
214 GenerateBuildingCode(io::Printer* printer) const {
215   printer->Print(variables_,
216     "if ($get_has_field_bit_from_local$) {\n"
217     "  $set_has_field_bit_to_local$;\n"
218     "}\n"
219     "result.$name$_ = $name$_;\n");
220 }
221
222 void EnumFieldGenerator::
223 GenerateParsingCode(io::Printer* printer) const {
224   printer->Print(variables_,
225     "int rawValue = input.readEnum();\n"
226     "$type$ value = $type$.valueOf(rawValue);\n");
227   if (HasUnknownFields(descriptor_->containing_type())) {
228     printer->Print(variables_,
229       "if (value == null) {\n"
230       "  unknownFields.mergeVarintField($number$, rawValue);\n"
231       "} else {\n");
232   } else {
233     printer->Print(variables_,
234       "if (value != null) {\n");
235   }
236   printer->Print(variables_,
237     "  $set_has_field_bit_message$;\n"
238     "  $name$_ = value;\n"
239     "}\n");
240 }
241
242 void EnumFieldGenerator::
243 GenerateParsingDoneCode(io::Printer* printer) const {
244   // noop for enums
245 }
246
247 void EnumFieldGenerator::
248 GenerateSerializationCode(io::Printer* printer) const {
249   printer->Print(variables_,
250     "if ($get_has_field_bit_message$) {\n"
251     "  output.writeEnum($number$, $name$_.getNumber());\n"
252     "}\n");
253 }
254
255 void EnumFieldGenerator::
256 GenerateSerializedSizeCode(io::Printer* printer) const {
257   printer->Print(variables_,
258     "if ($get_has_field_bit_message$) {\n"
259     "  size += com.google.protobuf.CodedOutputStream\n"
260     "    .computeEnumSize($number$, $name$_.getNumber());\n"
261     "}\n");
262 }
263
264 void EnumFieldGenerator::
265 GenerateEqualsCode(io::Printer* printer) const {
266   printer->Print(variables_,
267     "result = result &&\n"
268     "    (get$capitalized_name$() == other.get$capitalized_name$());\n");
269 }
270
271 void EnumFieldGenerator::
272 GenerateHashCode(io::Printer* printer) const {
273   printer->Print(variables_,
274     "hash = (37 * hash) + $constant_name$;\n"
275     "hash = (53 * hash) + hashEnum(get$capitalized_name$());\n");
276 }
277
278 string EnumFieldGenerator::GetBoxedType() const {
279   return ClassName(descriptor_->enum_type());
280 }
281
282 // ===================================================================
283
284 RepeatedEnumFieldGenerator::
285 RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
286                            int messageBitIndex,
287                            int builderBitIndex)
288   : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
289     builderBitIndex_(builderBitIndex) {
290   SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
291 }
292
293 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
294
295 int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const {
296   return 0;
297 }
298
299 int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const {
300   return 1;
301 }
302
303 void RepeatedEnumFieldGenerator::
304 GenerateInterfaceMembers(io::Printer* printer) const {
305   WriteFieldDocComment(printer, descriptor_);
306   printer->Print(variables_,
307     "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
308   WriteFieldDocComment(printer, descriptor_);
309   printer->Print(variables_,
310     "$deprecation$int get$capitalized_name$Count();\n");
311   WriteFieldDocComment(printer, descriptor_);
312   printer->Print(variables_,
313     "$deprecation$$type$ get$capitalized_name$(int index);\n");
314 }
315
316 void RepeatedEnumFieldGenerator::
317 GenerateMembers(io::Printer* printer) const {
318   printer->Print(variables_,
319     "private java.util.List<$type$> $name$_;\n");
320   WriteFieldDocComment(printer, descriptor_);
321   printer->Print(variables_,
322     "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
323     "  return $name$_;\n"   // note:  unmodifiable list
324     "}\n");
325   WriteFieldDocComment(printer, descriptor_);
326   printer->Print(variables_,
327     "$deprecation$public int get$capitalized_name$Count() {\n"
328     "  return $name$_.size();\n"
329     "}\n");
330   WriteFieldDocComment(printer, descriptor_);
331   printer->Print(variables_,
332     "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
333     "  return $name$_.get(index);\n"
334     "}\n");
335
336   if (descriptor_->options().packed() &&
337       HasGeneratedMethods(descriptor_->containing_type())) {
338     printer->Print(variables_,
339       "private int $name$MemoizedSerializedSize;\n");
340   }
341 }
342
343 void RepeatedEnumFieldGenerator::
344 GenerateBuilderMembers(io::Printer* printer) const {
345   printer->Print(variables_,
346     // One field is the list and the other field keeps track of whether the
347     // list is immutable. If it's immutable, the invariant is that it must
348     // either an instance of Collections.emptyList() or it's an ArrayList
349     // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
350     // a refererence to the underlying ArrayList. This invariant allows us to
351     // share instances of lists between protocol buffers avoiding expensive
352     // memory allocations. Note, immutable is a strong guarantee here -- not
353     // just that the list cannot be modified via the reference but that the
354     // list can never be modified.
355     "private java.util.List<$type$> $name$_ =\n"
356     "  java.util.Collections.emptyList();\n"
357
358     "private void ensure$capitalized_name$IsMutable() {\n"
359     "  if (!$get_mutable_bit_builder$) {\n"
360     "    $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
361     "    $set_mutable_bit_builder$;\n"
362     "  }\n"
363     "}\n");
364
365   WriteFieldDocComment(printer, descriptor_);
366   printer->Print(variables_,
367     // Note:  We return an unmodifiable list because otherwise the caller
368     //   could hold on to the returned list and modify it after the message
369     //   has been built, thus mutating the message which is supposed to be
370     //   immutable.
371     "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
372     "  return java.util.Collections.unmodifiableList($name$_);\n"
373     "}\n");
374   WriteFieldDocComment(printer, descriptor_);
375   printer->Print(variables_,
376     "$deprecation$public int get$capitalized_name$Count() {\n"
377     "  return $name$_.size();\n"
378     "}\n");
379   WriteFieldDocComment(printer, descriptor_);
380   printer->Print(variables_,
381     "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
382     "  return $name$_.get(index);\n"
383     "}\n");
384   WriteFieldDocComment(printer, descriptor_);
385   printer->Print(variables_,
386     "$deprecation$public Builder set$capitalized_name$(\n"
387     "    int index, $type$ value) {\n"
388     "  if (value == null) {\n"
389     "    throw new NullPointerException();\n"
390     "  }\n"
391     "  ensure$capitalized_name$IsMutable();\n"
392     "  $name$_.set(index, value);\n"
393     "  $on_changed$\n"
394     "  return this;\n"
395     "}\n");
396   WriteFieldDocComment(printer, descriptor_);
397   printer->Print(variables_,
398     "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
399     "  if (value == null) {\n"
400     "    throw new NullPointerException();\n"
401     "  }\n"
402     "  ensure$capitalized_name$IsMutable();\n"
403     "  $name$_.add(value);\n"
404     "  $on_changed$\n"
405     "  return this;\n"
406     "}\n");
407   WriteFieldDocComment(printer, descriptor_);
408   printer->Print(variables_,
409     "$deprecation$public Builder addAll$capitalized_name$(\n"
410     "    java.lang.Iterable<? extends $type$> values) {\n"
411     "  ensure$capitalized_name$IsMutable();\n"
412     "  super.addAll(values, $name$_);\n"
413     "  $on_changed$\n"
414     "  return this;\n"
415     "}\n");
416   WriteFieldDocComment(printer, descriptor_);
417   printer->Print(variables_,
418     "$deprecation$public Builder clear$capitalized_name$() {\n"
419     "  $name$_ = java.util.Collections.emptyList();\n"
420     "  $clear_mutable_bit_builder$;\n"
421     "  $on_changed$\n"
422     "  return this;\n"
423     "}\n");
424 }
425
426 void RepeatedEnumFieldGenerator::
427 GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
428   // noop for enums
429 }
430
431 void RepeatedEnumFieldGenerator::
432 GenerateInitializationCode(io::Printer* printer) const {
433   printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
434 }
435
436 void RepeatedEnumFieldGenerator::
437 GenerateBuilderClearCode(io::Printer* printer) const {
438   printer->Print(variables_,
439     "$name$_ = java.util.Collections.emptyList();\n"
440     "$clear_mutable_bit_builder$;\n");
441 }
442
443 void RepeatedEnumFieldGenerator::
444 GenerateMergingCode(io::Printer* printer) const {
445   // The code below does two optimizations:
446   //   1. If the other list is empty, there's nothing to do. This ensures we
447   //      don't allocate a new array if we already have an immutable one.
448   //   2. If the other list is non-empty and our current list is empty, we can
449   //      reuse the other list which is guaranteed to be immutable.
450   printer->Print(variables_,
451     "if (!other.$name$_.isEmpty()) {\n"
452     "  if ($name$_.isEmpty()) {\n"
453     "    $name$_ = other.$name$_;\n"
454     "    $clear_mutable_bit_builder$;\n"
455     "  } else {\n"
456     "    ensure$capitalized_name$IsMutable();\n"
457     "    $name$_.addAll(other.$name$_);\n"
458     "  }\n"
459     "  $on_changed$\n"
460     "}\n");
461 }
462
463 void RepeatedEnumFieldGenerator::
464 GenerateBuildingCode(io::Printer* printer) const {
465   // The code below ensures that the result has an immutable list. If our
466   // list is immutable, we can just reuse it. If not, we make it immutable.
467   printer->Print(variables_,
468     "if ($get_mutable_bit_builder$) {\n"
469     "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
470     "  $clear_mutable_bit_builder$;\n"
471     "}\n"
472     "result.$name$_ = $name$_;\n");
473 }
474
475 void RepeatedEnumFieldGenerator::
476 GenerateParsingCode(io::Printer* printer) const {
477   // Read and store the enum
478   printer->Print(variables_,
479     "int rawValue = input.readEnum();\n"
480     "$type$ value = $type$.valueOf(rawValue);\n");
481   if (HasUnknownFields(descriptor_->containing_type())) {
482     printer->Print(variables_,
483       "if (value == null) {\n"
484       "  unknownFields.mergeVarintField($number$, rawValue);\n"
485       "} else {\n");
486   } else {
487     printer->Print(variables_,
488       "if (value != null) {\n");
489   }
490   printer->Print(variables_,
491     "  if (!$get_mutable_bit_parser$) {\n"
492     "    $name$_ = new java.util.ArrayList<$type$>();\n"
493     "    $set_mutable_bit_parser$;\n"
494     "  }\n"
495     "  $name$_.add(value);\n"
496     "}\n");
497 }
498
499 void RepeatedEnumFieldGenerator::
500 GenerateParsingCodeFromPacked(io::Printer* printer) const {
501   // Wrap GenerateParsingCode's contents with a while loop.
502
503   printer->Print(variables_,
504     "int length = input.readRawVarint32();\n"
505     "int oldLimit = input.pushLimit(length);\n"
506     "while(input.getBytesUntilLimit() > 0) {\n");
507   printer->Indent();
508
509   GenerateParsingCode(printer);
510
511   printer->Outdent();
512   printer->Print(variables_,
513     "}\n"
514     "input.popLimit(oldLimit);\n");
515 }
516
517 void RepeatedEnumFieldGenerator::
518 GenerateParsingDoneCode(io::Printer* printer) const {
519   printer->Print(variables_,
520     "if ($get_mutable_bit_parser$) {\n"
521     "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
522     "}\n");
523 }
524
525 void RepeatedEnumFieldGenerator::
526 GenerateSerializationCode(io::Printer* printer) const {
527   if (descriptor_->options().packed()) {
528     printer->Print(variables_,
529       "if (get$capitalized_name$List().size() > 0) {\n"
530       "  output.writeRawVarint32($tag$);\n"
531       "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
532       "}\n"
533       "for (int i = 0; i < $name$_.size(); i++) {\n"
534       "  output.writeEnumNoTag($name$_.get(i).getNumber());\n"
535       "}\n");
536   } else {
537     printer->Print(variables_,
538       "for (int i = 0; i < $name$_.size(); i++) {\n"
539       "  output.writeEnum($number$, $name$_.get(i).getNumber());\n"
540       "}\n");
541   }
542 }
543
544 void RepeatedEnumFieldGenerator::
545 GenerateSerializedSizeCode(io::Printer* printer) const {
546   printer->Print(variables_,
547     "{\n"
548     "  int dataSize = 0;\n");
549   printer->Indent();
550
551   printer->Print(variables_,
552     "for (int i = 0; i < $name$_.size(); i++) {\n"
553     "  dataSize += com.google.protobuf.CodedOutputStream\n"
554     "    .computeEnumSizeNoTag($name$_.get(i).getNumber());\n"
555     "}\n");
556   printer->Print(
557     "size += dataSize;\n");
558   if (descriptor_->options().packed()) {
559     printer->Print(variables_,
560       "if (!get$capitalized_name$List().isEmpty()) {"
561       "  size += $tag_size$;\n"
562       "  size += com.google.protobuf.CodedOutputStream\n"
563       "    .computeRawVarint32Size(dataSize);\n"
564       "}");
565   } else {
566     printer->Print(variables_,
567       "size += $tag_size$ * $name$_.size();\n");
568   }
569
570   // cache the data size for packed fields.
571   if (descriptor_->options().packed()) {
572     printer->Print(variables_,
573       "$name$MemoizedSerializedSize = dataSize;\n");
574   }
575
576   printer->Outdent();
577   printer->Print("}\n");
578 }
579
580 void RepeatedEnumFieldGenerator::
581 GenerateEqualsCode(io::Printer* printer) const {
582   printer->Print(variables_,
583     "result = result && get$capitalized_name$List()\n"
584     "    .equals(other.get$capitalized_name$List());\n");
585 }
586
587 void RepeatedEnumFieldGenerator::
588 GenerateHashCode(io::Printer* printer) const {
589   printer->Print(variables_,
590     "if (get$capitalized_name$Count() > 0) {\n"
591     "  hash = (37 * hash) + $constant_name$;\n"
592     "  hash = (53 * hash) + hashEnumList(get$capitalized_name$List());\n"
593     "}\n");
594 }
595
596 string RepeatedEnumFieldGenerator::GetBoxedType() const {
597   return ClassName(descriptor_->enum_type());
598 }
599
600 }  // namespace java
601 }  // namespace compiler
602 }  // namespace protobuf
603 }  // namespace google