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/enum_field.h"
13
14 #include <cstdint>
15 #include <string>
16
17 #include "absl/container/flat_hash_map.h"
18 #include "absl/log/absl_check.h"
19 #include "absl/strings/str_cat.h"
20 #include "google/protobuf/compiler/java/context.h"
21 #include "google/protobuf/compiler/java/doc_comment.h"
22 #include "google/protobuf/compiler/java/field_common.h"
23 #include "google/protobuf/compiler/java/helpers.h"
24 #include "google/protobuf/compiler/java/internal_helpers.h"
25 #include "google/protobuf/compiler/java/name_resolver.h"
26 #include "google/protobuf/io/printer.h"
27 #include "google/protobuf/wire_format.h"
28
29 // Must be last.
30 #include "google/protobuf/port_def.inc"
31
32 namespace google {
33 namespace protobuf {
34 namespace compiler {
35 namespace java {
36 using Semantic = ::google::protobuf::io::AnnotationCollector::Semantic;
37
38 namespace {
EnableExperimentalRuntimeForLite()39 bool EnableExperimentalRuntimeForLite() {
40 #ifdef PROTOBUF_EXPERIMENT
41 return PROTOBUF_EXPERIMENT;
42 #else // PROTOBUF_EXPERIMENT
43 return false;
44 #endif // !PROTOBUF_EXPERIMENT
45 }
46
SetEnumVariables(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)47 void SetEnumVariables(
48 const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
49 const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
50 absl::flat_hash_map<absl::string_view, std::string>* variables,
51 Context* context) {
52 SetCommonFieldVariables(descriptor, info, variables);
53
54 (*variables)["type"] =
55 name_resolver->GetImmutableClassName(descriptor->enum_type());
56 variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])});
57 (*variables)["mutable_type"] =
58 name_resolver->GetMutableClassName(descriptor->enum_type());
59 (*variables)["default"] =
60 ImmutableDefaultValue(descriptor, name_resolver, context->options());
61 (*variables)["default_number"] =
62 absl::StrCat(descriptor->default_value_enum()->number());
63 (*variables)["tag"] = absl::StrCat(
64 static_cast<int32_t>(internal::WireFormat::MakeTag(descriptor)));
65 (*variables)["tag_size"] = absl::StrCat(
66 internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
67 // TODO: Add @deprecated javadoc when generating javadoc is supported
68 // by the proto compiler
69 (*variables)["deprecation"] =
70 descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
71 variables->insert(
72 {"kt_deprecation",
73 descriptor->options().deprecated()
74 ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
75 (*variables)["name"], " is deprecated\") ")
76 : ""});
77 (*variables)["required"] = descriptor->is_required() ? "true" : "false";
78
79 if (HasHasbit(descriptor)) {
80 if (!context->options().opensource_runtime) {
81 (*variables)["bit_field_id"] = absl::StrCat(messageBitIndex / 32);
82 (*variables)["bit_field_name"] = GetBitFieldNameForBit(messageBitIndex);
83 (*variables)["bit_field_mask"] =
84 absl::StrCat(1 << (messageBitIndex % 32));
85 }
86 // For singular messages and builders, one bit is used for the hasField bit.
87 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
88
89 // Note that these have a trailing ";".
90 (*variables)["set_has_field_bit_message"] =
91 absl::StrCat(GenerateSetBit(messageBitIndex), ";");
92 (*variables)["clear_has_field_bit_message"] =
93 absl::StrCat(GenerateClearBit(messageBitIndex), ";");
94
95 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
96 } else {
97 (*variables)["set_has_field_bit_message"] = "";
98 (*variables)["clear_has_field_bit_message"] = "";
99
100 variables->insert({"is_field_present_message",
101 absl::StrCat((*variables)["name"], "_ != ",
102 (*variables)["default"], ".getNumber()")});
103 }
104
105 if (SupportUnknownEnumValue(descriptor)) {
106 variables->insert(
107 {"unknown", absl::StrCat((*variables)["type"], ".UNRECOGNIZED")});
108 } else {
109 variables->insert({"unknown", (*variables)["default"]});
110 }
111
112 // Calls to Annotate() use variable ranges to know which text to annotate.
113 (*variables)["{"] = "";
114 (*variables)["}"] = "";
115 }
116
117 } // namespace
118
119 // ===================================================================
120
ImmutableEnumFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)121 ImmutableEnumFieldLiteGenerator::ImmutableEnumFieldLiteGenerator(
122 const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
123 : descriptor_(descriptor),
124 messageBitIndex_(messageBitIndex),
125 context_(context),
126 name_resolver_(context->GetNameResolver()) {
127 SetEnumVariables(descriptor, messageBitIndex, 0,
128 context->GetFieldGeneratorInfo(descriptor), name_resolver_,
129 &variables_, context);
130 }
131
~ImmutableEnumFieldLiteGenerator()132 ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {}
133
GetNumBitsForMessage() const134 int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
135 return HasHasbit(descriptor_) ? 1 : 0;
136 }
137
GenerateInterfaceMembers(io::Printer * printer) const138 void ImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers(
139 io::Printer* printer) const {
140 if (descriptor_->has_presence()) {
141 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
142 context_->options());
143 printer->Print(variables_,
144 "$deprecation$boolean ${$has$capitalized_name$$}$();\n");
145 printer->Annotate("{", "}", descriptor_);
146 }
147 if (SupportUnknownEnumValue(descriptor_)) {
148 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER,
149 context_->options());
150 printer->Print(variables_,
151 "$deprecation$int ${$get$capitalized_name$Value$}$();\n");
152 printer->Annotate("{", "}", descriptor_);
153 }
154 WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
155 context_->options());
156 printer->Print(variables_,
157 "$deprecation$$type$ ${$get$capitalized_name$$}$();\n");
158 printer->Annotate("{", "}", descriptor_);
159 }
160
GenerateMembers(io::Printer * printer) const161 void ImmutableEnumFieldLiteGenerator::GenerateMembers(
162 io::Printer* printer) const {
163 if (!context_->options().opensource_runtime) {
164 printer->Print(variables_,
165 "@com.google.protobuf.ProtoField(\n"
166 " isRequired=$required$)\n");
167 if (HasHasbit(descriptor_)) {
168 printer->Print(variables_,
169 "@com.google.protobuf.ProtoPresenceCheckedField(\n"
170 " presenceBitsId=$bit_field_id$,\n"
171 " mask=$bit_field_mask$)\n");
172 }
173 }
174 printer->Print(variables_, "private int $name$_;\n");
175 PrintExtraFieldInfo(variables_, printer);
176 if (descriptor_->has_presence()) {
177 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
178 context_->options());
179 printer->Print(
180 variables_,
181 "@java.lang.Override\n"
182 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
183 " return $get_has_field_bit_message$;\n"
184 "}\n");
185 printer->Annotate("{", "}", descriptor_);
186 }
187 if (SupportUnknownEnumValue(descriptor_)) {
188 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER,
189 context_->options());
190 printer->Print(
191 variables_,
192 "@java.lang.Override\n"
193 "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
194 " return $name$_;\n"
195 "}\n");
196 printer->Annotate("{", "}", descriptor_);
197 }
198 WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
199 context_->options());
200 printer->Print(variables_,
201 "@java.lang.Override\n"
202 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
203 " $type$ result = $type$.forNumber($name$_);\n"
204 " return result == null ? $unknown$ : result;\n"
205 "}\n");
206 printer->Annotate("{", "}", descriptor_);
207
208 // Generate private setters for the builder to proxy into.
209 if (SupportUnknownEnumValue(descriptor_)) {
210 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
211 context_->options());
212 printer->Print(variables_,
213 "private void set$capitalized_name$Value(int value) {\n"
214 " $set_has_field_bit_message$"
215 " $name$_ = value;\n"
216 "}\n");
217 }
218 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
219 context_->options());
220 printer->Print(variables_,
221 "private void set$capitalized_name$($type$ value) {\n"
222 " $name$_ = value.getNumber();\n"
223 " $set_has_field_bit_message$\n"
224 "}\n");
225 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
226 context_->options());
227 printer->Print(variables_,
228 "private void clear$capitalized_name$() {\n"
229 " $clear_has_field_bit_message$\n"
230 " $name$_ = $default_number$;\n"
231 "}\n");
232 }
233
GenerateBuilderMembers(io::Printer * printer) const234 void ImmutableEnumFieldLiteGenerator::GenerateBuilderMembers(
235 io::Printer* printer) const {
236 if (descriptor_->has_presence()) {
237 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
238 context_->options());
239 printer->Print(
240 variables_,
241 "@java.lang.Override\n"
242 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
243 " return instance.has$capitalized_name$();\n"
244 "}\n");
245 printer->Annotate("{", "}", descriptor_);
246 }
247 if (SupportUnknownEnumValue(descriptor_)) {
248 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER,
249 context_->options());
250 printer->Print(
251 variables_,
252 "@java.lang.Override\n"
253 "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
254 " return instance.get$capitalized_name$Value();\n"
255 "}\n");
256 printer->Annotate("{", "}", descriptor_);
257 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
258 context_->options(),
259 /* builder */ true);
260 printer->Print(variables_,
261 "$deprecation$public Builder "
262 "${$set$capitalized_name$Value$}$(int value) {\n"
263 " copyOnWrite();\n"
264 " instance.set$capitalized_name$Value(value);\n"
265 " return this;\n"
266 "}\n");
267 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
268 }
269 WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
270 context_->options());
271 printer->Print(variables_,
272 "@java.lang.Override\n"
273 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
274 " return instance.get$capitalized_name$();\n"
275 "}\n");
276 printer->Annotate("{", "}", descriptor_);
277 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
278 context_->options(),
279 /* builder */ true);
280 printer->Print(variables_,
281 "$deprecation$public Builder "
282 "${$set$capitalized_name$$}$($type$ value) {\n"
283 " copyOnWrite();\n"
284 " instance.set$capitalized_name$(value);\n"
285 " return this;\n"
286 "}\n");
287 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
288 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
289 context_->options(),
290 /* builder */ true);
291 printer->Print(
292 variables_,
293 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
294 " copyOnWrite();\n"
295 " instance.clear$capitalized_name$();\n"
296 " return this;\n"
297 "}\n");
298 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
299 }
300
GenerateKotlinDslMembers(io::Printer * printer) const301 void ImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
302 io::Printer* printer) const {
303 auto vars = printer->WithVars(variables_);
304 JvmNameContext name_ctx = {context_->options(), printer};
305 WriteFieldDocComment(printer, descriptor_, context_->options(),
306 /* kdoc */ true);
307 printer->Emit(
308 {
309 {"jvm_name_get",
310 [&] { JvmName("${$get$kt_capitalized_name$$}$", name_ctx); }},
311 {"jvm_name_set",
312 [&] { JvmName("${$set$kt_capitalized_name$$}$", name_ctx); }},
313 },
314 "$kt_deprecation$public var $kt_name$: $kt_type$\n"
315 " $jvm_name_get$"
316 " get() = $kt_dsl_builder$.${$$kt_safe_name$$}$\n"
317 " $jvm_name_set$"
318 " set(value) {\n"
319 " $kt_dsl_builder$.${$$kt_safe_name$$}$ = value\n"
320 " }\n");
321
322 if (SupportUnknownEnumValue(descriptor_)) {
323 printer->Emit(
324 {
325 {"jvm_name_get",
326 [&] { JvmName("${$get$kt_capitalized_name$Value$}$", name_ctx); }},
327 {"jvm_name_set",
328 [&] { JvmName("${$set$kt_capitalized_name$Value$}$", name_ctx); }},
329 },
330 "$kt_deprecation$public var $kt_name$Value: kotlin.Int\n"
331 " $jvm_name_get$"
332 " get() = $kt_dsl_builder$.${$$kt_property_name$Value$}$\n"
333 " $jvm_name_set$"
334 " set(value) {\n"
335 " $kt_dsl_builder$.${$$kt_property_name$Value$}$ = value\n"
336 " }\n");
337 }
338
339 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
340 context_->options(),
341 /* builder */ false, /* kdoc */ true);
342 printer->Print(
343 "public fun ${$clear$kt_capitalized_name$$}$() {\n"
344 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
345 "}\n");
346
347 if (descriptor_->has_presence()) {
348 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
349 context_->options(),
350 /* builder */ false, /* kdoc */ true);
351 printer->Print(
352 "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
353 " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
354 "}\n");
355 }
356 }
357
GenerateInitializationCode(io::Printer * printer) const358 void ImmutableEnumFieldLiteGenerator::GenerateInitializationCode(
359 io::Printer* printer) const {
360 if (!IsDefaultValueJavaDefault(descriptor_)) {
361 printer->Print(variables_, "$name$_ = $default_number$;\n");
362 }
363 }
364
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const365 void ImmutableEnumFieldLiteGenerator::GenerateFieldInfo(
366 io::Printer* printer, std::vector<uint16_t>* output) const {
367 WriteIntToUtf16CharSequence(descriptor_->number(), output);
368 WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
369 output);
370 if (HasHasbit(descriptor_)) {
371 WriteIntToUtf16CharSequence(messageBitIndex_, output);
372 }
373 printer->Print(variables_, "\"$name$_\",\n");
374 if (!SupportUnknownEnumValue((descriptor_))) {
375 PrintEnumVerifierLogic(printer, descriptor_, variables_,
376 /*var_name=*/"$type$",
377 /*terminating_string=*/",\n",
378 /*enforce_lite=*/context_->EnforceLite());
379 }
380 }
381
GetBoxedType() const382 std::string ImmutableEnumFieldLiteGenerator::GetBoxedType() const {
383 return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
384 }
385
386 // ===================================================================
387
ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)388 ImmutableEnumOneofFieldLiteGenerator::ImmutableEnumOneofFieldLiteGenerator(
389 const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
390 : ImmutableEnumFieldLiteGenerator(descriptor, messageBitIndex, context) {
391 const OneofGeneratorInfo* info =
392 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
393 SetCommonOneofVariables(descriptor, info, &variables_);
394 }
395
~ImmutableEnumOneofFieldLiteGenerator()396 ImmutableEnumOneofFieldLiteGenerator::~ImmutableEnumOneofFieldLiteGenerator() {}
397
GenerateMembers(io::Printer * printer) const398 void ImmutableEnumOneofFieldLiteGenerator::GenerateMembers(
399 io::Printer* printer) const {
400 PrintExtraFieldInfo(variables_, printer);
401 ABSL_DCHECK(descriptor_->has_presence());
402 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
403 context_->options());
404 printer->Print(variables_,
405 "@java.lang.Override\n"
406 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
407 " return $has_oneof_case_message$;\n"
408 "}\n");
409 printer->Annotate("{", "}", descriptor_);
410
411 if (SupportUnknownEnumValue(descriptor_)) {
412 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER,
413 context_->options());
414 printer->Print(
415 variables_,
416 "@java.lang.Override\n"
417 "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
418 " if ($has_oneof_case_message$) {\n"
419 " return (java.lang.Integer) $oneof_name$_;\n"
420 " }\n"
421 " return $default_number$;\n"
422 "}\n");
423 printer->Annotate("{", "}", descriptor_);
424 }
425 WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
426 context_->options());
427 printer->Print(variables_,
428 "@java.lang.Override\n"
429 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
430 " if ($has_oneof_case_message$) {\n"
431 " $type$ result = $type$.forNumber((java.lang.Integer) "
432 "$oneof_name$_);\n"
433 " return result == null ? $unknown$ : result;\n"
434 " }\n"
435 " return $default$;\n"
436 "}\n");
437 printer->Annotate("{", "}", descriptor_);
438
439 // Generate private setters for the builder to proxy into.
440 if (SupportUnknownEnumValue(descriptor_)) {
441 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
442 context_->options());
443 printer->Print(variables_,
444 "private void set$capitalized_name$Value(int value) {\n"
445 " $set_oneof_case_message$;\n"
446 " $oneof_name$_ = value;\n"
447 "}\n");
448 }
449 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
450 context_->options());
451 printer->Print(variables_,
452 "private void set$capitalized_name$($type$ value) {\n"
453 " $oneof_name$_ = value.getNumber();\n"
454 " $set_oneof_case_message$;\n"
455 "}\n");
456 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
457 context_->options());
458 printer->Print(variables_,
459 "private void clear$capitalized_name$() {\n"
460 " if ($has_oneof_case_message$) {\n"
461 " $clear_oneof_case_message$;\n"
462 " $oneof_name$_ = null;\n"
463 " }\n"
464 "}\n");
465 }
466
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const467 void ImmutableEnumOneofFieldLiteGenerator::GenerateFieldInfo(
468 io::Printer* printer, std::vector<uint16_t>* output) const {
469 WriteIntToUtf16CharSequence(descriptor_->number(), output);
470 WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
471 output);
472 WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output);
473 if (!SupportUnknownEnumValue(descriptor_)) {
474 PrintEnumVerifierLogic(printer, descriptor_, variables_,
475 /*var_name=*/"$type$",
476 /*terminating_string=*/",\n",
477 /*enforce_lite=*/context_->EnforceLite());
478 }
479 }
480
GenerateBuilderMembers(io::Printer * printer) const481 void ImmutableEnumOneofFieldLiteGenerator::GenerateBuilderMembers(
482 io::Printer* printer) const {
483 ABSL_DCHECK(descriptor_->has_presence());
484 WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
485 context_->options());
486 printer->Print(variables_,
487 "@java.lang.Override\n"
488 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
489 " return instance.has$capitalized_name$();\n"
490 "}\n");
491 printer->Annotate("{", "}", descriptor_);
492
493 if (SupportUnknownEnumValue(descriptor_)) {
494 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER,
495 context_->options());
496 printer->Print(
497 variables_,
498 "@java.lang.Override\n"
499 "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
500 " return instance.get$capitalized_name$Value();\n"
501 "}\n");
502 printer->Annotate("{", "}", descriptor_);
503 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
504 context_->options(),
505 /* builder */ true);
506 printer->Print(variables_,
507 "$deprecation$public Builder "
508 "${$set$capitalized_name$Value$}$(int value) {\n"
509 " copyOnWrite();\n"
510 " instance.set$capitalized_name$Value(value);\n"
511 " return this;\n"
512 "}\n");
513 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
514 }
515 WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
516 context_->options());
517 printer->Print(variables_,
518 "@java.lang.Override\n"
519 "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
520 " return instance.get$capitalized_name$();\n"
521 "}\n");
522 printer->Annotate("{", "}", descriptor_);
523 WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
524 context_->options(),
525 /* builder */ true);
526 printer->Print(variables_,
527 "$deprecation$public Builder "
528 "${$set$capitalized_name$$}$($type$ value) {\n"
529 " copyOnWrite();\n"
530 " instance.set$capitalized_name$(value);\n"
531 " return this;\n"
532 "}\n");
533 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
534 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
535 context_->options(),
536 /* builder */ true);
537 printer->Print(
538 variables_,
539 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
540 " copyOnWrite();\n"
541 " instance.clear$capitalized_name$();\n"
542 " return this;\n"
543 "}\n");
544 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
545 }
546
547 // ===================================================================
548
549 RepeatedImmutableEnumFieldLiteGenerator::
RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)550 RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
551 int messageBitIndex,
552 Context* context)
553 : descriptor_(descriptor),
554 context_(context),
555 name_resolver_(context->GetNameResolver()) {
556 SetEnumVariables(descriptor, messageBitIndex, 0,
557 context->GetFieldGeneratorInfo(descriptor), name_resolver_,
558 &variables_, context);
559 }
560
561 RepeatedImmutableEnumFieldLiteGenerator::
~RepeatedImmutableEnumFieldLiteGenerator()562 ~RepeatedImmutableEnumFieldLiteGenerator() {}
563
GetNumBitsForMessage() const564 int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
565 return 0;
566 }
567
GenerateInterfaceMembers(io::Printer * printer) const568 void RepeatedImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers(
569 io::Printer* printer) const {
570 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
571 context_->options());
572 printer->Print(variables_,
573 "$deprecation$java.util.List<$type$> "
574 "${$get$capitalized_name$List$}$();\n");
575 printer->Annotate("{", "}", descriptor_);
576 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT,
577 context_->options());
578 printer->Print(variables_,
579 "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
580 printer->Annotate("{", "}", descriptor_);
581 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER,
582 context_->options());
583 printer->Print(
584 variables_,
585 "$deprecation$$type$ ${$get$capitalized_name$$}$(int index);\n");
586 printer->Annotate("{", "}", descriptor_);
587 if (SupportUnknownEnumValue(descriptor_)) {
588 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER,
589 context_->options());
590 printer->Print(variables_,
591 "$deprecation$java.util.List<java.lang.Integer>\n"
592 "${$get$capitalized_name$ValueList$}$();\n");
593 printer->Annotate("{", "}", descriptor_);
594 WriteFieldEnumValueAccessorDocComment(
595 printer, descriptor_, LIST_INDEXED_GETTER, context_->options());
596 printer->Print(
597 variables_,
598 "$deprecation$int ${$get$capitalized_name$Value$}$(int index);\n");
599 printer->Annotate("{", "}", descriptor_);
600 }
601 }
602
GenerateMembers(io::Printer * printer) const603 void RepeatedImmutableEnumFieldLiteGenerator::GenerateMembers(
604 io::Printer* printer) const {
605 printer->Print(
606 variables_,
607 "private com.google.protobuf.Internal.IntList $name$_;\n"
608 "private static final "
609 "com.google.protobuf.Internal.IntListAdapter.IntConverter<\n"
610 " $type$> $name$_converter_ =\n"
611 " new com.google.protobuf.Internal.IntListAdapter.IntConverter<\n"
612 " $type$>() {\n"
613 " @java.lang.Override\n"
614 " public $type$ convert(int from) {\n"
615 " $type$ result = $type$.forNumber(from);\n"
616 " return result == null ? $unknown$ : result;\n"
617 " }\n"
618 " };\n");
619 PrintExtraFieldInfo(variables_, printer);
620 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
621 context_->options());
622 printer->Print(variables_,
623 "@java.lang.Override\n"
624 "$deprecation$public java.util.List<$type$> "
625 "${$get$capitalized_name$List$}$() {\n"
626 " return new com.google.protobuf.Internal.IntListAdapter<\n"
627 " $type$>($name$_, $name$_converter_);\n"
628 "}\n");
629 printer->Annotate("{", "}", descriptor_);
630 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT,
631 context_->options());
632 printer->Print(
633 variables_,
634 "@java.lang.Override\n"
635 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
636 " return $name$_.size();\n"
637 "}\n");
638 printer->Annotate("{", "}", descriptor_);
639 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER,
640 context_->options());
641 printer->Print(
642 variables_,
643 // NB: Do not use the "$name$_converter_" field; the usage of generics
644 // (and requisite upcasts to Object) prevent optimizations. Even
645 // without any optimizations, the below code is cheaper because it
646 // avoids boxing an int and a checkcast from the generics.
647 "@java.lang.Override\n"
648 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
649 " $type$ result = $type$.forNumber($name$_.getInt(index));\n"
650 " return result == null ? $unknown$ : result;\n"
651 "}\n");
652 printer->Annotate("{", "}", descriptor_);
653 if (SupportUnknownEnumValue(descriptor_)) {
654 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER,
655 context_->options());
656 printer->Print(variables_,
657 "@java.lang.Override\n"
658 "$deprecation$public java.util.List<java.lang.Integer>\n"
659 "${$get$capitalized_name$ValueList$}$() {\n"
660 " return $name$_;\n"
661 "}\n");
662 printer->Annotate("{", "}", descriptor_);
663 WriteFieldEnumValueAccessorDocComment(
664 printer, descriptor_, LIST_INDEXED_GETTER, context_->options());
665 printer->Print(variables_,
666 "@java.lang.Override\n"
667 "$deprecation$public int "
668 "${$get$capitalized_name$Value$}$(int index) {\n"
669 " return $name$_.getInt(index);\n"
670 "}\n");
671 printer->Annotate("{", "}", descriptor_);
672 }
673
674 if (!EnableExperimentalRuntimeForLite() && descriptor_->is_packed() &&
675 context_->HasGeneratedMethods(descriptor_->containing_type())) {
676 printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n");
677 }
678
679 // Generate private setters for the builder to proxy into.
680 printer->Print(
681 variables_,
682 "private void ensure$capitalized_name$IsMutable() {\n"
683 // Use a temporary to avoid a redundant iget-object.
684 " com.google.protobuf.Internal.IntList tmp = $name$_;\n"
685 " if (!tmp.isModifiable()) {\n"
686 " $name$_ =\n"
687 " com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
688 " }\n"
689 "}\n");
690 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
691 context_->options());
692 printer->Print(variables_,
693 "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
694 "private void set$capitalized_name$(\n"
695 " int index, $type$ value) {\n"
696 " value.getClass(); // minimal bytecode null check\n"
697 " ensure$capitalized_name$IsMutable();\n"
698 " $name$_.setInt(index, value.getNumber());\n"
699 "}\n");
700 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
701 context_->options());
702 printer->Print(variables_,
703 "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
704 "private void add$capitalized_name$($type$ value) {\n"
705 " value.getClass(); // minimal bytecode null check\n"
706 " ensure$capitalized_name$IsMutable();\n"
707 " $name$_.addInt(value.getNumber());\n"
708 "}\n");
709 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
710 context_->options());
711 printer->Print(variables_,
712 "private void addAll$capitalized_name$(\n"
713 " java.lang.Iterable<? extends $type$> values) {\n"
714 " ensure$capitalized_name$IsMutable();\n"
715 " for ($type$ value : values) {\n"
716 " $name$_.addInt(value.getNumber());\n"
717 " }\n"
718 "}\n");
719 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
720 context_->options());
721 printer->Print(variables_,
722 "private void clear$capitalized_name$() {\n"
723 " $name$_ = emptyIntList();\n"
724 "}\n");
725
726 if (SupportUnknownEnumValue(descriptor_)) {
727 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
728 context_->options());
729 printer->Print(variables_,
730 "private void set$capitalized_name$Value(\n"
731 " int index, int value) {\n"
732 " ensure$capitalized_name$IsMutable();\n"
733 " $name$_.setInt(index, value);\n"
734 "}\n");
735 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER,
736 context_->options());
737 printer->Print(variables_,
738 "private void add$capitalized_name$Value(int value) {\n"
739 " ensure$capitalized_name$IsMutable();\n"
740 " $name$_.addInt(value);\n"
741 "}\n");
742 WriteFieldEnumValueAccessorDocComment(
743 printer, descriptor_, LIST_MULTI_ADDER, context_->options());
744 printer->Print(variables_,
745 "private void addAll$capitalized_name$Value(\n"
746 " java.lang.Iterable<java.lang.Integer> values) {\n"
747 " ensure$capitalized_name$IsMutable();\n"
748 " for (int value : values) {\n"
749 " $name$_.addInt(value);\n"
750 " }\n"
751 "}\n");
752 }
753 }
754
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const755 void RepeatedImmutableEnumFieldLiteGenerator::GenerateFieldInfo(
756 io::Printer* printer, std::vector<uint16_t>* output) const {
757 WriteIntToUtf16CharSequence(descriptor_->number(), output);
758 WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
759 output);
760 printer->Print(variables_, "\"$name$_\",\n");
761 if (!SupportUnknownEnumValue(descriptor_)) {
762 PrintEnumVerifierLogic(printer, descriptor_, variables_,
763 /*var_name=*/"$type$",
764 /*terminating_string=*/",\n",
765 /*enforce_lite=*/context_->EnforceLite());
766 }
767 }
768
GenerateBuilderMembers(io::Printer * printer) const769 void RepeatedImmutableEnumFieldLiteGenerator::GenerateBuilderMembers(
770 io::Printer* printer) const {
771 WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
772 context_->options());
773 printer->Print(variables_,
774 "@java.lang.Override\n"
775 "$deprecation$public java.util.List<$type$> "
776 "${$get$capitalized_name$List$}$() {\n"
777 " return instance.get$capitalized_name$List();\n"
778 "}\n");
779 printer->Annotate("{", "}", descriptor_);
780 WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT,
781 context_->options());
782 printer->Print(
783 variables_,
784 "@java.lang.Override\n"
785 "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
786 " return instance.get$capitalized_name$Count();\n"
787 "}\n");
788 printer->Annotate("{", "}", descriptor_);
789 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER,
790 context_->options());
791 printer->Print(
792 variables_,
793 "@java.lang.Override\n"
794 "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
795 " return instance.get$capitalized_name$(index);\n"
796 "}\n");
797 printer->Annotate("{", "}", descriptor_);
798 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
799 context_->options(),
800 /* builder */ true);
801 printer->Print(variables_,
802 "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
803 " int index, $type$ value) {\n"
804 " copyOnWrite();\n"
805 " instance.set$capitalized_name$(index, value);\n"
806 " return this;\n"
807 "}\n");
808 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
809 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
810 context_->options(),
811 /* builder */ true);
812 printer->Print(variables_,
813 "$deprecation$public Builder "
814 "${$add$capitalized_name$$}$($type$ value) {\n"
815 " copyOnWrite();\n"
816 " instance.add$capitalized_name$(value);\n"
817 " return this;\n"
818 "}\n");
819 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
820 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
821 context_->options(),
822 /* builder */ true);
823 printer->Print(variables_,
824 "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
825 " java.lang.Iterable<? extends $type$> values) {\n"
826 " copyOnWrite();\n"
827 " instance.addAll$capitalized_name$(values);"
828 " return this;\n"
829 "}\n");
830 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
831 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
832 context_->options(),
833 /* builder */ true);
834 printer->Print(
835 variables_,
836 "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
837 " copyOnWrite();\n"
838 " instance.clear$capitalized_name$();\n"
839 " return this;\n"
840 "}\n");
841 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
842
843 if (SupportUnknownEnumValue(descriptor_)) {
844 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER,
845 context_->options());
846 printer->Print(variables_,
847 "@java.lang.Override\n"
848 "$deprecation$public java.util.List<java.lang.Integer>\n"
849 "${$get$capitalized_name$ValueList$}$() {\n"
850 " return java.util.Collections.unmodifiableList(\n"
851 " instance.get$capitalized_name$ValueList());\n"
852 "}\n");
853 printer->Annotate("{", "}", descriptor_);
854 WriteFieldEnumValueAccessorDocComment(
855 printer, descriptor_, LIST_INDEXED_GETTER, context_->options());
856 printer->Print(variables_,
857 "@java.lang.Override\n"
858 "$deprecation$public int "
859 "${$get$capitalized_name$Value$}$(int index) {\n"
860 " return instance.get$capitalized_name$Value(index);\n"
861 "}\n");
862 printer->Annotate("{", "}", descriptor_);
863 WriteFieldEnumValueAccessorDocComment(
864 printer, descriptor_, LIST_INDEXED_SETTER, context_->options(),
865 /* builder */ true);
866 printer->Print(
867 variables_,
868 "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
869 " int index, int value) {\n"
870 " copyOnWrite();\n"
871 " instance.set$capitalized_name$Value(index, value);\n"
872 " return this;\n"
873 "}\n");
874 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
875 WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER,
876 context_->options(),
877 /* builder */ true);
878 printer->Print(variables_,
879 "$deprecation$public Builder "
880 "${$add$capitalized_name$Value$}$(int value) {\n"
881 " copyOnWrite();\n"
882 " instance.add$capitalized_name$Value(value);\n"
883 " return this;\n"
884 "}\n");
885 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
886 WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
887 LIST_MULTI_ADDER, context_->options(),
888 /* builder */ true);
889 printer->Print(
890 variables_,
891 "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
892 " java.lang.Iterable<java.lang.Integer> values) {\n"
893 " copyOnWrite();\n"
894 " instance.addAll$capitalized_name$Value(values);\n"
895 " return this;\n"
896 "}\n");
897 printer->Annotate("{", "}", descriptor_, Semantic::kSet);
898 }
899 }
900
GenerateInitializationCode(io::Printer * printer) const901 void RepeatedImmutableEnumFieldLiteGenerator::GenerateInitializationCode(
902 io::Printer* printer) const {
903 printer->Print(variables_, "$name$_ = emptyIntList();\n");
904 }
905
GenerateKotlinDslMembers(io::Printer * printer) const906 void RepeatedImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
907 io::Printer* printer) const {
908 auto vars = printer->WithVars(variables_);
909 JvmNameContext name_ctx = {context_->options(), printer};
910 printer->Print(
911 "/**\n"
912 " * An uninstantiable, behaviorless type to represent the field in\n"
913 " * generics.\n"
914 " */\n"
915 "@kotlin.OptIn"
916 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
917 "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
918 " : com.google.protobuf.kotlin.DslProxy()\n");
919
920 WriteFieldDocComment(printer, descriptor_, context_->options(),
921 /* kdoc */ true);
922 printer->Print(
923 "$kt_deprecation$ public val $kt_name$: "
924 "com.google.protobuf.kotlin.DslList"
925 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
926 "$ jvm_synthetic$"
927 " get() = com.google.protobuf.kotlin.DslList(\n"
928 " $kt_dsl_builder$.${$$kt_property_name$List$}$\n"
929 " )\n");
930
931 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
932 context_->options(),
933 /* builder */ false, /* kdoc */ true);
934 printer->Emit(
935 {
936 {"jvm_name", [&] { JvmName("add$kt_capitalized_name$", name_ctx); }},
937 },
938 "$jvm_synthetic$"
939 "$jvm_name$"
940 "public fun com.google.protobuf.kotlin.DslList"
941 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
942 "add(value: $kt_type$) {\n"
943 " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
944 "}");
945
946 WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
947 context_->options(),
948 /* builder */ false, /* kdoc */ true);
949 printer->Emit(
950 {
951 {"jvm_name",
952 [&] { JvmName("plusAssign$kt_capitalized_name$", name_ctx); }},
953 },
954 "$jvm_synthetic$"
955 "$jvm_name$"
956 "@Suppress(\"NOTHING_TO_INLINE\")\n"
957 "public inline operator fun com.google.protobuf.kotlin.DslList"
958 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
959 "plusAssign(value: $kt_type$) {\n"
960 " add(value)\n"
961 "}");
962
963 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
964 context_->options(),
965 /* builder */ false, /* kdoc */ true);
966 printer->Emit(
967 {
968 {"jvm_name",
969 [&] { JvmName("addAll$kt_capitalized_name$", name_ctx); }},
970 },
971 "$jvm_synthetic$"
972 "$jvm_name$"
973 "public fun com.google.protobuf.kotlin.DslList"
974 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
975 "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
976 " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
977 "}");
978
979 WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
980 context_->options(),
981 /* builder */ false, /* kdoc */ true);
982 printer->Emit(
983 {
984 {"jvm_name",
985 [&] { JvmName("plusAssignAll$kt_capitalized_name$", name_ctx); }},
986 },
987 "$jvm_synthetic$"
988 "$jvm_name$"
989 "@Suppress(\"NOTHING_TO_INLINE\")\n"
990 "public inline operator fun com.google.protobuf.kotlin.DslList"
991 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
992 "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
993 " addAll(values)\n"
994 "}");
995
996 WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
997 context_->options(),
998 /* builder */ false, /* kdoc */ true);
999 printer->Emit(
1000 {
1001 {"jvm_name", [&] { JvmName("set$kt_capitalized_name$", name_ctx); }},
1002 },
1003 "$jvm_synthetic$"
1004 "$jvm_name$"
1005 "public operator fun com.google.protobuf.kotlin.DslList"
1006 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
1007 "set(index: kotlin.Int, value: $kt_type$) {\n"
1008 " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
1009 "}");
1010
1011 WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
1012 context_->options(),
1013 /* builder */ false, /* kdoc */ true);
1014 printer->Emit(
1015 {
1016 {"jvm_name",
1017 [&] { JvmName("clear$kt_capitalized_name$", name_ctx); }},
1018 },
1019 "$jvm_synthetic$"
1020 "$jvm_name$"
1021 "public fun com.google.protobuf.kotlin.DslList"
1022 "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
1023 "clear() {\n"
1024 " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
1025 "}");
1026 }
1027
GetBoxedType() const1028 std::string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const {
1029 return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
1030 }
1031
1032 } // namespace java
1033 } // namespace compiler
1034 } // namespace protobuf
1035 } // namespace google
1036
1037 #include "google/protobuf/port_undef.inc"
1038