• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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