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: [email protected] (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34
35 #include "google/protobuf/compiler/java/primitive_field.h"
36
37 #include <cstdint>
38 #include <map>
39 #include <string>
40
41 #include "google/protobuf/stubs/logging.h"
42 #include "google/protobuf/stubs/common.h"
43 #include "google/protobuf/io/printer.h"
44 #include "google/protobuf/wire_format.h"
45 #include "google/protobuf/stubs/strutil.h"
46 #include "google/protobuf/compiler/java/context.h"
47 #include "google/protobuf/compiler/java/doc_comment.h"
48 #include "google/protobuf/compiler/java/helpers.h"
49 #include "google/protobuf/compiler/java/name_resolver.h"
50
51 namespace google {
52 namespace protobuf {
53 namespace compiler {
54 namespace java {
55
56 using internal::WireFormat;
57
58 namespace {
59
SetPrimitiveVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,std::map<std::string,std::string> * variables,Context * context)60 void SetPrimitiveVariables(
61 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
62 const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
63 std::map<std::string, std::string>* variables,
64 Context* context) {
65 SetCommonFieldVariables(descriptor, info, variables);
66 JavaType javaType = GetJavaType(descriptor);
67
68 (*variables)["type"] = PrimitiveTypeName(javaType);
69 (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
70 (*variables)["kt_type"] = KotlinTypeName(javaType);
71 variables->insert({"field_type", (*variables)["type"]});
72
73 std::string name = (*variables)["name"];
74 if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE ||
75 javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT ||
76 javaType == JAVATYPE_LONG) {
77 std::string capitalized_type = UnderscoresToCamelCase(
78 PrimitiveTypeName(javaType), /*cap_first_letter=*/true);
79 (*variables)["field_list_type"] =
80 StrCat("com.google.protobuf.Internal.", capitalized_type, "List");
81 (*variables)["empty_list"] =
82 StrCat("empty", capitalized_type, "List()");
83 (*variables)["create_list"] =
84 StrCat("new", capitalized_type, "List()");
85 (*variables)["mutable_copy_list"] =
86 StrCat("mutableCopy(", name, "_)");
87 (*variables)["name_make_immutable"] =
88 StrCat(name, "_.makeImmutable()");
89 (*variables)["repeated_get"] =
90 StrCat(name, "_.get", capitalized_type);
91 (*variables)["repeated_add"] =
92 StrCat(name, "_.add", capitalized_type);
93 (*variables)["repeated_set"] =
94 StrCat(name, "_.set", capitalized_type);
95 } else {
96 std::string boxed_type = (*variables)["boxed_type"];
97 (*variables)["field_list_type"] =
98 StrCat("java.util.List<", boxed_type, ">");
99 (*variables)["create_list"] =
100 StrCat("new java.util.ArrayList<", boxed_type, ">()");
101 (*variables)["mutable_copy_list"] =
102 StrCat("new java.util.ArrayList<", boxed_type, ">(", name, "_)");
103 (*variables)["empty_list"] = "java.util.Collections.emptyList()";
104 (*variables)["name_make_immutable"] = StrCat(
105 name, "_ = java.util.Collections.unmodifiableList(", name, "_)");
106 (*variables)["repeated_get"] = StrCat(name, "_.get");
107 (*variables)["repeated_add"] = StrCat(name, "_.add");
108 (*variables)["repeated_set"] = StrCat(name, "_.set");
109 }
110
111 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
112 (*variables)["default_init"] =
113 IsDefaultValueJavaDefault(descriptor)
114 ? ""
115 : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
116 (*variables)["capitalized_type"] =
117 GetCapitalizedType(descriptor, /* immutable = */ true);
118 (*variables)["tag"] =
119 StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
120 (*variables)["tag_size"] = StrCat(
121 WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
122 if (IsReferenceType(GetJavaType(descriptor))) {
123 (*variables)["null_check"] =
124 "if (value == null) { throw new NullPointerException(); }";
125 } else {
126 (*variables)["null_check"] = "";
127 }
128 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
129 // by the proto compiler
130 (*variables)["deprecation"] =
131 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
132 (*variables)["kt_deprecation"] =
133 descriptor->options().deprecated()
134 ? StrCat("@kotlin.Deprecated(message = \"Field ", name,
135 " is deprecated\") ")
136 : "";
137 int fixed_size = FixedSize(GetType(descriptor));
138 if (fixed_size != -1) {
139 (*variables)["fixed_size"] = StrCat(fixed_size);
140 }
141 (*variables)["on_changed"] = "onChanged();";
142
143 if (HasHasbit(descriptor)) {
144 // For singular messages and builders, one bit is used for the hasField bit.
145 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
146 // Note that these have a trailing ";".
147 (*variables)["set_has_field_bit_to_local"] =
148 GenerateSetBitToLocal(messageBitIndex) + ";";
149 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
150 } else {
151 (*variables)["set_has_field_bit_to_local"] = "";
152 switch (descriptor->type()) {
153 case FieldDescriptor::TYPE_BYTES:
154 (*variables)["is_field_present_message"] =
155 StrCat("!", name, "_.isEmpty()");
156 break;
157 case FieldDescriptor::TYPE_FLOAT:
158 (*variables)["is_field_present_message"] =
159 StrCat("java.lang.Float.floatToRawIntBits(", name, "_) != 0");
160 break;
161 case FieldDescriptor::TYPE_DOUBLE:
162 (*variables)["is_field_present_message"] = StrCat(
163 "java.lang.Double.doubleToRawLongBits(", name, "_) != 0");
164 break;
165 default:
166 variables->insert(
167 {"is_field_present_message",
168 StrCat(name, "_ != ", (*variables)["default"])});
169 break;
170 }
171 }
172
173 // For repeated builders, one bit is used for whether the array is immutable.
174 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
175 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
176 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
177
178 // Always track the presence of a field explicitly in the builder, regardless
179 // of syntax.
180 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
181 (*variables)["get_has_field_bit_from_local"] =
182 GenerateGetBitFromLocal(builderBitIndex);
183 (*variables)["set_has_field_bit_builder"] =
184 GenerateSetBit(builderBitIndex) + ";";
185 (*variables)["clear_has_field_bit_builder"] =
186 GenerateClearBit(builderBitIndex) + ";";
187 }
188
189 } // namespace
190
191 // ===================================================================
192
ImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)193 ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator(
194 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
195 Context* context)
196 : descriptor_(descriptor),
197 message_bit_index_(messageBitIndex),
198 builder_bit_index_(builderBitIndex),
199 name_resolver_(context->GetNameResolver()) {
200 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
201 context->GetFieldGeneratorInfo(descriptor),
202 name_resolver_, &variables_, context);
203 }
204
~ImmutablePrimitiveFieldGenerator()205 ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
206
GetMessageBitIndex() const207 int ImmutablePrimitiveFieldGenerator::GetMessageBitIndex() const {
208 return message_bit_index_;
209 }
210
GetBuilderBitIndex() const211 int ImmutablePrimitiveFieldGenerator::GetBuilderBitIndex() const {
212 return builder_bit_index_;
213 }
214
GetNumBitsForMessage() const215 int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
216 return HasHasbit(descriptor_) ? 1 : 0;
217 }
218
GetNumBitsForBuilder() const219 int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { return 1; }
220
GenerateInterfaceMembers(io::Printer * printer) const221 void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
222 io::Printer* printer) const {
223 if (HasHazzer(descriptor_)) {
224 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
225 printer->Print(variables_,
226 "$deprecation$boolean has$capitalized_name$();\n");
227 }
228 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
229 printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
230 }
231
GenerateMembers(io::Printer * printer) const232 void ImmutablePrimitiveFieldGenerator::GenerateMembers(
233 io::Printer* printer) const {
234 printer->Print(variables_, "private $field_type$ $name$_ = $default$;\n");
235 PrintExtraFieldInfo(variables_, printer);
236 if (HasHazzer(descriptor_)) {
237 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
238 printer->Print(
239 variables_,
240 "@java.lang.Override\n"
241 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
242 " return $get_has_field_bit_message$;\n"
243 "}\n");
244 printer->Annotate("{", "}", descriptor_);
245 }
246
247 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
248 printer->Print(variables_,
249 "@java.lang.Override\n"
250 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
251 " return $name$_;\n"
252 "}\n");
253 printer->Annotate("{", "}", descriptor_);
254 }
255
GenerateBuilderMembers(io::Printer * printer) const256 void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
257 io::Printer* printer) const {
258 printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n");
259
260 if (HasHazzer(descriptor_)) {
261 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
262 printer->Print(
263 variables_,
264 "@java.lang.Override\n"
265 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
266 " return $get_has_field_bit_builder$;\n"
267 "}\n");
268 printer->Annotate("{", "}", descriptor_);
269 }
270
271 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
272 printer->Print(variables_,
273 "@java.lang.Override\n"
274 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
275 " return $name$_;\n"
276 "}\n");
277 printer->Annotate("{", "}", descriptor_);
278
279 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
280 /* builder */ true);
281 printer->Print(variables_,
282 "$deprecation$public Builder "
283 "${$set$capitalized_name$$}$($type$ value) {\n"
284 " $null_check$\n"
285 " $name$_ = value;\n"
286 " $set_has_field_bit_builder$\n"
287 " $on_changed$\n"
288 " return this;\n"
289 "}\n");
290 printer->Annotate("{", "}", descriptor_);
291
292 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
293 /* builder */ true);
294 printer->Print(
295 variables_,
296 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
297 " $clear_has_field_bit_builder$\n");
298 printer->Annotate("{", "}", descriptor_);
299 JavaType type = GetJavaType(descriptor_);
300 if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
301 // The default value is not a simple literal so we want to avoid executing
302 // it multiple times. Instead, get the default out of the default instance.
303 printer->Print(
304 variables_,
305 " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
306 } else {
307 printer->Print(variables_, " $name$_ = $default$;\n");
308 }
309 printer->Print(variables_,
310 " $on_changed$\n"
311 " return this;\n"
312 "}\n");
313 }
314
GenerateKotlinDslMembers(io::Printer * printer) const315 void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
316 io::Printer* printer) const {
317 WriteFieldDocComment(printer, descriptor_);
318 printer->Print(variables_,
319 "$kt_deprecation$public var $kt_name$: $kt_type$\n"
320 " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
321 " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
322 " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
323 " set(value) {\n"
324 " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
325 " }\n");
326
327 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
328 /* builder */ false);
329 printer->Print(variables_,
330 "public fun ${$clear$kt_capitalized_name$$}$() {\n"
331 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
332 "}\n");
333
334 if (HasHazzer(descriptor_)) {
335 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
336 printer->Print(
337 variables_,
338 "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
339 " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
340 "}\n");
341 }
342 }
343
GenerateFieldBuilderInitializationCode(io::Printer * printer) const344 void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode(
345 io::Printer* printer) const {
346 // noop for primitives
347 }
348
GenerateInitializationCode(io::Printer * printer) const349 void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
350 io::Printer* printer) const {
351 if (!IsDefaultValueJavaDefault(descriptor_)) {
352 printer->Print(variables_, "$name$_ = $default$;\n");
353 }
354 }
355
GenerateBuilderClearCode(io::Printer * printer) const356 void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
357 io::Printer* printer) const {
358 // No need to clear the has-bit since we clear the bitField ints all at once.
359 printer->Print(variables_, "$name$_ = $default$;\n");
360 }
361
GenerateMergingCode(io::Printer * printer) const362 void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
363 io::Printer* printer) const {
364 if (HasHazzer(descriptor_)) {
365 printer->Print(variables_,
366 "if (other.has$capitalized_name$()) {\n"
367 " set$capitalized_name$(other.get$capitalized_name$());\n"
368 "}\n");
369 } else {
370 printer->Print(variables_,
371 "if (other.get$capitalized_name$() != $default$) {\n"
372 " set$capitalized_name$(other.get$capitalized_name$());\n"
373 "}\n");
374 }
375 }
376
GenerateBuildingCode(io::Printer * printer) const377 void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
378 io::Printer* printer) const {
379 printer->Print(variables_,
380 "if ($get_has_field_bit_from_local$) {\n"
381 " result.$name$_ = $name$_;\n");
382 if (GetNumBitsForMessage() > 0) {
383 printer->Print(variables_, " $set_has_field_bit_to_local$\n");
384 }
385 printer->Print("}\n");
386 }
387
GenerateBuilderParsingCode(io::Printer * printer) const388 void ImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(
389 io::Printer* printer) const {
390 printer->Print(variables_,
391 "$name$_ = input.read$capitalized_type$();\n"
392 "$set_has_field_bit_builder$\n");
393 }
394
GenerateSerializationCode(io::Printer * printer) const395 void ImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
396 io::Printer* printer) const {
397 printer->Print(variables_,
398 "if ($is_field_present_message$) {\n"
399 " output.write$capitalized_type$($number$, $name$_);\n"
400 "}\n");
401 }
402
GenerateSerializedSizeCode(io::Printer * printer) const403 void ImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
404 io::Printer* printer) const {
405 printer->Print(variables_,
406 "if ($is_field_present_message$) {\n"
407 " size += com.google.protobuf.CodedOutputStream\n"
408 " .compute$capitalized_type$Size($number$, $name$_);\n"
409 "}\n");
410 }
411
GenerateEqualsCode(io::Printer * printer) const412 void ImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
413 io::Printer* printer) const {
414 switch (GetJavaType(descriptor_)) {
415 case JAVATYPE_INT:
416 case JAVATYPE_LONG:
417 case JAVATYPE_BOOLEAN:
418 printer->Print(variables_,
419 "if (get$capitalized_name$()\n"
420 " != other.get$capitalized_name$()) return false;\n");
421 break;
422
423 case JAVATYPE_FLOAT:
424 printer->Print(
425 variables_,
426 "if (java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
427 " != java.lang.Float.floatToIntBits(\n"
428 " other.get$capitalized_name$())) return false;\n");
429 break;
430
431 case JAVATYPE_DOUBLE:
432 printer->Print(
433 variables_,
434 "if (java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
435 " != java.lang.Double.doubleToLongBits(\n"
436 " other.get$capitalized_name$())) return false;\n");
437 break;
438
439 case JAVATYPE_STRING:
440 case JAVATYPE_BYTES:
441 printer->Print(
442 variables_,
443 "if (!get$capitalized_name$()\n"
444 " .equals(other.get$capitalized_name$())) return false;\n");
445 break;
446
447 case JAVATYPE_ENUM:
448 case JAVATYPE_MESSAGE:
449 default:
450 GOOGLE_LOG(FATAL) << "Can't get here.";
451 break;
452 }
453 }
454
GenerateHashCode(io::Printer * printer) const455 void ImmutablePrimitiveFieldGenerator::GenerateHashCode(
456 io::Printer* printer) const {
457 printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
458 switch (GetJavaType(descriptor_)) {
459 case JAVATYPE_INT:
460 printer->Print(variables_,
461 "hash = (53 * hash) + get$capitalized_name$();\n");
462 break;
463
464 case JAVATYPE_LONG:
465 printer->Print(
466 variables_,
467 "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
468 " get$capitalized_name$());\n");
469 break;
470
471 case JAVATYPE_BOOLEAN:
472 printer->Print(
473 variables_,
474 "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
475 " get$capitalized_name$());\n");
476 break;
477
478 case JAVATYPE_FLOAT:
479 printer->Print(variables_,
480 "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
481 " get$capitalized_name$());\n");
482 break;
483
484 case JAVATYPE_DOUBLE:
485 printer->Print(
486 variables_,
487 "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
488 " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
489 break;
490
491 case JAVATYPE_STRING:
492 case JAVATYPE_BYTES:
493 printer->Print(
494 variables_,
495 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
496 break;
497
498 case JAVATYPE_ENUM:
499 case JAVATYPE_MESSAGE:
500 default:
501 GOOGLE_LOG(FATAL) << "Can't get here.";
502 break;
503 }
504 }
505
GetBoxedType() const506 std::string ImmutablePrimitiveFieldGenerator::GetBoxedType() const {
507 return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
508 }
509
510 // ===================================================================
511
ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)512 ImmutablePrimitiveOneofFieldGenerator::ImmutablePrimitiveOneofFieldGenerator(
513 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
514 Context* context)
515 : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
516 builderBitIndex, context) {
517 const OneofGeneratorInfo* info =
518 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
519 SetCommonOneofVariables(descriptor, info, &variables_);
520 }
521
522 ImmutablePrimitiveOneofFieldGenerator::
~ImmutablePrimitiveOneofFieldGenerator()523 ~ImmutablePrimitiveOneofFieldGenerator() {}
524
GenerateMembers(io::Printer * printer) const525 void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
526 io::Printer* printer) const {
527 PrintExtraFieldInfo(variables_, printer);
528 GOOGLE_DCHECK(HasHazzer(descriptor_));
529 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
530 printer->Print(variables_,
531 "@java.lang.Override\n"
532 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
533 " return $has_oneof_case_message$;\n"
534 "}\n");
535 printer->Annotate("{", "}", descriptor_);
536
537 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
538 printer->Print(variables_,
539 "@java.lang.Override\n"
540 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
541 " if ($has_oneof_case_message$) {\n"
542 " return ($boxed_type$) $oneof_name$_;\n"
543 " }\n"
544 " return $default$;\n"
545 "}\n");
546 printer->Annotate("{", "}", descriptor_);
547 }
548
GenerateBuilderMembers(io::Printer * printer) const549 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
550 io::Printer* printer) const {
551 GOOGLE_DCHECK(HasHazzer(descriptor_));
552 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
553 printer->Print(variables_,
554 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
555 " return $has_oneof_case_message$;\n"
556 "}\n");
557 printer->Annotate("{", "}", descriptor_);
558
559 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
560 printer->Print(variables_,
561 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
562 " if ($has_oneof_case_message$) {\n"
563 " return ($boxed_type$) $oneof_name$_;\n"
564 " }\n"
565 " return $default$;\n"
566 "}\n");
567 printer->Annotate("{", "}", descriptor_);
568
569 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
570 /* builder */ true);
571 printer->Print(variables_,
572 "$deprecation$public Builder "
573 "${$set$capitalized_name$$}$($type$ value) {\n"
574 " $null_check$\n"
575 " $set_oneof_case_message$;\n"
576 " $oneof_name$_ = value;\n"
577 " $on_changed$\n"
578 " return this;\n"
579 "}\n");
580 printer->Annotate("{", "}", descriptor_);
581
582 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
583 /* builder */ true);
584 printer->Print(
585 variables_,
586 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
587 " if ($has_oneof_case_message$) {\n"
588 " $clear_oneof_case_message$;\n"
589 " $oneof_name$_ = null;\n"
590 " $on_changed$\n"
591 " }\n"
592 " return this;\n"
593 "}\n");
594 printer->Annotate("{", "}", descriptor_);
595 }
596
GenerateBuilderClearCode(io::Printer * printer) const597 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderClearCode(
598 io::Printer* printer) const {
599 // No-Op: When a primitive field is in a oneof, clearing the oneof clears that
600 // field.
601 }
602
GenerateBuildingCode(io::Printer * printer) const603 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode(
604 io::Printer* printer) const {
605 // no-op
606 }
607
GenerateMergingCode(io::Printer * printer) const608 void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode(
609 io::Printer* printer) const {
610 printer->Print(variables_,
611 "set$capitalized_name$(other.get$capitalized_name$());\n");
612 }
613
GenerateBuilderParsingCode(io::Printer * printer) const614 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderParsingCode(
615 io::Printer* printer) const {
616 printer->Print(variables_,
617 "$oneof_name$_ = input.read$capitalized_type$();\n"
618 "$set_oneof_case_message$;\n");
619 }
620
GenerateSerializationCode(io::Printer * printer) const621 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializationCode(
622 io::Printer* printer) const {
623 printer->Print(variables_,
624 "if ($has_oneof_case_message$) {\n"
625 " output.write$capitalized_type$(\n");
626 // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
627 // do redundant casts.
628 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
629 printer->Print(variables_, " $number$, ($type$) $oneof_name$_);\n");
630 } else {
631 printer->Print(
632 variables_,
633 " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
634 }
635 printer->Print("}\n");
636 }
637
GenerateSerializedSizeCode(io::Printer * printer) const638 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
639 io::Printer* printer) const {
640 printer->Print(variables_,
641 "if ($has_oneof_case_message$) {\n"
642 " size += com.google.protobuf.CodedOutputStream\n"
643 " .compute$capitalized_type$Size(\n");
644 // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
645 // do redundant casts.
646 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
647 printer->Print(variables_, " $number$, ($type$) $oneof_name$_);\n");
648 } else {
649 printer->Print(
650 variables_,
651 " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
652 }
653 printer->Print("}\n");
654 }
655
656 // ===================================================================
657
658 RepeatedImmutablePrimitiveFieldGenerator::
RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)659 RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
660 int messageBitIndex,
661 int builderBitIndex,
662 Context* context)
663 : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
664 builderBitIndex, context) {}
665
666 RepeatedImmutablePrimitiveFieldGenerator::
~RepeatedImmutablePrimitiveFieldGenerator()667 ~RepeatedImmutablePrimitiveFieldGenerator() {}
668
GetNumBitsForMessage() const669 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
670 return 0;
671 }
672
GetNumBitsForBuilder() const673 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
674 return 1;
675 }
676
GenerateInterfaceMembers(io::Printer * printer) const677 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
678 io::Printer* printer) const {
679 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
680 printer->Print(variables_,
681 "$deprecation$java.util.List<$boxed_type$> "
682 "get$capitalized_name$List();\n");
683 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
684 printer->Print(variables_,
685 "$deprecation$int get$capitalized_name$Count();\n");
686 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
687 printer->Print(variables_,
688 "$deprecation$$type$ get$capitalized_name$(int index);\n");
689 }
690
GenerateMembers(io::Printer * printer) const691 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers(
692 io::Printer* printer) const {
693 printer->Print(variables_, "@SuppressWarnings(\"serial\")\n"
694 "private $field_list_type$ $name$_;\n");
695 PrintExtraFieldInfo(variables_, printer);
696 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
697 printer->Print(variables_,
698 "@java.lang.Override\n"
699 "$deprecation$public java.util.List<$boxed_type$>\n"
700 " ${$get$capitalized_name$List$}$() {\n"
701 " return $name$_;\n" // note: unmodifiable list
702 "}\n");
703 printer->Annotate("{", "}", descriptor_);
704 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
705 printer->Print(
706 variables_,
707 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
708 " return $name$_.size();\n"
709 "}\n");
710 printer->Annotate("{", "}", descriptor_);
711 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
712 printer->Print(
713 variables_,
714 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
715 " return $repeated_get$(index);\n"
716 "}\n");
717 printer->Annotate("{", "}", descriptor_);
718
719 if (descriptor_->is_packed()) {
720 printer->Print(variables_,
721 "private int $name$MemoizedSerializedSize = -1;\n");
722 }
723 }
724
GenerateBuilderMembers(io::Printer * printer) const725 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
726 io::Printer* printer) const {
727 // One field is the list and the bit field keeps track of whether the
728 // list is immutable. If it's immutable, the invariant is that it must
729 // either an instance of Collections.emptyList() or it's an ArrayList
730 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
731 // a reference to the underlying ArrayList. This invariant allows us to
732 // share instances of lists between protocol buffers avoiding expensive
733 // memory allocations. Note, immutable is a strong guarantee here -- not
734 // just that the list cannot be modified via the reference but that the
735 // list can never be modified.
736 printer->Print(variables_,
737 "private $field_list_type$ $name$_ = $empty_list$;\n");
738
739 printer->Print(variables_,
740 "private void ensure$capitalized_name$IsMutable() {\n"
741 " if (!$get_mutable_bit_builder$) {\n"
742 " $name$_ = $mutable_copy_list$;\n"
743 " $set_mutable_bit_builder$;\n"
744 " }\n"
745 "}\n");
746
747 // Note: We return an unmodifiable list because otherwise the caller
748 // could hold on to the returned list and modify it after the message
749 // has been built, thus mutating the message which is supposed to be
750 // immutable.
751 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
752 printer->Print(
753 variables_,
754 "$deprecation$public java.util.List<$boxed_type$>\n"
755 " ${$get$capitalized_name$List$}$() {\n"
756 " return $get_mutable_bit_builder$ ?\n"
757 " java.util.Collections.unmodifiableList($name$_) : $name$_;\n"
758 "}\n");
759 printer->Annotate("{", "}", descriptor_);
760 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
761 printer->Print(
762 variables_,
763 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
764 " return $name$_.size();\n"
765 "}\n");
766 printer->Annotate("{", "}", descriptor_);
767 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
768 printer->Print(
769 variables_,
770 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
771 " return $repeated_get$(index);\n"
772 "}\n");
773 printer->Annotate("{", "}", descriptor_);
774 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
775 /* builder */ true);
776 printer->Print(variables_,
777 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
778 " int index, $type$ value) {\n"
779 " $null_check$\n"
780 " ensure$capitalized_name$IsMutable();\n"
781 " $repeated_set$(index, value);\n"
782 " $on_changed$\n"
783 " return this;\n"
784 "}\n");
785 printer->Annotate("{", "}", descriptor_);
786 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
787 /* builder */ true);
788 printer->Print(variables_,
789 "$deprecation$public Builder "
790 "${$add$capitalized_name$$}$($type$ value) {\n"
791 " $null_check$\n"
792 " ensure$capitalized_name$IsMutable();\n"
793 " $repeated_add$(value);\n"
794 " $on_changed$\n"
795 " return this;\n"
796 "}\n");
797 printer->Annotate("{", "}", descriptor_);
798 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
799 /* builder */ true);
800 printer->Print(variables_,
801 "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
802 " java.lang.Iterable<? extends $boxed_type$> values) {\n"
803 " ensure$capitalized_name$IsMutable();\n"
804 " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
805 " values, $name$_);\n"
806 " $on_changed$\n"
807 " return this;\n"
808 "}\n");
809 printer->Annotate("{", "}", descriptor_);
810 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
811 /* builder */ true);
812 printer->Print(
813 variables_,
814 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
815 " $name$_ = $empty_list$;\n"
816 " $clear_mutable_bit_builder$;\n"
817 " $on_changed$\n"
818 " return this;\n"
819 "}\n");
820 printer->Annotate("{", "}", descriptor_);
821 }
822
GenerateKotlinDslMembers(io::Printer * printer) const823 void RepeatedImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
824 io::Printer* printer) const {
825 printer->Print(
826 variables_,
827 "/**\n"
828 " * An uninstantiable, behaviorless type to represent the field in\n"
829 " * generics.\n"
830 " */\n"
831 "@kotlin.OptIn"
832 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
833 "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
834 " : com.google.protobuf.kotlin.DslProxy()\n");
835
836 WriteFieldDocComment(printer, descriptor_);
837 printer->Print(variables_,
838 "$kt_deprecation$ public val $kt_name$: "
839 "com.google.protobuf.kotlin.DslList"
840 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
841 " @kotlin.jvm.JvmSynthetic\n"
842 " get() = com.google.protobuf.kotlin.DslList(\n"
843 " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
844 " )\n");
845
846 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
847 /* builder */ false);
848 printer->Print(variables_,
849 "@kotlin.jvm.JvmSynthetic\n"
850 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
851 "public fun com.google.protobuf.kotlin.DslList"
852 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
853 "add(value: $kt_type$) {\n"
854 " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
855 "}");
856
857 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
858 /* builder */ false);
859 printer->Print(variables_,
860 "@kotlin.jvm.JvmSynthetic\n"
861 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
862 "@Suppress(\"NOTHING_TO_INLINE\")\n"
863 "public inline operator fun com.google.protobuf.kotlin.DslList"
864 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
865 "plusAssign(value: $kt_type$) {\n"
866 " add(value)\n"
867 "}");
868
869 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
870 /* builder */ false);
871 printer->Print(variables_,
872 "@kotlin.jvm.JvmSynthetic\n"
873 "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
874 "public fun com.google.protobuf.kotlin.DslList"
875 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
876 "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
877 " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
878 "}");
879
880 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
881 /* builder */ false);
882 printer->Print(
883 variables_,
884 "@kotlin.jvm.JvmSynthetic\n"
885 "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
886 "@Suppress(\"NOTHING_TO_INLINE\")\n"
887 "public inline operator fun com.google.protobuf.kotlin.DslList"
888 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
889 "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
890 " addAll(values)\n"
891 "}");
892
893 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
894 /* builder */ false);
895 printer->Print(
896 variables_,
897 "@kotlin.jvm.JvmSynthetic\n"
898 "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
899 "public operator fun com.google.protobuf.kotlin.DslList"
900 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
901 "set(index: kotlin.Int, value: $kt_type$) {\n"
902 " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
903 "}");
904
905 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
906 /* builder */ false);
907 printer->Print(variables_,
908 "@kotlin.jvm.JvmSynthetic\n"
909 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
910 "public fun com.google.protobuf.kotlin.DslList"
911 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
912 "clear() {\n"
913 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
914 "}");
915 }
916
917 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const918 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
919 // noop for primitives
920 }
921
GenerateInitializationCode(io::Printer * printer) const922 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
923 io::Printer* printer) const {
924 printer->Print(variables_, "$name$_ = $empty_list$;\n");
925 }
926
GenerateBuilderClearCode(io::Printer * printer) const927 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
928 io::Printer* printer) const {
929 printer->Print(variables_, "$name$_ = $empty_list$;\n");
930 }
931
GenerateMergingCode(io::Printer * printer) const932 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode(
933 io::Printer* printer) const {
934 // The code below does two optimizations:
935 // 1. If the other list is empty, there's nothing to do. This ensures we
936 // don't allocate a new array if we already have an immutable one.
937 // 2. If the other list is non-empty and our current list is empty, we can
938 // reuse the other list which is guaranteed to be immutable.
939 printer->Print(variables_,
940 "if (!other.$name$_.isEmpty()) {\n"
941 " if ($name$_.isEmpty()) {\n"
942 " $name$_ = other.$name$_;\n"
943 " $clear_mutable_bit_builder$;\n"
944 " } else {\n"
945 " ensure$capitalized_name$IsMutable();\n"
946 " $name$_.addAll(other.$name$_);\n"
947 " }\n"
948 " $on_changed$\n"
949 "}\n");
950 }
951
GenerateBuildingCode(io::Printer * printer) const952 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
953 io::Printer* printer) const {
954 // The code below ensures that the result has an immutable list. If our
955 // list is immutable, we can just reuse it. If not, we make it immutable.
956 printer->Print(variables_,
957 "if ($get_mutable_bit_builder$) {\n"
958 " $name_make_immutable$;\n"
959 " $clear_mutable_bit_builder$;\n"
960 "}\n"
961 "result.$name$_ = $name$_;\n");
962 }
963
GenerateBuilderParsingCode(io::Printer * printer) const964 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(
965 io::Printer* printer) const {
966 printer->Print(variables_,
967 "$type$ v = input.read$capitalized_type$();\n"
968 "ensure$capitalized_name$IsMutable();\n"
969 "$repeated_add$(v);\n");
970 }
971
972 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateBuilderParsingCodeFromPacked(io::Printer * printer) const973 GenerateBuilderParsingCodeFromPacked(io::Printer* printer) const {
974 printer->Print(variables_,
975 "int length = input.readRawVarint32();\n"
976 "int limit = input.pushLimit(length);\n"
977 "ensure$capitalized_name$IsMutable();\n"
978 "while (input.getBytesUntilLimit() > 0) {\n"
979 " $repeated_add$(input.read$capitalized_type$());\n"
980 "}\n"
981 "input.popLimit(limit);\n");
982 }
983
GenerateSerializationCode(io::Printer * printer) const984 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
985 io::Printer* printer) const {
986 if (descriptor_->is_packed()) {
987 // We invoke getSerializedSize in writeTo for messages that have packed
988 // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
989 // That makes it safe to rely on the memoized size here.
990 printer->Print(variables_,
991 "if (get$capitalized_name$List().size() > 0) {\n"
992 " output.writeUInt32NoTag($tag$);\n"
993 " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
994 "}\n"
995 "for (int i = 0; i < $name$_.size(); i++) {\n"
996 " output.write$capitalized_type$NoTag($repeated_get$(i));\n"
997 "}\n");
998 } else {
999 printer->Print(
1000 variables_,
1001 "for (int i = 0; i < $name$_.size(); i++) {\n"
1002 " output.write$capitalized_type$($number$, $repeated_get$(i));\n"
1003 "}\n");
1004 }
1005 }
1006
GenerateSerializedSizeCode(io::Printer * printer) const1007 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
1008 io::Printer* printer) const {
1009 printer->Print(variables_,
1010 "{\n"
1011 " int dataSize = 0;\n");
1012 printer->Indent();
1013
1014 if (FixedSize(GetType(descriptor_)) == -1) {
1015 printer->Print(
1016 variables_,
1017 "for (int i = 0; i < $name$_.size(); i++) {\n"
1018 " dataSize += com.google.protobuf.CodedOutputStream\n"
1019 " .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n"
1020 "}\n");
1021 } else {
1022 printer->Print(
1023 variables_,
1024 "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
1025 }
1026
1027 printer->Print("size += dataSize;\n");
1028
1029 if (descriptor_->is_packed()) {
1030 printer->Print(variables_,
1031 "if (!get$capitalized_name$List().isEmpty()) {\n"
1032 " size += $tag_size$;\n"
1033 " size += com.google.protobuf.CodedOutputStream\n"
1034 " .computeInt32SizeNoTag(dataSize);\n"
1035 "}\n");
1036 } else {
1037 printer->Print(
1038 variables_,
1039 "size += $tag_size$ * get$capitalized_name$List().size();\n");
1040 }
1041
1042 // cache the data size for packed fields.
1043 if (descriptor_->is_packed()) {
1044 printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
1045 }
1046
1047 printer->Outdent();
1048 printer->Print("}\n");
1049 }
1050
GenerateEqualsCode(io::Printer * printer) const1051 void RepeatedImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
1052 io::Printer* printer) const {
1053 printer->Print(
1054 variables_,
1055 "if (!get$capitalized_name$List()\n"
1056 " .equals(other.get$capitalized_name$List())) return false;\n");
1057 }
1058
GenerateHashCode(io::Printer * printer) const1059 void RepeatedImmutablePrimitiveFieldGenerator::GenerateHashCode(
1060 io::Printer* printer) const {
1061 printer->Print(
1062 variables_,
1063 "if (get$capitalized_name$Count() > 0) {\n"
1064 " hash = (37 * hash) + $constant_name$;\n"
1065 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
1066 "}\n");
1067 }
1068
GetBoxedType() const1069 std::string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const {
1070 return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
1071 }
1072
1073 } // namespace java
1074 } // namespace compiler
1075 } // namespace protobuf
1076 } // namespace google
1077