1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 // Author: kenton@google.com (Kenton Varda)
9 // Based on original Protocol Buffers design by
10 // Sanjay Ghemawat, Jeff Dean, and others.
11
12 #include "google/protobuf/compiler/java/lite/message_field.h"
13
14 #include <cstdint>
15 #include <string>
16
17 #include "absl/strings/str_cat.h"
18 #include "google/protobuf/compiler/java/context.h"
19 #include "google/protobuf/compiler/java/doc_comment.h"
20 #include "google/protobuf/compiler/java/field_common.h"
21 #include "google/protobuf/compiler/java/helpers.h"
22 #include "google/protobuf/compiler/java/internal_helpers.h"
23 #include "google/protobuf/compiler/java/name_resolver.h"
24 #include "google/protobuf/io/printer.h"
25 #include "google/protobuf/wire_format.h"
26
27 // Must be last.
28 #include "google/protobuf/port_def.inc"
29
30 namespace google {
31 namespace protobuf {
32 namespace compiler {
33 namespace java {
34 using Semantic = ::google::protobuf::io::AnnotationCollector::Semantic;
35
36 namespace {
37
SetMessageVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,absl::flat_hash_map<absl::string_view,std::string> * variables,Context * context)38 void SetMessageVariables(
39 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
40 const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
41 absl::flat_hash_map<absl::string_view, std::string>* variables,
42 Context* context) {
43 SetCommonFieldVariables(descriptor, info, variables);
44
45 (*variables)["type"] =
46 name_resolver->GetImmutableClassName(descriptor->message_type());
47 variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])});
48 (*variables)["mutable_type"] =
49 name_resolver->GetMutableClassName(descriptor->message_type());
50 (*variables)["group_or_message"] =
51 (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? "Group"
52 : "Message";
53 // TODO: Add @deprecated javadoc when generating javadoc is supported
54 // by the proto compiler
55 (*variables)["deprecation"] =
56 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
57 variables->insert(
58 {"kt_deprecation",
59 descriptor->options().deprecated()
60 ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
61 (*variables)["name"], " is deprecated\") ")
62 : ""});
63 (*variables)["required"] = descriptor->is_required() ? "true" : "false";
64
65 if (HasHasbit(descriptor)) {
66 // For singular messages and builders, one bit is used for the hasField bit.
67 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
68
69 // Note that these have a trailing ";".
70 (*variables)["set_has_field_bit_message"] =
71 absl::StrCat(GenerateSetBit(messageBitIndex), ";");
72 (*variables)["clear_has_field_bit_message"] =
73 absl::StrCat(GenerateClearBit(messageBitIndex), ";");
74
75 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
76 } else {
77 (*variables)["set_has_field_bit_message"] = "";
78 (*variables)["clear_has_field_bit_message"] = "";
79
80 variables->insert({"is_field_present_message",
81 absl::StrCat((*variables)["name"], "_ != null")});
82 }
83
84 (*variables)["get_has_field_bit_from_local"] =
85 GenerateGetBitFromLocal(builderBitIndex);
86 (*variables)["set_has_field_bit_to_local"] =
87 GenerateSetBitToLocal(messageBitIndex);
88
89 // Annotations often use { and } to determine ranges.
90 (*variables)["{"] = "";
91 (*variables)["}"] = "";
92 }
93
94 } // namespace
95
96 // ===================================================================
97
ImmutableMessageFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)98 ImmutableMessageFieldLiteGenerator::ImmutableMessageFieldLiteGenerator(
99 const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
100 : descriptor_(descriptor),
101 messageBitIndex_(messageBitIndex),
102 name_resolver_(context->GetNameResolver()),
103 context_(context) {
104 SetMessageVariables(descriptor, messageBitIndex, 0,
105 context->GetFieldGeneratorInfo(descriptor),
106 name_resolver_, &variables_, context);
107 }
108
~ImmutableMessageFieldLiteGenerator()109 ImmutableMessageFieldLiteGenerator::~ImmutableMessageFieldLiteGenerator() {}
110
GetNumBitsForMessage() const111 int ImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const {
112 // TODO: We don't need a has bit for messages as they have null
113 // sentinels and no user should be reflecting on this. We could save some
114 // bits by setting to 0 and updating the runtimes but this might come at a
115 // runtime performance cost since we can't memoize has-bit reads.
116 return HasHasbit(descriptor_) ? 1 : 0;
117 }
118
GenerateInterfaceMembers(io::Printer * printer) const119 void ImmutableMessageFieldLiteGenerator::GenerateInterfaceMembers(
120 io::Printer* printer) const {
121 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
122 context_->options());
123 printer->Print(variables_,
124 "$deprecation$boolean ${$has$capitalized_name$$}$();\n");
125 printer->Annotate("{", "}", descriptor_);
126 WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
127 context_->options());
128 printer->Print(variables_,
129 "$deprecation$$type$ ${$get$capitalized_name$$}$();\n");
130 printer->Annotate("{", "}", descriptor_);
131 }
132
GenerateMembers(io::Printer * printer) const133 void ImmutableMessageFieldLiteGenerator::GenerateMembers(
134 io::Printer* printer) const {
135
136 printer->Print(variables_, "private $type$ $name$_;\n");
137 PrintExtraFieldInfo(variables_, printer);
138
139 if (HasHasbit(descriptor_)) {
140 WriteFieldDocComment(printer, descriptor_, context_->options());
141 printer->Print(
142 variables_,
143 "@java.lang.Override\n"
144 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
145 " return $get_has_field_bit_message$;\n"
146 "}\n");
147 printer->Annotate("{", "}", descriptor_);
148 WriteFieldDocComment(printer, descriptor_, context_->options());
149 printer->Print(
150 variables_,
151 "@java.lang.Override\n"
152 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
153 " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
154 "}\n");
155 printer->Annotate("{", "}", descriptor_);
156 } else {
157 WriteFieldDocComment(printer, descriptor_, context_->options());
158 printer->Print(
159 variables_,
160 "@java.lang.Override\n"
161 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
162 " return $name$_ != null;\n"
163 "}\n");
164 printer->Annotate("{", "}", descriptor_);
165 WriteFieldDocComment(printer, descriptor_, context_->options());
166 printer->Print(
167 variables_,
168 "@java.lang.Override\n"
169 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
170 " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
171 "}\n");
172 printer->Annotate("{", "}", descriptor_);
173 }
174
175 // Field.Builder setField(Field value)
176 WriteFieldDocComment(printer, descriptor_, context_->options());
177 printer->Print(variables_,
178 "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
179 "private void set$capitalized_name$($type$ value) {\n"
180 " value.getClass(); // minimal bytecode null check\n"
181 " $name$_ = value;\n"
182 " $set_has_field_bit_message$\n"
183 " }\n");
184
185 // Field.Builder mergeField(Field value)
186 WriteFieldDocComment(printer, descriptor_, context_->options());
187 printer->Print(
188 variables_,
189 "@java.lang.SuppressWarnings({\"ReferenceEquality\", "
190 "\"ReturnValueIgnored\"})\n"
191 "private void merge$capitalized_name$($type$ value) {\n"
192 " value.getClass(); // minimal bytecode null check\n"
193 " if ($name$_ != null &&\n"
194 " $name$_ != $type$.getDefaultInstance()) {\n"
195 " $name$_ =\n"
196 " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
197 " } else {\n"
198 " $name$_ = value;\n"
199 " }\n"
200 " $set_has_field_bit_message$\n"
201 "}\n");
202
203 // Field.Builder clearField()
204 WriteFieldDocComment(printer, descriptor_, context_->options());
205 printer->Print(variables_,
206 "private void clear$capitalized_name$() {"
207 " $name$_ = null;\n"
208 " $clear_has_field_bit_message$\n"
209 "}\n");
210 }
211
GenerateBuilderMembers(io::Printer * printer) const212 void ImmutableMessageFieldLiteGenerator::GenerateBuilderMembers(
213 io::Printer* printer) const {
214 // The comments above the methods below are based on a hypothetical
215 // field of type "Field" called "Field".
216
217 // boolean hasField()
218 WriteFieldDocComment(printer, descriptor_, context_->options());
219 printer->Print(variables_,
220 "@java.lang.Override\n"
221 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
222 " return instance.has$capitalized_name$();\n"
223 "}\n");
224 printer->Annotate("{", "}", descriptor_);
225
226 // Field getField()
227 WriteFieldDocComment(printer, descriptor_, context_->options());
228 printer->Print(variables_,
229 "@java.lang.Override\n"
230 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
231 " return instance.get$capitalized_name$();\n"
232 "}\n");
233 printer->Annotate("{", "}", descriptor_);
234
235 // Field.Builder setField(Field value)
236 WriteFieldDocComment(printer, descriptor_, context_->options());
237 printer->Print(variables_,
238 "$deprecation$public Builder "
239 "${$set$capitalized_name$$}$($type$ value) {\n"
240 " copyOnWrite();\n"
241 " instance.set$capitalized_name$(value);\n"
242 " return this;\n"
243 " }\n");
244 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
245
246 // Field.Builder setField(Field.Builder builderForValue)
247 WriteFieldDocComment(printer, descriptor_, context_->options());
248 printer->Print(variables_,
249 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
250 " $type$.Builder builderForValue) {\n"
251 " copyOnWrite();\n"
252 " instance.set$capitalized_name$(builderForValue.build());\n"
253 " return this;\n"
254 "}\n");
255 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
256
257 // Field.Builder mergeField(Field value)
258 WriteFieldDocComment(printer, descriptor_, context_->options());
259 printer->Print(variables_,
260 "$deprecation$public Builder "
261 "${$merge$capitalized_name$$}$($type$ value) {\n"
262 " copyOnWrite();\n"
263 " instance.merge$capitalized_name$(value);\n"
264 " return this;\n"
265 "}\n");
266 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
267
268 // Field.Builder clearField()
269 WriteFieldDocComment(printer, descriptor_, context_->options());
270 printer->Print(variables_,
271 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {"
272 " copyOnWrite();\n"
273 " instance.clear$capitalized_name$();\n"
274 " return this;\n"
275 "}\n");
276 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
277 }
278
GenerateKotlinDslMembers(io::Printer * printer) const279 void ImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers(
280 io::Printer* printer) const {
281 auto vars = printer->WithVars(variables_);
282 JvmNameContext name_ctx = {context_->options(), printer};
283 WriteFieldDocComment(printer, descriptor_, context_->options(),
284 /* kdoc */ true);
285 printer->Emit(
286 {
287 {"jvm_name_get",
288 [&] { JvmName("${$get$kt_capitalized_name$$}$", name_ctx); }},
289 {"jvm_name_set",
290 [&] { JvmName("${$set$kt_capitalized_name$$}$", name_ctx); }},
291 },
292 "$kt_deprecation$public var $kt_name$: $kt_type$\n"
293 " $jvm_name_get$"
294 " get() = $kt_dsl_builder$.${$$kt_safe_name$$}$\n"
295 " $jvm_name_set$"
296 " set(value) {\n"
297 " $kt_dsl_builder$.${$$kt_safe_name$$}$ = value\n"
298 " }\n");
299
300 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
301 context_->options(),
302 /* builder */ false, /* kdoc */ true);
303 printer->Print(
304 "public fun ${$clear$kt_capitalized_name$$}$() {\n"
305 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
306 "}\n");
307
308 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
309 context_->options(),
310 /* builder */ false, /* kdoc */ true);
311 printer->Print(
312 "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
313 " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
314 "}\n");
315 GenerateKotlinOrNull(printer);
316 }
317
GenerateKotlinOrNull(io::Printer * printer) const318 void ImmutableMessageFieldLiteGenerator::GenerateKotlinOrNull(
319 io::Printer* printer) const {
320 if (descriptor_->has_presence() &&
321 descriptor_->real_containing_oneof() == nullptr) {
322 printer->Print(
323 "$kt_deprecation$\n"
324 "public val $classname$Kt.Dsl.$name$OrNull: $kt_type$?\n"
325 " get() = $kt_dsl_builder$.$name$OrNull\n");
326 }
327 }
328
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const329 void ImmutableMessageFieldLiteGenerator::GenerateFieldInfo(
330 io::Printer* printer, std::vector<uint16_t>* output) const {
331 WriteIntToUtf16CharSequence(descriptor_->number(), output);
332 WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
333 output);
334 if (HasHasbit(descriptor_)) {
335 WriteIntToUtf16CharSequence(messageBitIndex_, output);
336 }
337 printer->Print(variables_, "\"$name$_\",\n");
338 }
339
GenerateInitializationCode(io::Printer * printer) const340 void ImmutableMessageFieldLiteGenerator::GenerateInitializationCode(
341 io::Printer* printer) const {}
342
GetBoxedType() const343 std::string ImmutableMessageFieldLiteGenerator::GetBoxedType() const {
344 return name_resolver_->GetImmutableClassName(descriptor_->message_type());
345 }
346
347 // ===================================================================
348
349 ImmutableMessageOneofFieldLiteGenerator::
ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)350 ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
351 int messageBitIndex,
352 Context* context)
353 : ImmutableMessageFieldLiteGenerator(descriptor, messageBitIndex, context) {
354 const OneofGeneratorInfo* info =
355 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
356 SetCommonOneofVariables(descriptor, info, &variables_);
357 }
358
359 ImmutableMessageOneofFieldLiteGenerator::
~ImmutableMessageOneofFieldLiteGenerator()360 ~ImmutableMessageOneofFieldLiteGenerator() {}
361
GenerateMembers(io::Printer * printer) const362 void ImmutableMessageOneofFieldLiteGenerator::GenerateMembers(
363 io::Printer* printer) const {
364 PrintExtraFieldInfo(variables_, printer);
365 WriteFieldDocComment(printer, descriptor_, context_->options());
366 printer->Print(variables_,
367 "@java.lang.Override\n"
368 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
369 " return $has_oneof_case_message$;\n"
370 "}\n");
371 printer->Annotate("{", "}", descriptor_);
372 WriteFieldDocComment(printer, descriptor_, context_->options());
373 printer->Print(variables_,
374 "@java.lang.Override\n"
375 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
376 " if ($has_oneof_case_message$) {\n"
377 " return ($type$) $oneof_name$_;\n"
378 " }\n"
379 " return $type$.getDefaultInstance();\n"
380 "}\n");
381 printer->Annotate("{", "}", descriptor_);
382
383 // Field.Builder setField(Field value)
384 WriteFieldDocComment(printer, descriptor_, context_->options());
385 printer->Print(variables_,
386 "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
387 "private void set$capitalized_name$($type$ value) {\n"
388 " value.getClass(); // minimal bytecode null check\n"
389 " $oneof_name$_ = value;\n"
390 " $set_oneof_case_message$;\n"
391 "}\n");
392
393 // Field.Builder mergeField(Field value)
394 WriteFieldDocComment(printer, descriptor_, context_->options());
395 printer->Print(
396 variables_,
397 "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
398 "private void merge$capitalized_name$($type$ value) {\n"
399 " value.getClass(); // minimal bytecode null check\n"
400 " if ($has_oneof_case_message$ &&\n"
401 " $oneof_name$_ != $type$.getDefaultInstance()) {\n"
402 " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n"
403 " .mergeFrom(value).buildPartial();\n"
404 " } else {\n"
405 " $oneof_name$_ = value;\n"
406 " }\n"
407 " $set_oneof_case_message$;\n"
408 "}\n");
409
410 // Field.Builder clearField()
411 WriteFieldDocComment(printer, descriptor_, context_->options());
412 printer->Print(variables_,
413 "private void clear$capitalized_name$() {\n"
414 " if ($has_oneof_case_message$) {\n"
415 " $clear_oneof_case_message$;\n"
416 " $oneof_name$_ = null;\n"
417 " }\n"
418 "}\n");
419 }
420
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const421 void ImmutableMessageOneofFieldLiteGenerator::GenerateFieldInfo(
422 io::Printer* printer, std::vector<uint16_t>* output) const {
423 WriteIntToUtf16CharSequence(descriptor_->number(), output);
424 WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
425 output);
426 WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output);
427 printer->Print(variables_, "$oneof_stored_type$.class,\n");
428 }
429
GenerateBuilderMembers(io::Printer * printer) const430 void ImmutableMessageOneofFieldLiteGenerator::GenerateBuilderMembers(
431 io::Printer* printer) const {
432 // The comments above the methods below are based on a hypothetical
433 // field of type "Field" called "Field".
434
435 // boolean hasField()
436 WriteFieldDocComment(printer, descriptor_, context_->options());
437 printer->Print(variables_,
438 "@java.lang.Override\n"
439 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
440 " return instance.has$capitalized_name$();\n"
441 "}\n");
442 printer->Annotate("{", "}", descriptor_);
443
444 // Field getField()
445 WriteFieldDocComment(printer, descriptor_, context_->options());
446 printer->Print(variables_,
447 "@java.lang.Override\n"
448 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
449 " return instance.get$capitalized_name$();\n"
450 "}\n");
451 printer->Annotate("{", "}", descriptor_);
452
453 // Field.Builder setField(Field value)
454 WriteFieldDocComment(printer, descriptor_, context_->options());
455 printer->Print(variables_,
456 "$deprecation$public Builder "
457 "${$set$capitalized_name$$}$($type$ value) {\n"
458 " copyOnWrite();\n"
459 " instance.set$capitalized_name$(value);\n"
460 " return this;\n"
461 "}\n");
462 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
463
464 // Field.Builder setField(Field.Builder builderForValue)
465 WriteFieldDocComment(printer, descriptor_, context_->options());
466 printer->Print(variables_,
467 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
468 " $type$.Builder builderForValue) {\n"
469 " copyOnWrite();\n"
470 " instance.set$capitalized_name$(builderForValue.build());\n"
471 " return this;\n"
472 "}\n");
473 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
474
475 // Field.Builder mergeField(Field value)
476 WriteFieldDocComment(printer, descriptor_, context_->options());
477 printer->Print(variables_,
478 "$deprecation$public Builder "
479 "${$merge$capitalized_name$$}$($type$ value) {\n"
480 " copyOnWrite();\n"
481 " instance.merge$capitalized_name$(value);\n"
482 " return this;\n"
483 "}\n");
484 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
485
486 // Field.Builder clearField()
487 WriteFieldDocComment(printer, descriptor_, context_->options());
488 printer->Print(
489 variables_,
490 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
491 " copyOnWrite();\n"
492 " instance.clear$capitalized_name$();\n"
493 " return this;\n"
494 "}\n");
495 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
496 }
497
498 // ===================================================================
499
500 RepeatedImmutableMessageFieldLiteGenerator::
RepeatedImmutableMessageFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)501 RepeatedImmutableMessageFieldLiteGenerator(
502 const FieldDescriptor* descriptor, int messageBitIndex,
503 Context* context)
504 : descriptor_(descriptor),
505 name_resolver_(context->GetNameResolver()),
506 context_(context) {
507 SetMessageVariables(descriptor, messageBitIndex, 0,
508 context->GetFieldGeneratorInfo(descriptor),
509 name_resolver_, &variables_, context);
510 }
511
512 RepeatedImmutableMessageFieldLiteGenerator::
~RepeatedImmutableMessageFieldLiteGenerator()513 ~RepeatedImmutableMessageFieldLiteGenerator() {}
514
GetNumBitsForMessage() const515 int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const {
516 return 0;
517 }
518
GenerateInterfaceMembers(io::Printer * printer) const519 void RepeatedImmutableMessageFieldLiteGenerator::GenerateInterfaceMembers(
520 io::Printer* printer) const {
521 // TODO: In the future, consider having methods specific to the
522 // interface so that builders can choose dynamically to either return a
523 // message or a nested builder, so that asking for the interface doesn't
524 // cause a message to ever be built.
525 WriteFieldDocComment(printer, descriptor_, context_->options());
526 printer->Print(variables_,
527 "$deprecation$java.util.List<$type$> \n"
528 " ${$get$capitalized_name$List$}$();\n");
529 printer->Annotate("{", "}", descriptor_);
530 WriteFieldDocComment(printer, descriptor_, context_->options());
531 printer->Print(
532 variables_,
533 "$deprecation$$type$ ${$get$capitalized_name$$}$(int index);\n");
534 printer->Annotate("{", "}", descriptor_);
535 WriteFieldDocComment(printer, descriptor_, context_->options());
536 printer->Print(variables_,
537 "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
538 printer->Annotate("{", "}", descriptor_);
539 }
540
GenerateMembers(io::Printer * printer) const541 void RepeatedImmutableMessageFieldLiteGenerator::GenerateMembers(
542 io::Printer* printer) const {
543 printer->Print(
544 variables_,
545 "private com.google.protobuf.Internal.ProtobufList<$type$> $name$_;\n");
546 PrintExtraFieldInfo(variables_, printer);
547 WriteFieldDocComment(printer, descriptor_, context_->options());
548 printer->Print(variables_,
549 "@java.lang.Override\n"
550 "$deprecation$public java.util.List<$type$> "
551 "${$get$capitalized_name$List$}$() {\n"
552 " return $name$_;\n" // note: unmodifiable list
553 "}\n");
554 printer->Annotate("{", "}", descriptor_);
555 WriteFieldDocComment(printer, descriptor_, context_->options());
556 printer->Print(
557 variables_,
558 "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
559 " ${$get$capitalized_name$OrBuilderList$}$() {\n"
560 " return $name$_;\n"
561 "}\n");
562 printer->Annotate("{", "}", descriptor_);
563 WriteFieldDocComment(printer, descriptor_, context_->options());
564 printer->Print(
565 variables_,
566 "@java.lang.Override\n"
567 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
568 " return $name$_.size();\n"
569 "}\n");
570 printer->Annotate("{", "}", descriptor_);
571 WriteFieldDocComment(printer, descriptor_, context_->options());
572 printer->Print(
573 variables_,
574 "@java.lang.Override\n"
575 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
576 " return $name$_.get(index);\n"
577 "}\n");
578 printer->Annotate("{", "}", descriptor_);
579 WriteFieldDocComment(printer, descriptor_, context_->options());
580 printer->Print(variables_,
581 "$deprecation$public $type$OrBuilder "
582 "${$get$capitalized_name$OrBuilder$}$(\n"
583 " int index) {\n"
584 " return $name$_.get(index);\n"
585 "}\n");
586 printer->Annotate("{", "}", descriptor_);
587
588 printer->Print(
589 variables_,
590 "private void ensure$capitalized_name$IsMutable() {\n"
591 // Use a temporary to avoid a redundant iget-object.
592 " com.google.protobuf.Internal.ProtobufList<$type$> tmp = $name$_;\n"
593 " if (!tmp.isModifiable()) {\n"
594 " $name$_ =\n"
595 " com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
596 " }\n"
597 "}\n"
598 "\n");
599
600 // Builder setRepeatedField(int index, Field value)
601 WriteFieldDocComment(printer, descriptor_, context_->options());
602 printer->Print(variables_,
603 "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
604 "private void set$capitalized_name$(\n"
605 " int index, $type$ value) {\n"
606 " value.getClass(); // minimal bytecode null check\n"
607 " ensure$capitalized_name$IsMutable();\n"
608 " $name$_.set(index, value);\n"
609 "}\n");
610
611 // Builder addRepeatedField(Field value)
612 WriteFieldDocComment(printer, descriptor_, context_->options());
613 printer->Print(variables_,
614 "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
615 "private void add$capitalized_name$($type$ value) {\n"
616 " value.getClass(); // minimal bytecode null check\n"
617 " ensure$capitalized_name$IsMutable();\n"
618 " $name$_.add(value);\n"
619 "}\n");
620
621 // Builder addRepeatedField(int index, Field value)
622 WriteFieldDocComment(printer, descriptor_, context_->options());
623 printer->Print(variables_,
624 "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
625 "private void add$capitalized_name$(\n"
626 " int index, $type$ value) {\n"
627 " value.getClass(); // minimal bytecode null check\n"
628 " ensure$capitalized_name$IsMutable();\n"
629 " $name$_.add(index, value);\n"
630 "}\n");
631
632 // Builder addAllRepeatedField(Iterable<Field> values)
633 WriteFieldDocComment(printer, descriptor_, context_->options());
634 printer->Print(variables_,
635 "private void addAll$capitalized_name$(\n"
636 " java.lang.Iterable<? extends $type$> values) {\n"
637 " ensure$capitalized_name$IsMutable();\n"
638 " com.google.protobuf.AbstractMessageLite.addAll(\n"
639 " values, $name$_);\n"
640 "}\n");
641
642 // Builder clearAllRepeatedField()
643 WriteFieldDocComment(printer, descriptor_, context_->options());
644 printer->Print(variables_,
645 "private void clear$capitalized_name$() {\n"
646 " $name$_ = emptyProtobufList();\n"
647 "}\n");
648
649 // Builder removeRepeatedField(int index)
650 WriteFieldDocComment(printer, descriptor_, context_->options());
651 printer->Print(variables_,
652 "private void remove$capitalized_name$(int index) {\n"
653 " ensure$capitalized_name$IsMutable();\n"
654 " $name$_.remove(index);\n"
655 "}\n");
656 }
657
GenerateBuilderMembers(io::Printer * printer) const658 void RepeatedImmutableMessageFieldLiteGenerator::GenerateBuilderMembers(
659 io::Printer* printer) const {
660 // The comments above the methods below are based on a hypothetical
661 // repeated field of type "Field" called "RepeatedField".
662
663 // List<Field> getRepeatedFieldList()
664 WriteFieldDocComment(printer, descriptor_, context_->options());
665 printer->Print(variables_,
666 "@java.lang.Override\n"
667 "$deprecation$public java.util.List<$type$> "
668 "${$get$capitalized_name$List$}$() {\n"
669 " return java.util.Collections.unmodifiableList(\n"
670 " instance.get$capitalized_name$List());\n"
671 "}\n");
672 printer->Annotate("{", "}", descriptor_);
673
674 // int getRepeatedFieldCount()
675 WriteFieldDocComment(printer, descriptor_, context_->options());
676 printer->Print(
677 variables_,
678 "@java.lang.Override\n"
679 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
680 " return instance.get$capitalized_name$Count();\n"
681 "}");
682 printer->Annotate("{", "}", descriptor_);
683
684 // Field getRepeatedField(int index)
685 WriteFieldDocComment(printer, descriptor_, context_->options());
686 printer->Print(
687 variables_,
688 "@java.lang.Override\n"
689 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
690 " return instance.get$capitalized_name$(index);\n"
691 "}\n");
692 printer->Annotate("{", "}", descriptor_);
693
694 // Builder setRepeatedField(int index, Field value)
695 WriteFieldDocComment(printer, descriptor_, context_->options());
696 printer->Print(variables_,
697 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
698 " int index, $type$ value) {\n"
699 " copyOnWrite();\n"
700 " instance.set$capitalized_name$(index, value);\n"
701 " return this;\n"
702 "}\n");
703 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
704
705 // Builder setRepeatedField(int index, Field.Builder builderForValue)
706 WriteFieldDocComment(printer, descriptor_, context_->options());
707 printer->Print(variables_,
708 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
709 " int index, $type$.Builder builderForValue) {\n"
710 " copyOnWrite();\n"
711 " instance.set$capitalized_name$(index,\n"
712 " builderForValue.build());\n"
713 " return this;\n"
714 "}\n");
715 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
716
717 // Builder addRepeatedField(Field value)
718 WriteFieldDocComment(printer, descriptor_, context_->options());
719 printer->Print(variables_,
720 "$deprecation$public Builder "
721 "${$add$capitalized_name$$}$($type$ value) {\n"
722 " copyOnWrite();\n"
723 " instance.add$capitalized_name$(value);\n"
724 " return this;\n"
725 "}\n");
726 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
727
728 // Builder addRepeatedField(int index, Field value)
729 WriteFieldDocComment(printer, descriptor_, context_->options());
730 printer->Print(variables_,
731 "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
732 " int index, $type$ value) {\n"
733 " copyOnWrite();\n"
734 " instance.add$capitalized_name$(index, value);\n"
735 " return this;\n"
736 "}\n");
737 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
738 // Builder addRepeatedField(Field.Builder builderForValue)
739 WriteFieldDocComment(printer, descriptor_, context_->options());
740 printer->Print(variables_,
741 "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
742 " $type$.Builder builderForValue) {\n"
743 " copyOnWrite();\n"
744 " instance.add$capitalized_name$(builderForValue.build());\n"
745 " return this;\n"
746 "}\n");
747 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
748
749 // Builder addRepeatedField(int index, Field.Builder builderForValue)
750 WriteFieldDocComment(printer, descriptor_, context_->options());
751 printer->Print(variables_,
752 "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
753 " int index, $type$.Builder builderForValue) {\n"
754 " copyOnWrite();\n"
755 " instance.add$capitalized_name$(index,\n"
756 " builderForValue.build());\n"
757 " return this;\n"
758 "}\n");
759 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
760
761 // Builder addAllRepeatedField(Iterable<Field> values)
762 WriteFieldDocComment(printer, descriptor_, context_->options());
763 printer->Print(variables_,
764 "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
765 " java.lang.Iterable<? extends $type$> values) {\n"
766 " copyOnWrite();\n"
767 " instance.addAll$capitalized_name$(values);\n"
768 " return this;\n"
769 "}\n");
770 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
771
772 // Builder clearAllRepeatedField()
773 WriteFieldDocComment(printer, descriptor_, context_->options());
774 printer->Print(
775 variables_,
776 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
777 " copyOnWrite();\n"
778 " instance.clear$capitalized_name$();\n"
779 " return this;\n"
780 "}\n");
781 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
782
783 // Builder removeRepeatedField(int index)
784 WriteFieldDocComment(printer, descriptor_, context_->options());
785 printer->Print(variables_,
786 "$deprecation$public Builder "
787 "${$remove$capitalized_name$$}$(int index) {\n"
788 " copyOnWrite();\n"
789 " instance.remove$capitalized_name$(index);\n"
790 " return this;\n"
791 "}\n");
792 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
793 }
794
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const795 void RepeatedImmutableMessageFieldLiteGenerator::GenerateFieldInfo(
796 io::Printer* printer, std::vector<uint16_t>* output) const {
797 WriteIntToUtf16CharSequence(descriptor_->number(), output);
798 WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
799 output);
800 printer->Print(variables_,
801 "\"$name$_\",\n"
802 "$type$.class,\n");
803 }
804
GenerateInitializationCode(io::Printer * printer) const805 void RepeatedImmutableMessageFieldLiteGenerator::GenerateInitializationCode(
806 io::Printer* printer) const {
807 printer->Print(variables_, "$name$_ = emptyProtobufList();\n");
808 }
809
GetBoxedType() const810 std::string RepeatedImmutableMessageFieldLiteGenerator::GetBoxedType() const {
811 return name_resolver_->GetImmutableClassName(descriptor_->message_type());
812 }
813
GenerateKotlinDslMembers(io::Printer * printer) const814 void RepeatedImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers(
815 io::Printer* printer) const {
816 auto vars = printer->WithVars(variables_);
817 JvmNameContext name_ctx = {context_->options(), printer};
818 printer->Print(
819 "/**\n"
820 " * An uninstantiable, behaviorless type to represent the field in\n"
821 " * generics.\n"
822 " */\n"
823 "@kotlin.OptIn"
824 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
825 "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
826 " : com.google.protobuf.kotlin.DslProxy()\n");
827
828 WriteFieldDocComment(printer, descriptor_, context_->options(),
829 /* kdoc */ true);
830 printer->Print(
831 "$kt_deprecation$ public val $kt_name$: "
832 "com.google.protobuf.kotlin.DslList"
833 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
834 "$ jvm_synthetic$"
835 " get() = com.google.protobuf.kotlin.DslList(\n"
836 " $kt_dsl_builder$.${$$kt_property_name$List$}$\n"
837 " )\n");
838
839 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
840 context_->options(),
841 /* builder */ false, /* kdoc */ true);
842 printer->Emit(
843 {
844 {"jvm_name", [&] { JvmName("add$kt_capitalized_name$", name_ctx); }},
845 },
846 "$jvm_synthetic$"
847 "$jvm_name$"
848 "public fun com.google.protobuf.kotlin.DslList"
849 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
850 "add(value: $kt_type$) {\n"
851 " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
852 "}\n");
853
854 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
855 context_->options(),
856 /* builder */ false, /* kdoc */ true);
857 printer->Emit(
858 {
859 {"jvm_name",
860 [&] { JvmName("plusAssign$kt_capitalized_name$", name_ctx); }},
861 },
862 "$jvm_synthetic$"
863 "$jvm_name$"
864 "@Suppress(\"NOTHING_TO_INLINE\")\n"
865 "public inline operator fun com.google.protobuf.kotlin.DslList"
866 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
867 "plusAssign(value: $kt_type$) {\n"
868 " add(value)\n"
869 "}\n");
870
871 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
872 context_->options(),
873 /* builder */ false, /* kdoc */ true);
874 printer->Emit(
875 {
876 {"jvm_name",
877 [&] { JvmName("addAll$kt_capitalized_name$", name_ctx); }},
878 },
879 "$jvm_synthetic$"
880 "$jvm_name$"
881 "public fun com.google.protobuf.kotlin.DslList"
882 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
883 "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
884 " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
885 "}\n");
886
887 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
888 context_->options(),
889 /* builder */ false, /* kdoc */ true);
890 printer->Emit(
891 {
892 {"jvm_name",
893 [&] { JvmName("plusAssignAll$kt_capitalized_name$", name_ctx); }},
894 },
895 "$jvm_synthetic$"
896 "$jvm_name$"
897 "@Suppress(\"NOTHING_TO_INLINE\")\n"
898 "public inline operator fun com.google.protobuf.kotlin.DslList"
899 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
900 "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
901 " addAll(values)\n"
902 "}\n");
903
904 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
905 context_->options(),
906 /* builder */ false, /* kdoc */ true);
907 printer->Emit(
908 {
909 {"jvm_name", [&] { JvmName("set$kt_capitalized_name$", name_ctx); }},
910 },
911 "$jvm_synthetic$"
912 "$jvm_name$"
913 "public operator fun com.google.protobuf.kotlin.DslList"
914 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
915 "set(index: kotlin.Int, value: $kt_type$) {\n"
916 " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
917 "}\n");
918
919 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
920 context_->options(),
921 /* builder */ false, /* kdoc */ true);
922 printer->Emit(
923 {
924 {"jvm_name",
925 [&] { JvmName("clear$kt_capitalized_name$", name_ctx); }},
926 },
927
928 "$jvm_synthetic$"
929 "$jvm_name$"
930 "public fun com.google.protobuf.kotlin.DslList"
931 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
932 "clear() {\n"
933 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
934 "}\n");
935 }
936
937 } // namespace java
938 } // namespace compiler
939 } // namespace protobuf
940 } // namespace google
941
942 #include "google/protobuf/port_undef.inc"
943