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 <google/protobuf/compiler/java/primitive_field_lite.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
51namespace google {
52namespace protobuf {
53namespace compiler {
54namespace java {
55
56using internal::WireFormat;
57using internal::WireFormatLite;
58
59namespace {
60bool EnableExperimentalRuntimeForLite() {
61#ifdef PROTOBUF_EXPERIMENT
62 return PROTOBUF_EXPERIMENT;
63#else // PROTOBUF_EXPERIMENT
64 return false;
65#endif // !PROTOBUF_EXPERIMENT
66}
67
68void SetPrimitiveVariables(const FieldDescriptor* descriptor,
69 int messageBitIndex, int builderBitIndex,
70 const FieldGeneratorInfo* info,
71 ClassNameResolver* name_resolver,
72 std::map<std::string, std::string>* variables) {
73 SetCommonFieldVariables(descriptor, info, variables);
74 JavaType javaType = GetJavaType(field: descriptor);
75 (*variables)["type"] = PrimitiveTypeName(type: javaType);
76 (*variables)["boxed_type"] = BoxedPrimitiveTypeName(type: javaType);
77 (*variables)["kt_type"] = KotlinTypeName(type: javaType);
78 (*variables)["field_type"] = (*variables)["type"];
79 (*variables)["default"] = ImmutableDefaultValue(field: descriptor, name_resolver);
80 (*variables)["capitalized_type"] =
81 GetCapitalizedType(field: descriptor, /* immutable = */ true);
82 (*variables)["tag"] =
83 StrCat(a: static_cast<int32_t>(WireFormat::MakeTag(field: descriptor)));
84 (*variables)["tag_size"] = StrCat(
85 a: WireFormat::TagSize(field_number: descriptor->number(), type: GetType(field: descriptor)));
86 (*variables)["required"] = descriptor->is_required() ? "true" : "false";
87
88 std::string capitalized_type = UnderscoresToCamelCase(
89 name: PrimitiveTypeName(type: javaType), cap_first_letter: true /* cap_next_letter */);
90 switch (javaType) {
91 case JAVATYPE_INT:
92 case JAVATYPE_LONG:
93 case JAVATYPE_FLOAT:
94 case JAVATYPE_DOUBLE:
95 case JAVATYPE_BOOLEAN:
96 (*variables)["field_list_type"] =
97 "com.google.protobuf.Internal." + capitalized_type + "List";
98 (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
99 (*variables)["make_name_unmodifiable"] =
100 (*variables)["name"] + "_.makeImmutable()";
101 (*variables)["repeated_get"] =
102 (*variables)["name"] + "_.get" + capitalized_type;
103 (*variables)["repeated_add"] =
104 (*variables)["name"] + "_.add" + capitalized_type;
105 (*variables)["repeated_set"] =
106 (*variables)["name"] + "_.set" + capitalized_type;
107 (*variables)["visit_type"] = capitalized_type;
108 (*variables)["visit_type_list"] = "visit" + capitalized_type + "List";
109 break;
110 default:
111 (*variables)["field_list_type"] =
112 "com.google.protobuf.Internal.ProtobufList<" +
113 (*variables)["boxed_type"] + ">";
114 (*variables)["empty_list"] = "emptyProtobufList()";
115 (*variables)["make_name_unmodifiable"] =
116 (*variables)["name"] + "_.makeImmutable()";
117 (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
118 (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
119 (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
120 (*variables)["visit_type"] = "ByteString";
121 (*variables)["visit_type_list"] = "visitList";
122 }
123
124 if (javaType == JAVATYPE_BYTES) {
125 (*variables)["bytes_default"] =
126 ToUpper(s: (*variables)["name"]) + "_DEFAULT_VALUE";
127 }
128
129 if (IsReferenceType(type: javaType)) {
130 // We use `x.getClass()` as a null check because it generates less bytecode
131 // than an `if (x == null) { throw ... }` statement.
132 (*variables)["null_check"] =
133 " java.lang.Class<?> valueClass = value.getClass();\n";
134 } else {
135 (*variables)["null_check"] = "";
136 }
137 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
138 // by the proto compiler
139 (*variables)["deprecation"] =
140 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
141 (*variables)["kt_deprecation"] =
142 descriptor->options().deprecated()
143 ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
144 " is deprecated\") "
145 : "";
146 int fixed_size = FixedSize(type: GetType(field: descriptor));
147 if (fixed_size != -1) {
148 (*variables)["fixed_size"] = StrCat(a: fixed_size);
149 }
150
151 if (HasHasbit(descriptor)) {
152 // For singular messages and builders, one bit is used for the hasField bit.
153 (*variables)["get_has_field_bit_message"] = GenerateGetBit(bitIndex: messageBitIndex);
154
155 // Note that these have a trailing ";".
156 (*variables)["set_has_field_bit_message"] =
157 GenerateSetBit(bitIndex: messageBitIndex) + ";";
158 (*variables)["clear_has_field_bit_message"] =
159 GenerateClearBit(bitIndex: messageBitIndex) + ";";
160
161 (*variables)["is_field_present_message"] = GenerateGetBit(bitIndex: messageBitIndex);
162 } else {
163 (*variables)["set_has_field_bit_message"] = "";
164 (*variables)["clear_has_field_bit_message"] = "";
165
166 switch (descriptor->type()) {
167 case FieldDescriptor::TYPE_BYTES:
168 (*variables)["is_field_present_message"] =
169 "!" + (*variables)["name"] + "_.isEmpty()";
170 break;
171 case FieldDescriptor::TYPE_FLOAT:
172 (*variables)["is_field_present_message"] =
173 "java.lang.Float.floatToRawIntBits(" + (*variables)["name"] +
174 "_) != 0";
175 break;
176 case FieldDescriptor::TYPE_DOUBLE:
177 (*variables)["is_field_present_message"] =
178 "java.lang.Double.doubleToRawLongBits(" + (*variables)["name"] +
179 "_) != 0";
180 break;
181 default:
182 (*variables)["is_field_present_message"] =
183 (*variables)["name"] + "_ != " + (*variables)["default"];
184 break;
185 }
186 }
187
188 (*variables)["get_has_field_bit_from_local"] =
189 GenerateGetBitFromLocal(bitIndex: builderBitIndex);
190 (*variables)["set_has_field_bit_to_local"] =
191 GenerateSetBitToLocal(bitIndex: messageBitIndex);
192}
193
194} // namespace
195
196// ===================================================================
197
198ImmutablePrimitiveFieldLiteGenerator::ImmutablePrimitiveFieldLiteGenerator(
199 const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
200 : descriptor_(descriptor),
201 messageBitIndex_(messageBitIndex),
202 name_resolver_(context->GetNameResolver()) {
203 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex: 0,
204 info: context->GetFieldGeneratorInfo(field: descriptor),
205 name_resolver: name_resolver_, variables: &variables_);
206}
207
208ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {}
209
210int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
211 return HasHasbit(descriptor: descriptor_) ? 1 : 0;
212}
213
214void ImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers(
215 io::Printer* printer) const {
216 if (HasHazzer(descriptor: descriptor_)) {
217 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
218 printer->Print(variables: variables_,
219 text: "$deprecation$boolean has$capitalized_name$();\n");
220 }
221 WriteFieldAccessorDocComment(printer, field: descriptor_, type: GETTER);
222 printer->Print(variables: variables_, text: "$deprecation$$type$ get$capitalized_name$();\n");
223}
224
225void ImmutablePrimitiveFieldLiteGenerator::GenerateMembers(
226 io::Printer* printer) const {
227 if (IsByteStringWithCustomDefaultValue(field: descriptor_)) {
228 // allocate this once statically since we know ByteStrings are immutable
229 // values that can be reused.
230 printer->Print(
231 variables: variables_,
232 text: "private static final $field_type$ $bytes_default$ = $default$;\n");
233 }
234 printer->Print(variables: variables_, text: "private $field_type$ $name$_;\n");
235 PrintExtraFieldInfo(variables: variables_, printer);
236 if (HasHazzer(descriptor: descriptor_)) {
237 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
238 printer->Print(
239 variables: variables_,
240 text: "@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(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
245 }
246
247 WriteFieldAccessorDocComment(printer, field: descriptor_, type: GETTER);
248 printer->Print(variables: variables_,
249 text: "@java.lang.Override\n"
250 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
251 " return $name$_;\n"
252 "}\n");
253 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
254
255 WriteFieldAccessorDocComment(printer, field: descriptor_, type: SETTER);
256 printer->Print(variables: variables_,
257 text: "private void set$capitalized_name$($type$ value) {\n"
258 "$null_check$"
259 " $set_has_field_bit_message$\n"
260 " $name$_ = value;\n"
261 "}\n");
262
263 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER);
264 printer->Print(variables: variables_,
265 text: "private void clear$capitalized_name$() {\n"
266 " $clear_has_field_bit_message$\n");
267 JavaType type = GetJavaType(field: descriptor_);
268 if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
269 // The default value is not a simple literal so we want to avoid executing
270 // it multiple times. Instead, get the default out of the default instance.
271 printer->Print(
272 variables: variables_,
273 text: " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
274 } else {
275 printer->Print(variables: variables_, text: " $name$_ = $default$;\n");
276 }
277 printer->Print(variables: variables_, text: "}\n");
278}
279
280void ImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers(
281 io::Printer* printer) const {
282 if (HasHazzer(descriptor: descriptor_)) {
283 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
284 printer->Print(
285 variables: variables_,
286 text: "@java.lang.Override\n"
287 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
288 " return instance.has$capitalized_name$();\n"
289 "}\n");
290 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
291 }
292
293 WriteFieldAccessorDocComment(printer, field: descriptor_, type: GETTER);
294 printer->Print(variables: variables_,
295 text: "@java.lang.Override\n"
296 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
297 " return instance.get$capitalized_name$();\n"
298 "}\n");
299 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
300
301 WriteFieldAccessorDocComment(printer, field: descriptor_, type: SETTER,
302 /* builder */ true);
303 printer->Print(variables: variables_,
304 text: "$deprecation$public Builder "
305 "${$set$capitalized_name$$}$($type$ value) {\n"
306 " copyOnWrite();\n"
307 " instance.set$capitalized_name$(value);\n"
308 " return this;\n"
309 "}\n");
310 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
311
312 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER,
313 /* builder */ true);
314 printer->Print(
315 variables: variables_,
316 text: "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
317 " copyOnWrite();\n"
318 " instance.clear$capitalized_name$();\n"
319 " return this;\n"
320 "}\n");
321 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
322}
323
324void ImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers(
325 io::Printer* printer) const {
326 WriteFieldDocComment(printer, field: descriptor_);
327 printer->Print(variables: variables_,
328 text: "$kt_deprecation$var $kt_name$: $kt_type$\n"
329 " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
330 " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
331 " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
332 " set(value) {\n"
333 " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
334 " }\n");
335
336 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER,
337 /* builder */ false);
338 printer->Print(variables: variables_,
339 text: "fun ${$clear$kt_capitalized_name$$}$() {\n"
340 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
341 "}\n");
342
343 if (HasHazzer(descriptor: descriptor_)) {
344 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
345 printer->Print(
346 variables: variables_,
347 text: "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
348 " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
349 "}\n");
350 }
351}
352
353void ImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo(
354 io::Printer* printer, std::vector<uint16_t>* output) const {
355 WriteIntToUtf16CharSequence(value: descriptor_->number(), output);
356 WriteIntToUtf16CharSequence(value: GetExperimentalJavaFieldType(field: descriptor_),
357 output);
358 if (HasHasbit(descriptor: descriptor_)) {
359 WriteIntToUtf16CharSequence(value: messageBitIndex_, output);
360 }
361 printer->Print(variables: variables_, text: "\"$name$_\",\n");
362}
363
364void ImmutablePrimitiveFieldLiteGenerator::GenerateInitializationCode(
365 io::Printer* printer) const {
366 if (IsByteStringWithCustomDefaultValue(field: descriptor_)) {
367 printer->Print(variables: variables_, text: "$name$_ = $bytes_default$;\n");
368 } else if (!IsDefaultValueJavaDefault(field: descriptor_)) {
369 printer->Print(variables: variables_, text: "$name$_ = $default$;\n");
370 }
371}
372
373std::string ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
374 return BoxedPrimitiveTypeName(type: GetJavaType(field: descriptor_));
375}
376
377// ===================================================================
378
379ImmutablePrimitiveOneofFieldLiteGenerator::
380 ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
381 int messageBitIndex,
382 Context* context)
383 : ImmutablePrimitiveFieldLiteGenerator(descriptor, messageBitIndex,
384 context) {
385 const OneofGeneratorInfo* info =
386 context->GetOneofGeneratorInfo(oneof: descriptor->containing_oneof());
387 SetCommonOneofVariables(descriptor, info, variables: &variables_);
388}
389
390ImmutablePrimitiveOneofFieldLiteGenerator::
391 ~ImmutablePrimitiveOneofFieldLiteGenerator() {}
392
393void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateMembers(
394 io::Printer* printer) const {
395 PrintExtraFieldInfo(variables: variables_, printer);
396 GOOGLE_DCHECK(HasHazzer(descriptor_));
397 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
398 printer->Print(variables: variables_,
399 text: "@java.lang.Override\n"
400 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
401 " return $has_oneof_case_message$;\n"
402 "}\n");
403 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
404
405 WriteFieldAccessorDocComment(printer, field: descriptor_, type: GETTER);
406 printer->Print(variables: variables_,
407 text: "@java.lang.Override\n"
408 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
409 " if ($has_oneof_case_message$) {\n"
410 " return ($boxed_type$) $oneof_name$_;\n"
411 " }\n"
412 " return $default$;\n"
413 "}\n");
414 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
415
416 WriteFieldAccessorDocComment(printer, field: descriptor_, type: SETTER);
417 printer->Print(variables: variables_,
418 text: "private void set$capitalized_name$($type$ value) {\n"
419 "$null_check$"
420 " $set_oneof_case_message$;\n"
421 " $oneof_name$_ = value;\n"
422 "}\n");
423
424 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER);
425 printer->Print(variables: variables_,
426 text: "private void clear$capitalized_name$() {\n"
427 " if ($has_oneof_case_message$) {\n"
428 " $clear_oneof_case_message$;\n"
429 " $oneof_name$_ = null;\n"
430 " }\n"
431 "}\n");
432}
433
434void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateFieldInfo(
435 io::Printer* printer, std::vector<uint16_t>* output) const {
436 WriteIntToUtf16CharSequence(value: descriptor_->number(), output);
437 WriteIntToUtf16CharSequence(value: GetExperimentalJavaFieldType(field: descriptor_),
438 output);
439 WriteIntToUtf16CharSequence(value: descriptor_->containing_oneof()->index(), output);
440}
441
442void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateBuilderMembers(
443 io::Printer* printer) const {
444 GOOGLE_DCHECK(HasHazzer(descriptor_));
445 WriteFieldAccessorDocComment(printer, field: descriptor_, type: HAZZER);
446 printer->Print(variables: variables_,
447 text: "@java.lang.Override\n"
448 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
449 " return instance.has$capitalized_name$();\n"
450 "}\n");
451 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
452
453 WriteFieldAccessorDocComment(printer, field: descriptor_, type: GETTER);
454 printer->Print(variables: variables_,
455 text: "@java.lang.Override\n"
456 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
457 " return instance.get$capitalized_name$();\n"
458 "}\n");
459 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
460
461 WriteFieldAccessorDocComment(printer, field: descriptor_, type: SETTER,
462 /* builder */ true);
463 printer->Print(variables: variables_,
464 text: "$deprecation$public Builder "
465 "${$set$capitalized_name$$}$($type$ value) {\n"
466 " copyOnWrite();\n"
467 " instance.set$capitalized_name$(value);\n"
468 " return this;\n"
469 "}\n");
470 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
471
472 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER,
473 /* builder */ true);
474 printer->Print(
475 variables: variables_,
476 text: "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
477 " copyOnWrite();\n"
478 " instance.clear$capitalized_name$();\n"
479 " return this;\n"
480 "}\n");
481 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
482}
483
484// ===================================================================
485
486RepeatedImmutablePrimitiveFieldLiteGenerator::
487 RepeatedImmutablePrimitiveFieldLiteGenerator(
488 const FieldDescriptor* descriptor, int messageBitIndex,
489 Context* context)
490 : descriptor_(descriptor),
491 context_(context),
492 name_resolver_(context->GetNameResolver()) {
493 SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex: 0,
494 info: context->GetFieldGeneratorInfo(field: descriptor),
495 name_resolver: name_resolver_, variables: &variables_);
496}
497
498RepeatedImmutablePrimitiveFieldLiteGenerator::
499 ~RepeatedImmutablePrimitiveFieldLiteGenerator() {}
500
501int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
502 return 0;
503}
504
505void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers(
506 io::Printer* printer) const {
507 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_GETTER);
508 printer->Print(variables: variables_,
509 text: "$deprecation$java.util.List<$boxed_type$> "
510 "get$capitalized_name$List();\n");
511 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_COUNT);
512 printer->Print(variables: variables_,
513 text: "$deprecation$int get$capitalized_name$Count();\n");
514 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_INDEXED_GETTER);
515 printer->Print(variables: variables_,
516 text: "$deprecation$$type$ get$capitalized_name$(int index);\n");
517}
518
519void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateMembers(
520 io::Printer* printer) const {
521 printer->Print(variables: variables_, text: "private $field_list_type$ $name$_;\n");
522 PrintExtraFieldInfo(variables: variables_, printer);
523 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_GETTER);
524 printer->Print(variables: variables_,
525 text: "@java.lang.Override\n"
526 "$deprecation$public java.util.List<$boxed_type$>\n"
527 " ${$get$capitalized_name$List$}$() {\n"
528 " return $name$_;\n" // note: unmodifiable list
529 "}\n");
530 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
531 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_COUNT);
532 printer->Print(
533 variables: variables_,
534 text: "@java.lang.Override\n"
535 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
536 " return $name$_.size();\n"
537 "}\n");
538 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
539 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_INDEXED_GETTER);
540 printer->Print(
541 variables: variables_,
542 text: "@java.lang.Override\n"
543 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
544 " return $repeated_get$(index);\n"
545 "}\n");
546 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
547
548 if (!EnableExperimentalRuntimeForLite() && descriptor_->is_packed() &&
549 context_->HasGeneratedMethods(descriptor: descriptor_->containing_type())) {
550 printer->Print(variables: variables_,
551 text: "private int $name$MemoizedSerializedSize = -1;\n");
552 }
553
554 printer->Print(
555 variables: variables_,
556 text: "private void ensure$capitalized_name$IsMutable() {\n"
557 // Use a temporary to avoid a redundant iget-object.
558 " $field_list_type$ tmp = $name$_;\n"
559 " if (!tmp.isModifiable()) {\n"
560 " $name$_ =\n"
561 " com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
562 " }\n"
563 "}\n");
564
565 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_INDEXED_SETTER);
566 printer->Print(variables: variables_,
567 text: "private void set$capitalized_name$(\n"
568 " int index, $type$ value) {\n"
569 "$null_check$"
570 " ensure$capitalized_name$IsMutable();\n"
571 " $repeated_set$(index, value);\n"
572 "}\n");
573 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_ADDER);
574 printer->Print(variables: variables_,
575 text: "private void add$capitalized_name$($type$ value) {\n"
576 "$null_check$"
577 " ensure$capitalized_name$IsMutable();\n"
578 " $repeated_add$(value);\n"
579 "}\n");
580 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_MULTI_ADDER);
581 printer->Print(variables: variables_,
582 text: "private void addAll$capitalized_name$(\n"
583 " java.lang.Iterable<? extends $boxed_type$> values) {\n"
584 " ensure$capitalized_name$IsMutable();\n"
585 " com.google.protobuf.AbstractMessageLite.addAll(\n"
586 " values, $name$_);\n"
587 "}\n");
588 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER);
589 printer->Print(variables: variables_,
590 text: "private void clear$capitalized_name$() {\n"
591 " $name$_ = $empty_list$;\n"
592 "}\n");
593}
594
595void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers(
596 io::Printer* printer) const {
597 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_GETTER);
598 printer->Print(variables: variables_,
599 text: "@java.lang.Override\n"
600 "$deprecation$public java.util.List<$boxed_type$>\n"
601 " ${$get$capitalized_name$List$}$() {\n"
602 " return java.util.Collections.unmodifiableList(\n"
603 " instance.get$capitalized_name$List());\n"
604 "}\n");
605 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
606 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_COUNT);
607 printer->Print(
608 variables: variables_,
609 text: "@java.lang.Override\n"
610 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
611 " return instance.get$capitalized_name$Count();\n"
612 "}\n");
613 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
614 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_INDEXED_GETTER);
615 printer->Print(
616 variables: variables_,
617 text: "@java.lang.Override\n"
618 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
619 " return instance.get$capitalized_name$(index);\n"
620 "}\n");
621 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
622 WriteFieldAccessorDocComment(printer, field: descriptor_, type: SETTER,
623 /* builder */ true);
624 printer->Print(variables: variables_,
625 text: "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
626 " int index, $type$ value) {\n"
627 " copyOnWrite();\n"
628 " instance.set$capitalized_name$(index, value);\n"
629 " return this;\n"
630 "}\n");
631 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
632 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_ADDER,
633 /* builder */ true);
634 printer->Print(variables: variables_,
635 text: "$deprecation$public Builder "
636 "${$add$capitalized_name$$}$($type$ value) {\n"
637 " copyOnWrite();\n"
638 " instance.add$capitalized_name$(value);\n"
639 " return this;\n"
640 "}\n");
641 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
642 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_MULTI_ADDER,
643 /* builder */ true);
644 printer->Print(variables: variables_,
645 text: "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
646 " java.lang.Iterable<? extends $boxed_type$> values) {\n"
647 " copyOnWrite();\n"
648 " instance.addAll$capitalized_name$(values);\n"
649 " return this;\n"
650 "}\n");
651 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
652 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER,
653 /* builder */ true);
654 printer->Print(
655 variables: variables_,
656 text: "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
657 " copyOnWrite();\n"
658 " instance.clear$capitalized_name$();\n"
659 " return this;\n"
660 "}\n");
661 printer->Annotate(begin_varname: "{", end_varname: "}", descriptor: descriptor_);
662}
663
664void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers(
665 io::Printer* printer) const {
666 printer->Print(
667 variables: variables_,
668 text: "/**\n"
669 " * An uninstantiable, behaviorless type to represent the field in\n"
670 " * generics.\n"
671 " */\n"
672 "@kotlin.OptIn"
673 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
674 "class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
675 " : com.google.protobuf.kotlin.DslProxy()\n");
676
677 WriteFieldDocComment(printer, field: descriptor_);
678 printer->Print(variables: variables_,
679 text: "$kt_deprecation$ val $kt_name$: "
680 "com.google.protobuf.kotlin.DslList"
681 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
682 " @kotlin.jvm.JvmSynthetic\n"
683 " get() = com.google.protobuf.kotlin.DslList(\n"
684 " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
685 " )\n");
686
687 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_ADDER,
688 /* builder */ false);
689 printer->Print(variables: variables_,
690 text: "@kotlin.jvm.JvmSynthetic\n"
691 "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
692 "fun com.google.protobuf.kotlin.DslList"
693 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
694 "add(value: $kt_type$) {\n"
695 " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
696 "}");
697
698 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_ADDER,
699 /* builder */ false);
700 printer->Print(variables: variables_,
701 text: "@kotlin.jvm.JvmSynthetic\n"
702 "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
703 "@Suppress(\"NOTHING_TO_INLINE\")\n"
704 "inline operator fun com.google.protobuf.kotlin.DslList"
705 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
706 "plusAssign(value: $kt_type$) {\n"
707 " add(value)\n"
708 "}");
709
710 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_MULTI_ADDER,
711 /* builder */ false);
712 printer->Print(variables: variables_,
713 text: "@kotlin.jvm.JvmSynthetic\n"
714 "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
715 "fun com.google.protobuf.kotlin.DslList"
716 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
717 "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
718 " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
719 "}");
720
721 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_MULTI_ADDER,
722 /* builder */ false);
723 printer->Print(
724 variables: variables_,
725 text: "@kotlin.jvm.JvmSynthetic\n"
726 "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
727 "@Suppress(\"NOTHING_TO_INLINE\")\n"
728 "inline operator fun com.google.protobuf.kotlin.DslList"
729 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
730 "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
731 " addAll(values)\n"
732 "}");
733
734 WriteFieldAccessorDocComment(printer, field: descriptor_, type: LIST_INDEXED_SETTER,
735 /* builder */ false);
736 printer->Print(
737 variables: variables_,
738 text: "@kotlin.jvm.JvmSynthetic\n"
739 "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
740 "operator fun com.google.protobuf.kotlin.DslList"
741 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
742 "set(index: kotlin.Int, value: $kt_type$) {\n"
743 " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
744 "}");
745
746 WriteFieldAccessorDocComment(printer, field: descriptor_, type: CLEARER,
747 /* builder */ false);
748 printer->Print(variables: variables_,
749 text: "@kotlin.jvm.JvmSynthetic\n"
750 "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
751 "fun com.google.protobuf.kotlin.DslList"
752 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
753 "clear() {\n"
754 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
755 "}");
756}
757
758void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo(
759 io::Printer* printer, std::vector<uint16_t>* output) const {
760 WriteIntToUtf16CharSequence(value: descriptor_->number(), output);
761 WriteIntToUtf16CharSequence(value: GetExperimentalJavaFieldType(field: descriptor_),
762 output);
763 printer->Print(variables: variables_, text: "\"$name$_\",\n");
764}
765
766void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateInitializationCode(
767 io::Printer* printer) const {
768 printer->Print(variables: variables_, text: "$name$_ = $empty_list$;\n");
769}
770
771std::string RepeatedImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
772 return BoxedPrimitiveTypeName(type: GetJavaType(field: descriptor_));
773}
774
775} // namespace java
776} // namespace compiler
777} // namespace protobuf
778} // namespace google
779