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_helpers.h>
43 #include <google/protobuf/compiler/java/java_name_resolver.h>
44 #include <google/protobuf/compiler/java/java_primitive_field.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 using internal::WireFormat;
55 using internal::WireFormatLite;
56
57 namespace {
58
SetPrimitiveVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,std::map<std::string,std::string> * variables)59 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
60 int messageBitIndex, int builderBitIndex,
61 const FieldGeneratorInfo* info,
62 ClassNameResolver* name_resolver,
63 std::map<std::string, std::string>* variables) {
64 SetCommonFieldVariables(descriptor, info, variables);
65 JavaType javaType = GetJavaType(descriptor);
66
67 (*variables)["type"] = PrimitiveTypeName(javaType);
68 (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType);
69 (*variables)["field_type"] = (*variables)["type"];
70
71 if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE ||
72 javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT ||
73 javaType == JAVATYPE_LONG) {
74 std::string capitalized_type = UnderscoresToCamelCase(
75 PrimitiveTypeName(javaType), /*cap_first_letter=*/true);
76 (*variables)["field_list_type"] =
77 "com.google.protobuf.Internal." + capitalized_type + "List";
78 (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
79 (*variables)["create_list"] = "new" + capitalized_type + "List()";
80 (*variables)["mutable_copy_list"] =
81 "mutableCopy(" + (*variables)["name"] + "_)";
82 (*variables)["name_make_immutable"] =
83 (*variables)["name"] + "_.makeImmutable()";
84 (*variables)["repeated_get"] =
85 (*variables)["name"] + "_.get" + capitalized_type;
86 (*variables)["repeated_add"] =
87 (*variables)["name"] + "_.add" + capitalized_type;
88 (*variables)["repeated_set"] =
89 (*variables)["name"] + "_.set" + capitalized_type;
90 } else {
91 (*variables)["field_list_type"] =
92 "java.util.List<" + (*variables)["boxed_type"] + ">";
93 (*variables)["create_list"] =
94 "new java.util.ArrayList<" + (*variables)["boxed_type"] + ">()";
95 (*variables)["mutable_copy_list"] = "new java.util.ArrayList<" +
96 (*variables)["boxed_type"] + ">(" +
97 (*variables)["name"] + "_)";
98 (*variables)["empty_list"] = "java.util.Collections.emptyList()";
99 (*variables)["name_make_immutable"] =
100 (*variables)["name"] + "_ = java.util.Collections.unmodifiableList(" +
101 (*variables)["name"] + "_)";
102 (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
103 (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
104 (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
105 }
106
107 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
108 (*variables)["default_init"] =
109 IsDefaultValueJavaDefault(descriptor)
110 ? ""
111 : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
112 (*variables)["capitalized_type"] =
113 GetCapitalizedType(descriptor, /* immutable = */ true);
114 (*variables)["tag"] =
115 StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
116 (*variables)["tag_size"] = StrCat(
117 WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
118 if (IsReferenceType(GetJavaType(descriptor))) {
119 (*variables)["null_check"] =
120 " if (value == null) {\n"
121 " throw new NullPointerException();\n"
122 " }\n";
123 } else {
124 (*variables)["null_check"] = "";
125 }
126 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
127 // by the proto compiler
128 (*variables)["deprecation"] =
129 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
130 int fixed_size = FixedSize(GetType(descriptor));
131 if (fixed_size != -1) {
132 (*variables)["fixed_size"] = StrCat(fixed_size);
133 }
134 (*variables)["on_changed"] = "onChanged();";
135
136 if (HasHasbit(descriptor)) {
137 // For singular messages and builders, one bit is used for the hasField bit.
138 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
139 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
140
141 // Note that these have a trailing ";".
142 (*variables)["set_has_field_bit_message"] =
143 GenerateSetBit(messageBitIndex) + ";";
144 (*variables)["set_has_field_bit_builder"] =
145 GenerateSetBit(builderBitIndex) + ";";
146 (*variables)["clear_has_field_bit_builder"] =
147 GenerateClearBit(builderBitIndex) + ";";
148
149 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
150 } else {
151 (*variables)["set_has_field_bit_message"] = "";
152 (*variables)["set_has_field_bit_builder"] = "";
153 (*variables)["clear_has_field_bit_builder"] = "";
154
155 if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
156 (*variables)["is_field_present_message"] =
157 "!" + (*variables)["name"] + "_.isEmpty()";
158 } else {
159 (*variables)["is_field_present_message"] =
160 (*variables)["name"] + "_ != " + (*variables)["default"];
161 }
162 }
163
164 // For repeated builders, one bit is used for whether the array is immutable.
165 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
166 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
167 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
168
169 (*variables)["get_has_field_bit_from_local"] =
170 GenerateGetBitFromLocal(builderBitIndex);
171 (*variables)["set_has_field_bit_to_local"] =
172 GenerateSetBitToLocal(messageBitIndex);
173 }
174
175 } // namespace
176
177 // ===================================================================
178
ImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)179 ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator(
180 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
181 Context* context)
182 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
183 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
184 context->GetFieldGeneratorInfo(descriptor),
185 name_resolver_, &variables_);
186 }
187
~ImmutablePrimitiveFieldGenerator()188 ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
189
GetNumBitsForMessage() const190 int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
191 return HasHasbit(descriptor_) ? 1 : 0;
192 }
193
GetNumBitsForBuilder() const194 int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
195 return GetNumBitsForMessage();
196 }
197
GenerateInterfaceMembers(io::Printer * printer) const198 void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
199 io::Printer* printer) const {
200 if (SupportFieldPresence(descriptor_)) {
201 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
202 printer->Print(variables_,
203 "$deprecation$boolean has$capitalized_name$();\n");
204 }
205 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
206 printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
207 }
208
GenerateMembers(io::Printer * printer) const209 void ImmutablePrimitiveFieldGenerator::GenerateMembers(
210 io::Printer* printer) const {
211 printer->Print(variables_, "private $field_type$ $name$_;\n");
212 PrintExtraFieldInfo(variables_, printer);
213 if (SupportFieldPresence(descriptor_)) {
214 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
215 printer->Print(
216 variables_,
217 "@java.lang.Override\n"
218 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
219 " return $get_has_field_bit_message$;\n"
220 "}\n");
221 printer->Annotate("{", "}", descriptor_);
222 }
223
224 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
225 printer->Print(variables_,
226 "@java.lang.Override\n"
227 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
228 " return $name$_;\n"
229 "}\n");
230 printer->Annotate("{", "}", descriptor_);
231 }
232
GenerateBuilderMembers(io::Printer * printer) const233 void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
234 io::Printer* printer) const {
235 printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n");
236
237 if (SupportFieldPresence(descriptor_)) {
238 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
239 printer->Print(
240 variables_,
241 "@java.lang.Override\n"
242 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
243 " return $get_has_field_bit_builder$;\n"
244 "}\n");
245 printer->Annotate("{", "}", descriptor_);
246 }
247
248 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
249 printer->Print(variables_,
250 "@java.lang.Override\n"
251 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
252 " return $name$_;\n"
253 "}\n");
254 printer->Annotate("{", "}", descriptor_);
255
256 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
257 /* builder */ true);
258 printer->Print(variables_,
259 "$deprecation$public Builder "
260 "${$set$capitalized_name$$}$($type$ value) {\n"
261 "$null_check$"
262 " $set_has_field_bit_builder$\n"
263 " $name$_ = value;\n"
264 " $on_changed$\n"
265 " return this;\n"
266 "}\n");
267 printer->Annotate("{", "}", descriptor_);
268
269 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
270 /* builder */ true);
271 printer->Print(
272 variables_,
273 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
274 " $clear_has_field_bit_builder$\n");
275 printer->Annotate("{", "}", descriptor_);
276 JavaType type = GetJavaType(descriptor_);
277 if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
278 // The default value is not a simple literal so we want to avoid executing
279 // it multiple times. Instead, get the default out of the default instance.
280 printer->Print(
281 variables_,
282 " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
283 } else {
284 printer->Print(variables_, " $name$_ = $default$;\n");
285 }
286 printer->Print(variables_,
287 " $on_changed$\n"
288 " return this;\n"
289 "}\n");
290 }
291
292
GenerateFieldBuilderInitializationCode(io::Printer * printer) const293 void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode(
294 io::Printer* printer) const {
295 // noop for primitives
296 }
297
GenerateInitializationCode(io::Printer * printer) const298 void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
299 io::Printer* printer) const {
300 if (!IsDefaultValueJavaDefault(descriptor_)) {
301 printer->Print(variables_, "$name$_ = $default$;\n");
302 }
303 }
304
GenerateBuilderClearCode(io::Printer * printer) const305 void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
306 io::Printer* printer) const {
307 printer->Print(variables_,
308 "$name$_ = $default$;\n"
309 "$clear_has_field_bit_builder$\n");
310 }
311
GenerateMergingCode(io::Printer * printer) const312 void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
313 io::Printer* printer) const {
314 if (SupportFieldPresence(descriptor_)) {
315 printer->Print(variables_,
316 "if (other.has$capitalized_name$()) {\n"
317 " set$capitalized_name$(other.get$capitalized_name$());\n"
318 "}\n");
319 } else {
320 printer->Print(variables_,
321 "if (other.get$capitalized_name$() != $default$) {\n"
322 " set$capitalized_name$(other.get$capitalized_name$());\n"
323 "}\n");
324 }
325 }
326
GenerateBuildingCode(io::Printer * printer) const327 void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
328 io::Printer* printer) const {
329 if (SupportFieldPresence(descriptor_)) {
330 if (IsDefaultValueJavaDefault(descriptor_)) {
331 printer->Print(variables_,
332 "if ($get_has_field_bit_from_local$) {\n"
333 " result.$name$_ = $name$_;\n"
334 " $set_has_field_bit_to_local$;\n"
335 "}\n");
336 } else {
337 printer->Print(variables_,
338 "if ($get_has_field_bit_from_local$) {\n"
339 " $set_has_field_bit_to_local$;\n"
340 "}\n"
341 "result.$name$_ = $name$_;\n");
342 }
343 } else {
344 printer->Print(variables_, "result.$name$_ = $name$_;\n");
345 }
346 }
347
GenerateBuilderParsingCode(io::Printer * printer) const348 void ImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(
349 io::Printer* printer) const {
350 printer->Print(variables_,
351 "$name$_ = input.read$capitalized_type$();\n"
352 "$set_has_field_bit_builder$\n");
353 }
354
GenerateSerializationCode(io::Printer * printer) const355 void ImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
356 io::Printer* printer) const {
357 printer->Print(variables_,
358 "if ($is_field_present_message$) {\n"
359 " output.write$capitalized_type$($number$, $name$_);\n"
360 "}\n");
361 }
362
GenerateSerializedSizeCode(io::Printer * printer) const363 void ImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
364 io::Printer* printer) const {
365 printer->Print(variables_,
366 "if ($is_field_present_message$) {\n"
367 " size += com.google.protobuf.CodedOutputStream\n"
368 " .compute$capitalized_type$Size($number$, $name$_);\n"
369 "}\n");
370 }
371
GenerateEqualsCode(io::Printer * printer) const372 void ImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
373 io::Printer* printer) const {
374 switch (GetJavaType(descriptor_)) {
375 case JAVATYPE_INT:
376 case JAVATYPE_LONG:
377 case JAVATYPE_BOOLEAN:
378 printer->Print(variables_,
379 "if (get$capitalized_name$()\n"
380 " != other.get$capitalized_name$()) return false;\n");
381 break;
382
383 case JAVATYPE_FLOAT:
384 printer->Print(
385 variables_,
386 "if (java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
387 " != java.lang.Float.floatToIntBits(\n"
388 " other.get$capitalized_name$())) return false;\n");
389 break;
390
391 case JAVATYPE_DOUBLE:
392 printer->Print(
393 variables_,
394 "if (java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
395 " != java.lang.Double.doubleToLongBits(\n"
396 " other.get$capitalized_name$())) return false;\n");
397 break;
398
399 case JAVATYPE_STRING:
400 case JAVATYPE_BYTES:
401 printer->Print(
402 variables_,
403 "if (!get$capitalized_name$()\n"
404 " .equals(other.get$capitalized_name$())) return false;\n");
405 break;
406
407 case JAVATYPE_ENUM:
408 case JAVATYPE_MESSAGE:
409 default:
410 GOOGLE_LOG(FATAL) << "Can't get here.";
411 break;
412 }
413 }
414
GenerateHashCode(io::Printer * printer) const415 void ImmutablePrimitiveFieldGenerator::GenerateHashCode(
416 io::Printer* printer) const {
417 printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n");
418 switch (GetJavaType(descriptor_)) {
419 case JAVATYPE_INT:
420 printer->Print(variables_,
421 "hash = (53 * hash) + get$capitalized_name$();\n");
422 break;
423
424 case JAVATYPE_LONG:
425 printer->Print(
426 variables_,
427 "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
428 " get$capitalized_name$());\n");
429 break;
430
431 case JAVATYPE_BOOLEAN:
432 printer->Print(
433 variables_,
434 "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
435 " get$capitalized_name$());\n");
436 break;
437
438 case JAVATYPE_FLOAT:
439 printer->Print(variables_,
440 "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
441 " get$capitalized_name$());\n");
442 break;
443
444 case JAVATYPE_DOUBLE:
445 printer->Print(
446 variables_,
447 "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
448 " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
449 break;
450
451 case JAVATYPE_STRING:
452 case JAVATYPE_BYTES:
453 printer->Print(
454 variables_,
455 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
456 break;
457
458 case JAVATYPE_ENUM:
459 case JAVATYPE_MESSAGE:
460 default:
461 GOOGLE_LOG(FATAL) << "Can't get here.";
462 break;
463 }
464 }
465
GetBoxedType() const466 std::string ImmutablePrimitiveFieldGenerator::GetBoxedType() const {
467 return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
468 }
469
470 // ===================================================================
471
ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)472 ImmutablePrimitiveOneofFieldGenerator::ImmutablePrimitiveOneofFieldGenerator(
473 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
474 Context* context)
475 : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex,
476 builderBitIndex, context) {
477 const OneofGeneratorInfo* info =
478 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
479 SetCommonOneofVariables(descriptor, info, &variables_);
480 }
481
482 ImmutablePrimitiveOneofFieldGenerator::
~ImmutablePrimitiveOneofFieldGenerator()483 ~ImmutablePrimitiveOneofFieldGenerator() {}
484
GenerateMembers(io::Printer * printer) const485 void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
486 io::Printer* printer) const {
487 PrintExtraFieldInfo(variables_, printer);
488 if (SupportFieldPresence(descriptor_)) {
489 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
490 printer->Print(
491 variables_,
492 "@java.lang.Override\n"
493 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
494 " return $has_oneof_case_message$;\n"
495 "}\n");
496 printer->Annotate("{", "}", descriptor_);
497 }
498
499 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
500 printer->Print(variables_,
501 "@java.lang.Override\n"
502 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
503 " if ($has_oneof_case_message$) {\n"
504 " return ($boxed_type$) $oneof_name$_;\n"
505 " }\n"
506 " return $default$;\n"
507 "}\n");
508 printer->Annotate("{", "}", descriptor_);
509 }
510
GenerateBuilderMembers(io::Printer * printer) const511 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
512 io::Printer* printer) const {
513 if (SupportFieldPresence(descriptor_)) {
514 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
515 printer->Print(
516 variables_,
517 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
518 " return $has_oneof_case_message$;\n"
519 "}\n");
520 printer->Annotate("{", "}", descriptor_);
521 }
522
523 WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
524 printer->Print(variables_,
525 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
526 " if ($has_oneof_case_message$) {\n"
527 " return ($boxed_type$) $oneof_name$_;\n"
528 " }\n"
529 " return $default$;\n"
530 "}\n");
531 printer->Annotate("{", "}", descriptor_);
532
533 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
534 /* builder */ true);
535 printer->Print(variables_,
536 "$deprecation$public Builder "
537 "${$set$capitalized_name$$}$($type$ value) {\n"
538 "$null_check$"
539 " $set_oneof_case_message$;\n"
540 " $oneof_name$_ = value;\n"
541 " $on_changed$\n"
542 " return this;\n"
543 "}\n");
544 printer->Annotate("{", "}", descriptor_);
545
546 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
547 /* builder */ true);
548 printer->Print(
549 variables_,
550 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
551 " if ($has_oneof_case_message$) {\n"
552 " $clear_oneof_case_message$;\n"
553 " $oneof_name$_ = null;\n"
554 " $on_changed$\n"
555 " }\n"
556 " return this;\n"
557 "}\n");
558 printer->Annotate("{", "}", descriptor_);
559 }
560
GenerateBuilderClearCode(io::Printer * printer) const561 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderClearCode(
562 io::Printer* printer) const {
563 // No-Op: When a primitive field is in a oneof, clearing the oneof clears that
564 // field.
565 }
566
GenerateBuildingCode(io::Printer * printer) const567 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode(
568 io::Printer* printer) const {
569 printer->Print(variables_,
570 "if ($has_oneof_case_message$) {\n"
571 " result.$oneof_name$_ = $oneof_name$_;\n"
572 "}\n");
573 }
574
GenerateMergingCode(io::Printer * printer) const575 void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode(
576 io::Printer* printer) const {
577 printer->Print(variables_,
578 "set$capitalized_name$(other.get$capitalized_name$());\n");
579 }
580
GenerateBuilderParsingCode(io::Printer * printer) const581 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderParsingCode(
582 io::Printer* printer) const {
583 printer->Print(variables_,
584 "$set_oneof_case_message$;\n"
585 "$oneof_name$_ = input.read$capitalized_type$();\n");
586 }
587
GenerateSerializationCode(io::Printer * printer) const588 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializationCode(
589 io::Printer* printer) const {
590 printer->Print(variables_,
591 "if ($has_oneof_case_message$) {\n"
592 " output.write$capitalized_type$(\n");
593 // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
594 // do redundant casts.
595 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
596 printer->Print(variables_, " $number$, ($type$) $oneof_name$_);\n");
597 } else {
598 printer->Print(
599 variables_,
600 " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
601 }
602 printer->Print("}\n");
603 }
604
GenerateSerializedSizeCode(io::Printer * printer) const605 void ImmutablePrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
606 io::Printer* printer) const {
607 printer->Print(variables_,
608 "if ($has_oneof_case_message$) {\n"
609 " size += com.google.protobuf.CodedOutputStream\n"
610 " .compute$capitalized_type$Size(\n");
611 // $type$ and $boxed_type$ is the same for bytes fields so we don't need to
612 // do redundant casts.
613 if (GetJavaType(descriptor_) == JAVATYPE_BYTES) {
614 printer->Print(variables_, " $number$, ($type$) $oneof_name$_);\n");
615 } else {
616 printer->Print(
617 variables_,
618 " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n");
619 }
620 printer->Print("}\n");
621 }
622
623 // ===================================================================
624
625 RepeatedImmutablePrimitiveFieldGenerator::
RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)626 RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
627 int messageBitIndex,
628 int builderBitIndex,
629 Context* context)
630 : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
631 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
632 context->GetFieldGeneratorInfo(descriptor),
633 name_resolver_, &variables_);
634 }
635
636 RepeatedImmutablePrimitiveFieldGenerator::
~RepeatedImmutablePrimitiveFieldGenerator()637 ~RepeatedImmutablePrimitiveFieldGenerator() {}
638
GetNumBitsForMessage() const639 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
640 return 0;
641 }
642
GetNumBitsForBuilder() const643 int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
644 return 1;
645 }
646
GenerateInterfaceMembers(io::Printer * printer) const647 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
648 io::Printer* printer) const {
649 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
650 printer->Print(variables_,
651 "$deprecation$java.util.List<$boxed_type$> "
652 "get$capitalized_name$List();\n");
653 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
654 printer->Print(variables_,
655 "$deprecation$int get$capitalized_name$Count();\n");
656 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
657 printer->Print(variables_,
658 "$deprecation$$type$ get$capitalized_name$(int index);\n");
659 }
660
GenerateMembers(io::Printer * printer) const661 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers(
662 io::Printer* printer) const {
663 printer->Print(variables_, "private $field_list_type$ $name$_;\n");
664 PrintExtraFieldInfo(variables_, printer);
665 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
666 printer->Print(variables_,
667 "@java.lang.Override\n"
668 "$deprecation$public java.util.List<$boxed_type$>\n"
669 " ${$get$capitalized_name$List$}$() {\n"
670 " return $name$_;\n" // note: unmodifiable list
671 "}\n");
672 printer->Annotate("{", "}", descriptor_);
673 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
674 printer->Print(
675 variables_,
676 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
677 " return $name$_.size();\n"
678 "}\n");
679 printer->Annotate("{", "}", descriptor_);
680 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
681 printer->Print(
682 variables_,
683 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
684 " return $repeated_get$(index);\n"
685 "}\n");
686 printer->Annotate("{", "}", descriptor_);
687
688 if (descriptor_->is_packed()) {
689 printer->Print(variables_,
690 "private int $name$MemoizedSerializedSize = -1;\n");
691 }
692 }
693
GenerateBuilderMembers(io::Printer * printer) const694 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers(
695 io::Printer* printer) const {
696 // One field is the list and the bit field keeps track of whether the
697 // list is immutable. If it's immutable, the invariant is that it must
698 // either an instance of Collections.emptyList() or it's an ArrayList
699 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
700 // a reference to the underlying ArrayList. This invariant allows us to
701 // share instances of lists between protocol buffers avoiding expensive
702 // memory allocations. Note, immutable is a strong guarantee here -- not
703 // just that the list cannot be modified via the reference but that the
704 // list can never be modified.
705 printer->Print(variables_,
706 "private $field_list_type$ $name$_ = $empty_list$;\n");
707
708 printer->Print(variables_,
709 "private void ensure$capitalized_name$IsMutable() {\n"
710 " if (!$get_mutable_bit_builder$) {\n"
711 " $name$_ = $mutable_copy_list$;\n"
712 " $set_mutable_bit_builder$;\n"
713 " }\n"
714 "}\n");
715
716 // Note: We return an unmodifiable list because otherwise the caller
717 // could hold on to the returned list and modify it after the message
718 // has been built, thus mutating the message which is supposed to be
719 // immutable.
720 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
721 printer->Print(
722 variables_,
723 "$deprecation$public java.util.List<$boxed_type$>\n"
724 " ${$get$capitalized_name$List$}$() {\n"
725 " return $get_mutable_bit_builder$ ?\n"
726 " java.util.Collections.unmodifiableList($name$_) : $name$_;\n"
727 "}\n");
728 printer->Annotate("{", "}", descriptor_);
729 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
730 printer->Print(
731 variables_,
732 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
733 " return $name$_.size();\n"
734 "}\n");
735 printer->Annotate("{", "}", descriptor_);
736 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
737 printer->Print(
738 variables_,
739 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
740 " return $repeated_get$(index);\n"
741 "}\n");
742 printer->Annotate("{", "}", descriptor_);
743 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
744 /* builder */ true);
745 printer->Print(variables_,
746 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
747 " int index, $type$ value) {\n"
748 "$null_check$"
749 " ensure$capitalized_name$IsMutable();\n"
750 " $repeated_set$(index, value);\n"
751 " $on_changed$\n"
752 " return this;\n"
753 "}\n");
754 printer->Annotate("{", "}", descriptor_);
755 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
756 /* builder */ true);
757 printer->Print(variables_,
758 "$deprecation$public Builder "
759 "${$add$capitalized_name$$}$($type$ value) {\n"
760 "$null_check$"
761 " ensure$capitalized_name$IsMutable();\n"
762 " $repeated_add$(value);\n"
763 " $on_changed$\n"
764 " return this;\n"
765 "}\n");
766 printer->Annotate("{", "}", descriptor_);
767 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
768 /* builder */ true);
769 printer->Print(variables_,
770 "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
771 " java.lang.Iterable<? extends $boxed_type$> values) {\n"
772 " ensure$capitalized_name$IsMutable();\n"
773 " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
774 " values, $name$_);\n"
775 " $on_changed$\n"
776 " return this;\n"
777 "}\n");
778 printer->Annotate("{", "}", descriptor_);
779 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
780 /* builder */ true);
781 printer->Print(
782 variables_,
783 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
784 " $name$_ = $empty_list$;\n"
785 " $clear_mutable_bit_builder$;\n"
786 " $on_changed$\n"
787 " return this;\n"
788 "}\n");
789 printer->Annotate("{", "}", descriptor_);
790 }
791
792 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const793 GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
794 // noop for primitives
795 }
796
GenerateInitializationCode(io::Printer * printer) const797 void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode(
798 io::Printer* printer) const {
799 printer->Print(variables_, "$name$_ = $empty_list$;\n");
800 }
801
GenerateBuilderClearCode(io::Printer * printer) const802 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode(
803 io::Printer* printer) const {
804 printer->Print(variables_,
805 "$name$_ = $empty_list$;\n"
806 "$clear_mutable_bit_builder$;\n");
807 }
808
GenerateMergingCode(io::Printer * printer) const809 void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode(
810 io::Printer* printer) const {
811 // The code below does two optimizations:
812 // 1. If the other list is empty, there's nothing to do. This ensures we
813 // don't allocate a new array if we already have an immutable one.
814 // 2. If the other list is non-empty and our current list is empty, we can
815 // reuse the other list which is guaranteed to be immutable.
816 printer->Print(variables_,
817 "if (!other.$name$_.isEmpty()) {\n"
818 " if ($name$_.isEmpty()) {\n"
819 " $name$_ = other.$name$_;\n"
820 " $clear_mutable_bit_builder$;\n"
821 " } else {\n"
822 " ensure$capitalized_name$IsMutable();\n"
823 " $name$_.addAll(other.$name$_);\n"
824 " }\n"
825 " $on_changed$\n"
826 "}\n");
827 }
828
GenerateBuildingCode(io::Printer * printer) const829 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
830 io::Printer* printer) const {
831 // The code below ensures that the result has an immutable list. If our
832 // list is immutable, we can just reuse it. If not, we make it immutable.
833 printer->Print(variables_,
834 "if ($get_mutable_bit_builder$) {\n"
835 " $name_make_immutable$;\n"
836 " $clear_mutable_bit_builder$;\n"
837 "}\n"
838 "result.$name$_ = $name$_;\n");
839 }
840
GenerateBuilderParsingCode(io::Printer * printer) const841 void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode(
842 io::Printer* printer) const {
843 printer->Print(variables_,
844 "$type$ v = input.read$capitalized_type$();\n"
845 "ensure$capitalized_name$IsMutable();\n"
846 "$repeated_add$(v);\n");
847 }
848
849 void RepeatedImmutablePrimitiveFieldGenerator::
GenerateBuilderParsingCodeFromPacked(io::Printer * printer) const850 GenerateBuilderParsingCodeFromPacked(io::Printer* printer) const {
851 printer->Print(variables_,
852 "int length = input.readRawVarint32();\n"
853 "int limit = input.pushLimit(length);\n"
854 "ensure$capitalized_name$IsMutable();\n"
855 "while (input.getBytesUntilLimit() > 0) {\n"
856 " $repeated_add$(input.read$capitalized_type$());\n"
857 "}\n"
858 "input.popLimit(limit);\n");
859 }
860
GenerateSerializationCode(io::Printer * printer) const861 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializationCode(
862 io::Printer* printer) const {
863 if (descriptor_->is_packed()) {
864 // We invoke getSerializedSize in writeTo for messages that have packed
865 // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
866 // That makes it safe to rely on the memoized size here.
867 printer->Print(variables_,
868 "if (get$capitalized_name$List().size() > 0) {\n"
869 " output.writeUInt32NoTag($tag$);\n"
870 " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
871 "}\n"
872 "for (int i = 0; i < $name$_.size(); i++) {\n"
873 " output.write$capitalized_type$NoTag($repeated_get$(i));\n"
874 "}\n");
875 } else {
876 printer->Print(
877 variables_,
878 "for (int i = 0; i < $name$_.size(); i++) {\n"
879 " output.write$capitalized_type$($number$, $repeated_get$(i));\n"
880 "}\n");
881 }
882 }
883
GenerateSerializedSizeCode(io::Printer * printer) const884 void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializedSizeCode(
885 io::Printer* printer) const {
886 printer->Print(variables_,
887 "{\n"
888 " int dataSize = 0;\n");
889 printer->Indent();
890
891 if (FixedSize(GetType(descriptor_)) == -1) {
892 printer->Print(
893 variables_,
894 "for (int i = 0; i < $name$_.size(); i++) {\n"
895 " dataSize += com.google.protobuf.CodedOutputStream\n"
896 " .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n"
897 "}\n");
898 } else {
899 printer->Print(
900 variables_,
901 "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
902 }
903
904 printer->Print("size += dataSize;\n");
905
906 if (descriptor_->is_packed()) {
907 printer->Print(variables_,
908 "if (!get$capitalized_name$List().isEmpty()) {\n"
909 " size += $tag_size$;\n"
910 " size += com.google.protobuf.CodedOutputStream\n"
911 " .computeInt32SizeNoTag(dataSize);\n"
912 "}\n");
913 } else {
914 printer->Print(
915 variables_,
916 "size += $tag_size$ * get$capitalized_name$List().size();\n");
917 }
918
919 // cache the data size for packed fields.
920 if (descriptor_->is_packed()) {
921 printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
922 }
923
924 printer->Outdent();
925 printer->Print("}\n");
926 }
927
GenerateEqualsCode(io::Printer * printer) const928 void RepeatedImmutablePrimitiveFieldGenerator::GenerateEqualsCode(
929 io::Printer* printer) const {
930 printer->Print(
931 variables_,
932 "if (!get$capitalized_name$List()\n"
933 " .equals(other.get$capitalized_name$List())) return false;\n");
934 }
935
GenerateHashCode(io::Printer * printer) const936 void RepeatedImmutablePrimitiveFieldGenerator::GenerateHashCode(
937 io::Printer* printer) const {
938 printer->Print(
939 variables_,
940 "if (get$capitalized_name$Count() > 0) {\n"
941 " hash = (37 * hash) + $constant_name$;\n"
942 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
943 "}\n");
944 }
945
GetBoxedType() const946 std::string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const {
947 return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
948 }
949
950 } // namespace java
951 } // namespace compiler
952 } // namespace protobuf
953 } // namespace google
954