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 <algorithm>
36 #include <google/protobuf/stubs/hash.h>
37 #include <google/protobuf/compiler/javanano/javanano_message.h>
38 #include <google/protobuf/compiler/javanano/javanano_enum.h>
39 #include <google/protobuf/compiler/javanano/javanano_extension.h>
40 #include <google/protobuf/compiler/javanano/javanano_helpers.h>
41 #include <google/protobuf/stubs/strutil.h>
42 #include <google/protobuf/io/printer.h>
43 #include <google/protobuf/io/coded_stream.h>
44 #include <google/protobuf/wire_format.h>
45 #include <google/protobuf/descriptor.pb.h>
46
47 namespace google {
48 namespace protobuf {
49 namespace compiler {
50 namespace javanano {
51
52 using internal::WireFormat;
53 using internal::WireFormatLite;
54
55 namespace {
56
57 struct FieldOrderingByNumber {
operator ()google::protobuf::compiler::javanano::__anon0aed76a10111::FieldOrderingByNumber58 inline bool operator()(const FieldDescriptor* a,
59 const FieldDescriptor* b) const {
60 return a->number() < b->number();
61 }
62 };
63
64 // Sort the fields of the given Descriptor by number into a new[]'d array
65 // and return it.
SortFieldsByNumber(const Descriptor * descriptor)66 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
67 const FieldDescriptor** fields =
68 new const FieldDescriptor*[descriptor->field_count()];
69 for (int i = 0; i < descriptor->field_count(); i++) {
70 fields[i] = descriptor->field(i);
71 }
72 sort(fields, fields + descriptor->field_count(),
73 FieldOrderingByNumber());
74 return fields;
75 }
76
77 } // namespace
78
79 // ===================================================================
80
MessageGenerator(const Descriptor * descriptor,const Params & params)81 MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Params& params)
82 : params_(params),
83 descriptor_(descriptor),
84 field_generators_(descriptor, params) {
85 }
86
~MessageGenerator()87 MessageGenerator::~MessageGenerator() {}
88
GenerateStaticVariables(io::Printer * printer)89 void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
90 // Generate static members for all nested types.
91 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
92 // TODO(kenton): Reuse MessageGenerator objects?
93 if (IsMapEntry(descriptor_->nested_type(i))) continue;
94 MessageGenerator(descriptor_->nested_type(i), params_)
95 .GenerateStaticVariables(printer);
96 }
97 }
98
GenerateStaticVariableInitializers(io::Printer * printer)99 void MessageGenerator::GenerateStaticVariableInitializers(
100 io::Printer* printer) {
101 // Generate static member initializers for all nested types.
102 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
103 // TODO(kenton): Reuse MessageGenerator objects?
104 if (IsMapEntry(descriptor_->nested_type(i))) continue;
105 MessageGenerator(descriptor_->nested_type(i), params_)
106 .GenerateStaticVariableInitializers(printer);
107 }
108 }
109
Generate(io::Printer * printer)110 void MessageGenerator::Generate(io::Printer* printer) {
111 if (!params_.store_unknown_fields() &&
112 (descriptor_->extension_count() != 0 || descriptor_->extension_range_count() != 0)) {
113 GOOGLE_LOG(FATAL) << "Extensions are only supported in NANO_RUNTIME if the "
114 "'store_unknown_fields' generator option is 'true'\n";
115 }
116
117 const string& file_name = descriptor_->file()->name();
118 bool is_own_file =
119 params_.java_multiple_files(file_name)
120 && descriptor_->containing_type() == NULL;
121
122 if (is_own_file) {
123 // Note: constants (from enums and fields requiring stored defaults, emitted in the loop below)
124 // may have the same names as constants in the nested classes. This causes Java warnings, but
125 // is not fatal, so we suppress those warnings here in the top-most class declaration.
126 printer->Print(
127 "\n"
128 "@SuppressWarnings(\"hiding\")\n"
129 "public final class $classname$ extends\n",
130 "classname", descriptor_->name());
131 } else {
132 printer->Print(
133 "\n"
134 "public static final class $classname$ extends\n",
135 "classname", descriptor_->name());
136 }
137 if (params_.store_unknown_fields() && params_.parcelable_messages()) {
138 printer->Print(
139 " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>",
140 "classname", descriptor_->name());
141 } else if (params_.store_unknown_fields()) {
142 printer->Print(
143 " com.google.protobuf.nano.ExtendableMessageNano<$classname$>",
144 "classname", descriptor_->name());
145 } else if (params_.parcelable_messages()) {
146 printer->Print(
147 " com.google.protobuf.nano.android.ParcelableMessageNano");
148 } else {
149 printer->Print(
150 " com.google.protobuf.nano.MessageNano");
151 }
152 if (params_.generate_clone()) {
153 printer->Print(" implements java.lang.Cloneable {\n");
154 } else {
155 printer->Print(" {\n");
156 }
157 printer->Indent();
158
159 if (params_.parcelable_messages()) {
160 printer->Print(
161 "\n"
162 "// Used by Parcelable\n"
163 "@SuppressWarnings({\"unused\"})\n"
164 "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n"
165 " new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n"
166 " $classname$>($classname$.class);\n",
167 "classname", descriptor_->name());
168 }
169
170 // Nested types and extensions
171 for (int i = 0; i < descriptor_->extension_count(); i++) {
172 ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
173 }
174
175 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
176 EnumGenerator(descriptor_->enum_type(i), params_).Generate(printer);
177 }
178
179 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
180 if (IsMapEntry(descriptor_->nested_type(i))) continue;
181 MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
182 }
183
184 // oneof
185 map<string, string> vars;
186 vars["message_name"] = descriptor_->name();
187 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
188 const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
189 vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc);
190 vars["oneof_capitalized_name"] =
191 UnderscoresToCapitalizedCamelCase(oneof_desc);
192 vars["oneof_index"] = SimpleItoa(oneof_desc->index());
193 // Oneof Constants
194 for (int j = 0; j < oneof_desc->field_count(); j++) {
195 const FieldDescriptor* field = oneof_desc->field(j);
196 vars["number"] = SimpleItoa(field->number());
197 vars["cap_field_name"] = ToUpper(field->name());
198 printer->Print(vars,
199 "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n");
200 }
201 // oneofCase_ and oneof_
202 printer->Print(vars,
203 "private int $oneof_name$Case_ = 0;\n"
204 "private java.lang.Object $oneof_name$_;\n");
205 printer->Print(vars,
206 "public int get$oneof_capitalized_name$Case() {\n"
207 " return this.$oneof_name$Case_;\n"
208 "}\n");
209 // Oneof clear
210 printer->Print(vars,
211 "public $message_name$ clear$oneof_capitalized_name$() {\n"
212 " this.$oneof_name$Case_ = 0;\n"
213 " this.$oneof_name$_ = null;\n"
214 " return this;\n"
215 "}\n");
216 }
217
218 // Lazy initialization of otherwise static final fields can help prevent the
219 // class initializer from being generated. We want to prevent it because it
220 // stops ProGuard from inlining any methods in this class into call sites and
221 // therefore reducing the method count. However, extensions are best kept as
222 // public static final fields with initializers, so with their existence we
223 // won't bother with lazy initialization.
224 bool lazy_init = descriptor_->extension_count() == 0;
225
226 // Empty array
227 if (lazy_init) {
228 printer->Print(
229 "\n"
230 "private static volatile $classname$[] _emptyArray;\n"
231 "public static $classname$[] emptyArray() {\n"
232 " // Lazily initializes the empty array\n"
233 " if (_emptyArray == null) {\n"
234 " synchronized (\n"
235 " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
236 " if (_emptyArray == null) {\n"
237 " _emptyArray = new $classname$[0];\n"
238 " }\n"
239 " }\n"
240 " }\n"
241 " return _emptyArray;\n"
242 "}\n",
243 "classname", descriptor_->name());
244 } else {
245 printer->Print(
246 "\n"
247 "private static final $classname$[] EMPTY_ARRAY = {};\n"
248 "public static $classname$[] emptyArray() {\n"
249 " return EMPTY_ARRAY;\n"
250 "}\n",
251 "classname", descriptor_->name());
252 }
253
254 // Integers for bit fields
255 int totalInts = (field_generators_.total_bits() + 31) / 32;
256 if (totalInts > 0) {
257 printer->Print("\n");
258 for (int i = 0; i < totalInts; i++) {
259 printer->Print("private int $bit_field_name$;\n",
260 "bit_field_name", GetBitFieldName(i));
261 }
262 }
263
264 // Fields and maybe their default values
265 for (int i = 0; i < descriptor_->field_count(); i++) {
266 printer->Print("\n");
267 PrintFieldComment(printer, descriptor_->field(i));
268 field_generators_.get(descriptor_->field(i)).GenerateMembers(
269 printer, lazy_init);
270 }
271
272 // Constructor, with lazy init code if needed
273 if (lazy_init && field_generators_.saved_defaults_needed()) {
274 printer->Print(
275 "\n"
276 "private static volatile boolean _classInitialized;\n"
277 "\n"
278 "public $classname$() {\n"
279 " // Lazily initializes the field defaults\n"
280 " if (!_classInitialized) {\n"
281 " synchronized (\n"
282 " com.google.protobuf.nano.InternalNano.LAZY_INIT_LOCK) {\n"
283 " if (!_classInitialized) {\n",
284 "classname", descriptor_->name());
285 printer->Indent();
286 printer->Indent();
287 printer->Indent();
288 printer->Indent();
289 for (int i = 0; i < descriptor_->field_count(); i++) {
290 field_generators_.get(descriptor_->field(i))
291 .GenerateInitSavedDefaultCode(printer);
292 }
293 printer->Outdent();
294 printer->Outdent();
295 printer->Outdent();
296 printer->Outdent();
297 printer->Print(
298 " _classInitialized = true;\n"
299 " }\n"
300 " }\n"
301 " }\n");
302 if (params_.generate_clear()) {
303 printer->Print(" clear();\n");
304 }
305 printer->Print("}\n");
306 } else {
307 printer->Print(
308 "\n"
309 "public $classname$() {\n",
310 "classname", descriptor_->name());
311 if (params_.generate_clear()) {
312 printer->Print(" clear();\n");
313 } else {
314 printer->Indent();
315 GenerateFieldInitializers(printer);
316 printer->Outdent();
317 }
318 printer->Print("}\n");
319 }
320
321 // Other methods in this class
322
323 GenerateClear(printer);
324
325 if (params_.generate_clone()) {
326 GenerateClone(printer);
327 }
328
329 if (params_.generate_equals()) {
330 GenerateEquals(printer);
331 GenerateHashCode(printer);
332 }
333
334 GenerateMessageSerializationMethods(printer);
335 GenerateMergeFromMethods(printer);
336 GenerateParseFromMethods(printer);
337
338 printer->Outdent();
339 printer->Print("}\n");
340 }
341
342 // ===================================================================
343
344 void MessageGenerator::
GenerateMessageSerializationMethods(io::Printer * printer)345 GenerateMessageSerializationMethods(io::Printer* printer) {
346 // Rely on the parent implementations of writeTo() and getSerializedSize()
347 // if there are no fields to serialize in this message.
348 if (descriptor_->field_count() == 0) {
349 return;
350 }
351
352 scoped_array<const FieldDescriptor*> sorted_fields(
353 SortFieldsByNumber(descriptor_));
354
355 printer->Print(
356 "\n"
357 "@Override\n"
358 "public void writeTo(com.google.protobuf.nano.CodedOutputByteBufferNano output)\n"
359 " throws java.io.IOException {\n");
360 printer->Indent();
361
362 // Output the fields in sorted order
363 for (int i = 0; i < descriptor_->field_count(); i++) {
364 GenerateSerializeOneField(printer, sorted_fields[i]);
365 }
366
367 // The parent implementation will write any unknown fields if necessary.
368 printer->Print(
369 "super.writeTo(output);\n");
370
371 printer->Outdent();
372 printer->Print("}\n");
373
374 // The parent implementation will get the serialized size for unknown
375 // fields if necessary.
376 printer->Print(
377 "\n"
378 "@Override\n"
379 "protected int computeSerializedSize() {\n"
380 " int size = super.computeSerializedSize();\n");
381 printer->Indent();
382
383 for (int i = 0; i < descriptor_->field_count(); i++) {
384 field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
385 }
386
387 printer->Outdent();
388 printer->Print(
389 " return size;\n"
390 "}\n");
391 }
392
GenerateMergeFromMethods(io::Printer * printer)393 void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
394 scoped_array<const FieldDescriptor*> sorted_fields(
395 SortFieldsByNumber(descriptor_));
396
397 printer->Print(
398 "\n"
399 "@Override\n"
400 "public $classname$ mergeFrom(\n"
401 " com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
402 " throws java.io.IOException {\n",
403 "classname", descriptor_->name());
404
405 printer->Indent();
406 if (HasMapField(descriptor_)) {
407 printer->Print(
408 "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n"
409 " com.google.protobuf.nano.MapFactories.getMapFactory();\n");
410 }
411
412 printer->Print(
413 "while (true) {\n");
414 printer->Indent();
415
416 printer->Print(
417 "int tag = input.readTag();\n"
418 "switch (tag) {\n");
419 printer->Indent();
420
421 printer->Print(
422 "case 0:\n" // zero signals EOF / limit reached
423 " return this;\n"
424 "default: {\n");
425
426 printer->Indent();
427 if (params_.store_unknown_fields()) {
428 printer->Print(
429 "if (!storeUnknownField(input, tag)) {\n"
430 " return this;\n"
431 "}\n");
432 } else {
433 printer->Print(
434 "if (!com.google.protobuf.nano.WireFormatNano.parseUnknownField(input, tag)) {\n"
435 " return this;\n" // it's an endgroup tag
436 "}\n");
437 }
438 printer->Print("break;\n");
439 printer->Outdent();
440 printer->Print("}\n");
441
442 for (int i = 0; i < descriptor_->field_count(); i++) {
443 const FieldDescriptor* field = sorted_fields[i];
444 uint32 tag = WireFormatLite::MakeTag(field->number(),
445 WireFormat::WireTypeForFieldType(field->type()));
446
447 printer->Print(
448 "case $tag$: {\n",
449 "tag", SimpleItoa(tag));
450 printer->Indent();
451
452 field_generators_.get(field).GenerateMergingCode(printer);
453
454 printer->Outdent();
455 printer->Print(
456 " break;\n"
457 "}\n");
458
459 if (field->is_packable()) {
460 // To make packed = true wire compatible, we generate parsing code from a
461 // packed version of this field regardless of field->options().packed().
462 uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
463 WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
464 printer->Print(
465 "case $tag$: {\n",
466 "tag", SimpleItoa(packed_tag));
467 printer->Indent();
468
469 field_generators_.get(field).GenerateMergingCodeFromPacked(printer);
470
471 printer->Outdent();
472 printer->Print(
473 " break;\n"
474 "}\n");
475 }
476 }
477
478 printer->Outdent();
479 printer->Outdent();
480 printer->Outdent();
481 printer->Print(
482 " }\n" // switch (tag)
483 " }\n" // while (true)
484 "}\n");
485 }
486
487 void MessageGenerator::
GenerateParseFromMethods(io::Printer * printer)488 GenerateParseFromMethods(io::Printer* printer) {
489 // Note: These are separate from GenerateMessageSerializationMethods()
490 // because they need to be generated even for messages that are optimized
491 // for code size.
492 printer->Print(
493 "\n"
494 "public static $classname$ parseFrom(byte[] data)\n"
495 " throws com.google.protobuf.nano.InvalidProtocolBufferNanoException {\n"
496 " return com.google.protobuf.nano.MessageNano.mergeFrom(new $classname$(), data);\n"
497 "}\n"
498 "\n"
499 "public static $classname$ parseFrom(\n"
500 " com.google.protobuf.nano.CodedInputByteBufferNano input)\n"
501 " throws java.io.IOException {\n"
502 " return new $classname$().mergeFrom(input);\n"
503 "}\n",
504 "classname", descriptor_->name());
505 }
506
GenerateSerializeOneField(io::Printer * printer,const FieldDescriptor * field)507 void MessageGenerator::GenerateSerializeOneField(
508 io::Printer* printer, const FieldDescriptor* field) {
509 field_generators_.get(field).GenerateSerializationCode(printer);
510 }
511
GenerateClear(io::Printer * printer)512 void MessageGenerator::GenerateClear(io::Printer* printer) {
513 if (!params_.generate_clear()) {
514 return;
515 }
516 printer->Print(
517 "\n"
518 "public $classname$ clear() {\n",
519 "classname", descriptor_->name());
520 printer->Indent();
521
522 GenerateFieldInitializers(printer);
523
524 printer->Outdent();
525 printer->Print(
526 " return this;\n"
527 "}\n");
528 }
529
GenerateFieldInitializers(io::Printer * printer)530 void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) {
531 // Clear bit fields.
532 int totalInts = (field_generators_.total_bits() + 31) / 32;
533 for (int i = 0; i < totalInts; i++) {
534 printer->Print("$bit_field_name$ = 0;\n",
535 "bit_field_name", GetBitFieldName(i));
536 }
537
538 // Call clear for all of the fields.
539 for (int i = 0; i < descriptor_->field_count(); i++) {
540 const FieldDescriptor* field = descriptor_->field(i);
541 field_generators_.get(field).GenerateClearCode(printer);
542 }
543
544 // Clear oneofs.
545 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
546 printer->Print(
547 "clear$oneof_capitalized_name$();\n",
548 "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase(
549 descriptor_->oneof_decl(i)));
550 }
551
552 // Clear unknown fields.
553 if (params_.store_unknown_fields()) {
554 printer->Print("unknownFieldData = null;\n");
555 }
556 printer->Print("cachedSize = -1;\n");
557 }
558
GenerateClone(io::Printer * printer)559 void MessageGenerator::GenerateClone(io::Printer* printer) {
560 printer->Print(
561 "@Override\n"
562 "public $classname$ clone() {\n",
563 "classname", descriptor_->name());
564 printer->Indent();
565
566 printer->Print(
567 "$classname$ cloned;\n"
568 "try {\n"
569 " cloned = ($classname$) super.clone();\n"
570 "} catch (java.lang.CloneNotSupportedException e) {\n"
571 " throw new java.lang.AssertionError(e);\n"
572 "}\n",
573 "classname", descriptor_->name());
574
575 for (int i = 0; i < descriptor_->field_count(); i++) {
576 field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer);
577 }
578
579 printer->Outdent();
580 printer->Print(
581 " return cloned;\n"
582 "}\n"
583 "\n");
584 }
585
GenerateEquals(io::Printer * printer)586 void MessageGenerator::GenerateEquals(io::Printer* printer) {
587 // Don't override if there are no fields. We could generate an
588 // equals method that compares types, but often empty messages
589 // are used as namespaces.
590 if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
591 return;
592 }
593
594 printer->Print(
595 "\n"
596 "@Override\n"
597 "public boolean equals(Object o) {\n");
598 printer->Indent();
599 printer->Print(
600 "if (o == this) {\n"
601 " return true;\n"
602 "}\n"
603 "if (!(o instanceof $classname$)) {\n"
604 " return false;\n"
605 "}\n"
606 "$classname$ other = ($classname$) o;\n",
607 "classname", descriptor_->name());
608
609 // Checking oneof case before checking each oneof field.
610 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
611 const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
612 printer->Print(
613 "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n"
614 " return false;\n"
615 "}\n",
616 "oneof_name", UnderscoresToCamelCase(oneof_desc));
617 }
618
619 for (int i = 0; i < descriptor_->field_count(); i++) {
620 const FieldDescriptor* field = descriptor_->field(i);
621 field_generators_.get(field).GenerateEqualsCode(printer);
622 }
623
624 if (params_.store_unknown_fields()) {
625 printer->Print(
626 "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n"
627 " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n"
628 "} else {\n"
629 " return unknownFieldData.equals(other.unknownFieldData);\n"
630 "}");
631 } else {
632 printer->Print(
633 "return true;\n");
634 }
635
636 printer->Outdent();
637 printer->Print("}\n");
638 }
639
GenerateHashCode(io::Printer * printer)640 void MessageGenerator::GenerateHashCode(io::Printer* printer) {
641 if (descriptor_->field_count() == 0 && !params_.store_unknown_fields()) {
642 return;
643 }
644
645 printer->Print(
646 "\n"
647 "@Override\n"
648 "public int hashCode() {\n");
649 printer->Indent();
650
651 printer->Print("int result = 17;\n");
652 printer->Print("result = 31 * result + getClass().getName().hashCode();\n");
653 for (int i = 0; i < descriptor_->field_count(); i++) {
654 const FieldDescriptor* field = descriptor_->field(i);
655 field_generators_.get(field).GenerateHashCodeCode(printer);
656 }
657
658 if (params_.store_unknown_fields()) {
659 printer->Print(
660 "result = 31 * result + \n"
661 " (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n"
662 " unknownFieldData.hashCode());\n");
663 }
664
665 printer->Print("return result;\n");
666
667 printer->Outdent();
668 printer->Print("}\n");
669 }
670
671 // ===================================================================
672
673 } // namespace javanano
674 } // namespace compiler
675 } // namespace protobuf
676 } // namespace google
677