• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/compiler/java/java_enum_field_lite.h>
36 
37 #include <cstdint>
38 #include <map>
39 #include <string>
40 
41 #include <google/protobuf/stubs/logging.h>
42 #include <google/protobuf/stubs/common.h>
43 #include <google/protobuf/io/printer.h>
44 #include <google/protobuf/wire_format.h>
45 #include <google/protobuf/stubs/strutil.h>
46 #include <google/protobuf/compiler/java/java_context.h>
47 #include <google/protobuf/compiler/java/java_doc_comment.h>
48 #include <google/protobuf/compiler/java/java_helpers.h>
49 #include <google/protobuf/compiler/java/java_name_resolver.h>
50 
51 namespace google {
52 namespace protobuf {
53 namespace compiler {
54 namespace java {
55 
56 namespace {
EnableExperimentalRuntimeForLite()57 bool EnableExperimentalRuntimeForLite() {
58 #ifdef PROTOBUF_EXPERIMENT
59   return PROTOBUF_EXPERIMENT;
60 #else   // PROTOBUF_EXPERIMENT
61   return false;
62 #endif  // !PROTOBUF_EXPERIMENT
63 }
64 
SetEnumVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,std::map<std::string,std::string> * variables)65 void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
66                       int builderBitIndex, const FieldGeneratorInfo* info,
67                       ClassNameResolver* name_resolver,
68                       std::map<std::string, std::string>* variables) {
69   SetCommonFieldVariables(descriptor, info, variables);
70 
71   (*variables)["type"] =
72       name_resolver->GetImmutableClassName(descriptor->enum_type());
73   (*variables)["kt_type"] = (*variables)["type"];
74   (*variables)["mutable_type"] =
75       name_resolver->GetMutableClassName(descriptor->enum_type());
76   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
77   (*variables)["default_number"] =
78       StrCat(descriptor->default_value_enum()->number());
79   (*variables)["tag"] = StrCat(
80       static_cast<int32_t>(internal::WireFormat::MakeTag(descriptor)));
81   (*variables)["tag_size"] = StrCat(
82       internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
83   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
84   // by the proto compiler
85   (*variables)["deprecation"] =
86       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
87   (*variables)["kt_deprecation"] =
88       descriptor->options().deprecated()
89           ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
90                 " is deprecated\") "
91           : "";
92   (*variables)["required"] = descriptor->is_required() ? "true" : "false";
93 
94   if (HasHasbit(descriptor)) {
95     // For singular messages and builders, one bit is used for the hasField bit.
96     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
97 
98     // Note that these have a trailing ";".
99     (*variables)["set_has_field_bit_message"] =
100         GenerateSetBit(messageBitIndex) + ";";
101     (*variables)["clear_has_field_bit_message"] =
102         GenerateClearBit(messageBitIndex) + ";";
103 
104     (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
105   } else {
106     (*variables)["set_has_field_bit_message"] = "";
107     (*variables)["clear_has_field_bit_message"] = "";
108 
109     (*variables)["is_field_present_message"] =
110         (*variables)["name"] + "_ != " + (*variables)["default"] +
111         ".getNumber()";
112   }
113 
114   (*variables)["get_has_field_bit_from_local"] =
115       GenerateGetBitFromLocal(builderBitIndex);
116   (*variables)["set_has_field_bit_to_local"] =
117       GenerateSetBitToLocal(messageBitIndex);
118 
119   if (SupportUnknownEnumValue(descriptor->file())) {
120     (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
121   } else {
122     (*variables)["unknown"] = (*variables)["default"];
123   }
124 
125   // We use `x.getClass()` as a null check because it generates less bytecode
126   // than an `if (x == null) { throw ... }` statement.
127   (*variables)["null_check"] = "value.getClass();\n";
128 }
129 
130 }  // namespace
131 
132 // ===================================================================
133 
ImmutableEnumFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)134 ImmutableEnumFieldLiteGenerator::ImmutableEnumFieldLiteGenerator(
135     const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
136     : descriptor_(descriptor),
137       messageBitIndex_(messageBitIndex),
138       context_(context),
139       name_resolver_(context->GetNameResolver()) {
140   SetEnumVariables(descriptor, messageBitIndex, 0,
141                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
142                    &variables_);
143 }
144 
~ImmutableEnumFieldLiteGenerator()145 ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {}
146 
GetNumBitsForMessage() const147 int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
148   return HasHasbit(descriptor_) ? 1 : 0;
149 }
150 
GenerateInterfaceMembers(io::Printer * printer) const151 void ImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers(
152     io::Printer* printer) const {
153   if (HasHazzer(descriptor_)) {
154     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
155     printer->Print(variables_,
156                    "$deprecation$boolean has$capitalized_name$();\n");
157   }
158   if (SupportUnknownEnumValue(descriptor_->file())) {
159     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
160     printer->Print(variables_,
161                    "$deprecation$int get$capitalized_name$Value();\n");
162   }
163   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
164   printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
165 }
166 
GenerateMembers(io::Printer * printer) const167 void ImmutableEnumFieldLiteGenerator::GenerateMembers(
168     io::Printer* printer) const {
169   printer->Print(variables_, "private int $name$_;\n");
170   PrintExtraFieldInfo(variables_, printer);
171   if (HasHazzer(descriptor_)) {
172     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
173     printer->Print(
174         variables_,
175         "@java.lang.Override\n"
176         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
177         "  return $get_has_field_bit_message$;\n"
178         "}\n");
179     printer->Annotate("{", "}", descriptor_);
180   }
181   if (SupportUnknownEnumValue(descriptor_->file())) {
182     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
183     printer->Print(
184         variables_,
185         "@java.lang.Override\n"
186         "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
187         "  return $name$_;\n"
188         "}\n");
189     printer->Annotate("{", "}", descriptor_);
190   }
191   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
192   printer->Print(variables_,
193                  "@java.lang.Override\n"
194                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
195                  "  $type$ result = $type$.forNumber($name$_);\n"
196                  "  return result == null ? $unknown$ : result;\n"
197                  "}\n");
198   printer->Annotate("{", "}", descriptor_);
199 
200   // Generate private setters for the builder to proxy into.
201   if (SupportUnknownEnumValue(descriptor_->file())) {
202     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER);
203     printer->Print(variables_,
204                    "private void set$capitalized_name$Value(int value) {\n"
205                    "  $set_has_field_bit_message$"
206                    "  $name$_ = value;\n"
207                    "}\n");
208   }
209   WriteFieldAccessorDocComment(printer, descriptor_, SETTER);
210   printer->Print(variables_,
211                  "private void set$capitalized_name$($type$ value) {\n"
212                  "  $name$_ = value.getNumber();\n"
213                  "  $set_has_field_bit_message$\n"
214                  "}\n");
215   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
216   printer->Print(variables_,
217                  "private void clear$capitalized_name$() {\n"
218                  "  $clear_has_field_bit_message$\n"
219                  "  $name$_ = $default_number$;\n"
220                  "}\n");
221 }
222 
GenerateBuilderMembers(io::Printer * printer) const223 void ImmutableEnumFieldLiteGenerator::GenerateBuilderMembers(
224     io::Printer* printer) const {
225   if (HasHazzer(descriptor_)) {
226     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
227     printer->Print(
228         variables_,
229         "@java.lang.Override\n"
230         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
231         "  return instance.has$capitalized_name$();\n"
232         "}\n");
233     printer->Annotate("{", "}", descriptor_);
234   }
235   if (SupportUnknownEnumValue(descriptor_->file())) {
236     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
237     printer->Print(
238         variables_,
239         "@java.lang.Override\n"
240         "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
241         "  return instance.get$capitalized_name$Value();\n"
242         "}\n");
243     printer->Annotate("{", "}", descriptor_);
244     WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
245                                  /* builder */ true);
246     printer->Print(variables_,
247                    "$deprecation$public Builder "
248                    "${$set$capitalized_name$Value$}$(int value) {\n"
249                    "  copyOnWrite();\n"
250                    "  instance.set$capitalized_name$Value(value);\n"
251                    "  return this;\n"
252                    "}\n");
253     printer->Annotate("{", "}", descriptor_);
254   }
255   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
256   printer->Print(variables_,
257                  "@java.lang.Override\n"
258                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
259                  "  return instance.get$capitalized_name$();\n"
260                  "}\n");
261   printer->Annotate("{", "}", descriptor_);
262   WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
263                                         /* builder */ true);
264   printer->Print(variables_,
265                  "$deprecation$public Builder "
266                  "${$set$capitalized_name$$}$($type$ value) {\n"
267                  "  copyOnWrite();\n"
268                  "  instance.set$capitalized_name$(value);\n"
269                  "  return this;\n"
270                  "}\n");
271   printer->Annotate("{", "}", descriptor_);
272   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
273                                /* builder */ true);
274   printer->Print(
275       variables_,
276       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
277       "  copyOnWrite();\n"
278       "  instance.clear$capitalized_name$();\n"
279       "  return this;\n"
280       "}\n");
281   printer->Annotate("{", "}", descriptor_);
282 }
283 
GenerateKotlinDslMembers(io::Printer * printer) const284 void ImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
285     io::Printer* printer) const {
286   WriteFieldDocComment(printer, descriptor_);
287   printer->Print(variables_,
288                  "$kt_deprecation$public var $kt_name$: $kt_type$\n"
289                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
290                  "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
291                  "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
292                  "  set(value) {\n"
293                  "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
294                  "  }\n");
295 
296   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
297                                /* builder */ false);
298   printer->Print(variables_,
299                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
300                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
301                  "}\n");
302 
303   if (HasHazzer(descriptor_)) {
304     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
305     printer->Print(
306         variables_,
307         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
308         "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
309         "}\n");
310   }
311 }
312 
GenerateInitializationCode(io::Printer * printer) const313 void ImmutableEnumFieldLiteGenerator::GenerateInitializationCode(
314     io::Printer* printer) const {
315   if (!IsDefaultValueJavaDefault(descriptor_)) {
316     printer->Print(variables_, "$name$_ = $default_number$;\n");
317   }
318 }
319 
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const320 void ImmutableEnumFieldLiteGenerator::GenerateFieldInfo(
321     io::Printer* printer, std::vector<uint16_t>* output) const {
322   WriteIntToUtf16CharSequence(descriptor_->number(), output);
323   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
324                               output);
325   if (HasHasbit(descriptor_)) {
326     WriteIntToUtf16CharSequence(messageBitIndex_, output);
327   }
328   printer->Print(variables_, "\"$name$_\",\n");
329   if (!SupportUnknownEnumValue((descriptor_))) {
330     PrintEnumVerifierLogic(printer, descriptor_, variables_,
331                            /*var_name=*/"$type$",
332                            /*terminating_string=*/",\n",
333                            /*enforce_lite=*/context_->EnforceLite());
334   }
335 }
336 
GetBoxedType() const337 std::string ImmutableEnumFieldLiteGenerator::GetBoxedType() const {
338   return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
339 }
340 
341 // ===================================================================
342 
ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)343 ImmutableEnumOneofFieldLiteGenerator::ImmutableEnumOneofFieldLiteGenerator(
344     const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
345     : ImmutableEnumFieldLiteGenerator(descriptor, messageBitIndex, context) {
346   const OneofGeneratorInfo* info =
347       context->GetOneofGeneratorInfo(descriptor->containing_oneof());
348   SetCommonOneofVariables(descriptor, info, &variables_);
349 }
350 
~ImmutableEnumOneofFieldLiteGenerator()351 ImmutableEnumOneofFieldLiteGenerator::~ImmutableEnumOneofFieldLiteGenerator() {}
352 
GenerateMembers(io::Printer * printer) const353 void ImmutableEnumOneofFieldLiteGenerator::GenerateMembers(
354     io::Printer* printer) const {
355   PrintExtraFieldInfo(variables_, printer);
356   GOOGLE_DCHECK(HasHazzer(descriptor_));
357   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
358   printer->Print(variables_,
359                  "@java.lang.Override\n"
360                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
361                  "  return $has_oneof_case_message$;\n"
362                  "}\n");
363   printer->Annotate("{", "}", descriptor_);
364 
365   if (SupportUnknownEnumValue(descriptor_->file())) {
366     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
367     printer->Print(
368         variables_,
369         "@java.lang.Override\n"
370         "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
371         "  if ($has_oneof_case_message$) {\n"
372         "    return (java.lang.Integer) $oneof_name$_;\n"
373         "  }\n"
374         "  return $default_number$;\n"
375         "}\n");
376     printer->Annotate("{", "}", descriptor_);
377   }
378   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
379   printer->Print(variables_,
380                  "@java.lang.Override\n"
381                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
382                  "  if ($has_oneof_case_message$) {\n"
383                  "    $type$ result = $type$.forNumber((java.lang.Integer) "
384                  "$oneof_name$_);\n"
385                  "    return result == null ? $unknown$ : result;\n"
386                  "  }\n"
387                  "  return $default$;\n"
388                  "}\n");
389   printer->Annotate("{", "}", descriptor_);
390 
391   // Generate private setters for the builder to proxy into.
392   if (SupportUnknownEnumValue(descriptor_->file())) {
393     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER);
394     printer->Print(variables_,
395                    "private void set$capitalized_name$Value(int value) {\n"
396                    "  $set_oneof_case_message$;\n"
397                    "  $oneof_name$_ = value;\n"
398                    "}\n");
399   }
400   WriteFieldAccessorDocComment(printer, descriptor_, SETTER);
401   printer->Print(variables_,
402                  "private void set$capitalized_name$($type$ value) {\n"
403                  "  $oneof_name$_ = value.getNumber();\n"
404                  "  $set_oneof_case_message$;\n"
405                  "}\n");
406   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
407   printer->Print(variables_,
408                  "private void clear$capitalized_name$() {\n"
409                  "  if ($has_oneof_case_message$) {\n"
410                  "    $clear_oneof_case_message$;\n"
411                  "    $oneof_name$_ = null;\n"
412                  "  }\n"
413                  "}\n");
414 }
415 
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const416 void ImmutableEnumOneofFieldLiteGenerator::GenerateFieldInfo(
417     io::Printer* printer, std::vector<uint16_t>* output) const {
418   WriteIntToUtf16CharSequence(descriptor_->number(), output);
419   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
420                               output);
421   WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output);
422   if (!SupportUnknownEnumValue(descriptor_)) {
423     PrintEnumVerifierLogic(printer, descriptor_, variables_,
424                            /*var_name=*/"$type$",
425                            /*terminating_string=*/",\n",
426                            /*enforce_lite=*/context_->EnforceLite());
427   }
428 }
429 
GenerateBuilderMembers(io::Printer * printer) const430 void ImmutableEnumOneofFieldLiteGenerator::GenerateBuilderMembers(
431     io::Printer* printer) const {
432   GOOGLE_DCHECK(HasHazzer(descriptor_));
433   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
434   printer->Print(variables_,
435                  "@java.lang.Override\n"
436                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
437                  "  return instance.has$capitalized_name$();\n"
438                  "}\n");
439   printer->Annotate("{", "}", descriptor_);
440 
441   if (SupportUnknownEnumValue(descriptor_->file())) {
442     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
443     printer->Print(
444         variables_,
445         "@java.lang.Override\n"
446         "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
447         "  return instance.get$capitalized_name$Value();\n"
448         "}\n");
449     printer->Annotate("{", "}", descriptor_);
450     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
451                                           /* builder */ true);
452     printer->Print(variables_,
453                    "$deprecation$public Builder "
454                    "${$set$capitalized_name$Value$}$(int value) {\n"
455                    "  copyOnWrite();\n"
456                    "  instance.set$capitalized_name$Value(value);\n"
457                    "  return this;\n"
458                    "}\n");
459     printer->Annotate("{", "}", descriptor_);
460   }
461   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
462   printer->Print(variables_,
463                  "@java.lang.Override\n"
464                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
465                  "  return instance.get$capitalized_name$();\n"
466                  "}\n");
467   printer->Annotate("{", "}", descriptor_);
468   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
469                                /* builder */ true);
470   printer->Print(variables_,
471                  "$deprecation$public Builder "
472                  "${$set$capitalized_name$$}$($type$ value) {\n"
473                  "  copyOnWrite();\n"
474                  "  instance.set$capitalized_name$(value);\n"
475                  "  return this;\n"
476                  "}\n");
477   printer->Annotate("{", "}", descriptor_);
478   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
479                                /* builder */ true);
480   printer->Print(
481       variables_,
482       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
483       "  copyOnWrite();\n"
484       "  instance.clear$capitalized_name$();\n"
485       "  return this;\n"
486       "}\n");
487   printer->Annotate("{", "}", descriptor_);
488 }
489 
490 // ===================================================================
491 
492 RepeatedImmutableEnumFieldLiteGenerator::
RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)493     RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
494                                             int messageBitIndex,
495                                             Context* context)
496     : descriptor_(descriptor),
497       context_(context),
498       name_resolver_(context->GetNameResolver()) {
499   SetEnumVariables(descriptor, messageBitIndex, 0,
500                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
501                    &variables_);
502 }
503 
504 RepeatedImmutableEnumFieldLiteGenerator::
~RepeatedImmutableEnumFieldLiteGenerator()505     ~RepeatedImmutableEnumFieldLiteGenerator() {}
506 
GetNumBitsForMessage() const507 int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
508   return 0;
509 }
510 
GenerateInterfaceMembers(io::Printer * printer) const511 void RepeatedImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers(
512     io::Printer* printer) const {
513   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
514   printer->Print(
515       variables_,
516       "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
517   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
518   printer->Print(variables_,
519                  "$deprecation$int get$capitalized_name$Count();\n");
520   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
521   printer->Print(variables_,
522                  "$deprecation$$type$ get$capitalized_name$(int index);\n");
523   if (SupportUnknownEnumValue(descriptor_->file())) {
524     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
525     printer->Print(variables_,
526                    "$deprecation$java.util.List<java.lang.Integer>\n"
527                    "get$capitalized_name$ValueList();\n");
528     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
529                                           LIST_INDEXED_GETTER);
530     printer->Print(variables_,
531                    "$deprecation$int get$capitalized_name$Value(int index);\n");
532   }
533 }
534 
GenerateMembers(io::Printer * printer) const535 void RepeatedImmutableEnumFieldLiteGenerator::GenerateMembers(
536     io::Printer* printer) const {
537   printer->Print(
538       variables_,
539       "private com.google.protobuf.Internal.IntList $name$_;\n"
540       "private static final "
541       "com.google.protobuf.Internal.ListAdapter.Converter<\n"
542       "    java.lang.Integer, $type$> $name$_converter_ =\n"
543       "        new com.google.protobuf.Internal.ListAdapter.Converter<\n"
544       "            java.lang.Integer, $type$>() {\n"
545       "          @java.lang.Override\n"
546       "          public $type$ convert(java.lang.Integer from) {\n"
547       "            $type$ result = $type$.forNumber(from);\n"
548       "            return result == null ? $unknown$ : result;\n"
549       "          }\n"
550       "        };\n");
551   PrintExtraFieldInfo(variables_, printer);
552   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
553   printer->Print(
554       variables_,
555       "@java.lang.Override\n"
556       "$deprecation$public java.util.List<$type$> "
557       "${$get$capitalized_name$List$}$() {\n"
558       "  return new com.google.protobuf.Internal.ListAdapter<\n"
559       "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
560       "}\n");
561   printer->Annotate("{", "}", descriptor_);
562   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
563   printer->Print(
564       variables_,
565       "@java.lang.Override\n"
566       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
567       "  return $name$_.size();\n"
568       "}\n");
569   printer->Annotate("{", "}", descriptor_);
570   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
571   printer->Print(
572       variables_,
573       // NB: Do not use the "$name$_converter_" field; the usage of generics
574       // (and requisite upcasts to Object) prevent optimizations.  Even
575       // without any optimizations, the below code is cheaper because it
576       // avoids boxing an int and a checkcast from the generics.
577       "@java.lang.Override\n"
578       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
579       "  $type$ result = $type$.forNumber($name$_.getInt(index));\n"
580       "  return result == null ? $unknown$ : result;\n"
581       "}\n");
582   printer->Annotate("{", "}", descriptor_);
583   if (SupportUnknownEnumValue(descriptor_->file())) {
584     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
585     printer->Print(variables_,
586                    "@java.lang.Override\n"
587                    "$deprecation$public java.util.List<java.lang.Integer>\n"
588                    "${$get$capitalized_name$ValueList$}$() {\n"
589                    "  return $name$_;\n"
590                    "}\n");
591     printer->Annotate("{", "}", descriptor_);
592     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
593                                           LIST_INDEXED_GETTER);
594     printer->Print(variables_,
595                    "@java.lang.Override\n"
596                    "$deprecation$public int "
597                    "${$get$capitalized_name$Value$}$(int index) {\n"
598                    "  return $name$_.getInt(index);\n"
599                    "}\n");
600     printer->Annotate("{", "}", descriptor_);
601   }
602 
603   if (!EnableExperimentalRuntimeForLite() && descriptor_->is_packed() &&
604       context_->HasGeneratedMethods(descriptor_->containing_type())) {
605     printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n");
606   }
607 
608   // Generate private setters for the builder to proxy into.
609   printer->Print(
610       variables_,
611       "private void ensure$capitalized_name$IsMutable() {\n"
612       // Use a temporary to avoid a redundant iget-object.
613       "  com.google.protobuf.Internal.IntList tmp = $name$_;\n"
614       "  if (!tmp.isModifiable()) {\n"
615       "    $name$_ =\n"
616       "        com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
617       "  }\n"
618       "}\n");
619   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER);
620   printer->Print(variables_,
621                  "private void set$capitalized_name$(\n"
622                  "    int index, $type$ value) {\n"
623                  "  $null_check$"
624                  "  ensure$capitalized_name$IsMutable();\n"
625                  "  $name$_.setInt(index, value.getNumber());\n"
626                  "}\n");
627   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER);
628   printer->Print(variables_,
629                  "private void add$capitalized_name$($type$ value) {\n"
630                  "  $null_check$"
631                  "  ensure$capitalized_name$IsMutable();\n"
632                  "  $name$_.addInt(value.getNumber());\n"
633                  "}\n");
634   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER);
635   printer->Print(variables_,
636                  "private void addAll$capitalized_name$(\n"
637                  "    java.lang.Iterable<? extends $type$> values) {\n"
638                  "  ensure$capitalized_name$IsMutable();\n"
639                  "  for ($type$ value : values) {\n"
640                  "    $name$_.addInt(value.getNumber());\n"
641                  "  }\n"
642                  "}\n");
643   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER);
644   printer->Print(variables_,
645                  "private void clear$capitalized_name$() {\n"
646                  "  $name$_ = emptyIntList();\n"
647                  "}\n");
648 
649   if (SupportUnknownEnumValue(descriptor_->file())) {
650     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER);
651     printer->Print(variables_,
652                    "private void set$capitalized_name$Value(\n"
653                    "    int index, int value) {\n"
654                    "  ensure$capitalized_name$IsMutable();\n"
655                    "  $name$_.setInt(index, value);\n"
656                    "}\n");
657     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER);
658     printer->Print(variables_,
659                    "private void add$capitalized_name$Value(int value) {\n"
660                    "  ensure$capitalized_name$IsMutable();\n"
661                    "  $name$_.addInt(value);\n"
662                    "}\n");
663     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
664                                           LIST_MULTI_ADDER);
665     printer->Print(variables_,
666                    "private void addAll$capitalized_name$Value(\n"
667                    "    java.lang.Iterable<java.lang.Integer> values) {\n"
668                    "  ensure$capitalized_name$IsMutable();\n"
669                    "  for (int value : values) {\n"
670                    "    $name$_.addInt(value);\n"
671                    "  }\n"
672                    "}\n");
673   }
674 }
675 
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const676 void RepeatedImmutableEnumFieldLiteGenerator::GenerateFieldInfo(
677     io::Printer* printer, std::vector<uint16_t>* output) const {
678   WriteIntToUtf16CharSequence(descriptor_->number(), output);
679   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
680                               output);
681   printer->Print(variables_, "\"$name$_\",\n");
682   if (!SupportUnknownEnumValue(descriptor_->file())) {
683     PrintEnumVerifierLogic(printer, descriptor_, variables_,
684                            /*var_name=*/"$type$",
685                            /*terminating_string=*/",\n",
686                            /*enforce_lite=*/context_->EnforceLite());
687   }
688 }
689 
GenerateBuilderMembers(io::Printer * printer) const690 void RepeatedImmutableEnumFieldLiteGenerator::GenerateBuilderMembers(
691     io::Printer* printer) const {
692   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
693   printer->Print(variables_,
694                  "@java.lang.Override\n"
695                  "$deprecation$public java.util.List<$type$> "
696                  "${$get$capitalized_name$List$}$() {\n"
697                  "  return instance.get$capitalized_name$List();\n"
698                  "}\n");
699   printer->Annotate("{", "}", descriptor_);
700   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
701   printer->Print(
702       variables_,
703       "@java.lang.Override\n"
704       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
705       "  return instance.get$capitalized_name$Count();\n"
706       "}\n");
707   printer->Annotate("{", "}", descriptor_);
708   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
709   printer->Print(
710       variables_,
711       "@java.lang.Override\n"
712       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
713       "  return instance.get$capitalized_name$(index);\n"
714       "}\n");
715   printer->Annotate("{", "}", descriptor_);
716   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
717                                /* builder */ true);
718   printer->Print(variables_,
719                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
720                  "    int index, $type$ value) {\n"
721                  "  copyOnWrite();\n"
722                  "  instance.set$capitalized_name$(index, value);\n"
723                  "  return this;\n"
724                  "}\n");
725   printer->Annotate("{", "}", descriptor_);
726   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
727                                /* builder */ true);
728   printer->Print(variables_,
729                  "$deprecation$public Builder "
730                  "${$add$capitalized_name$$}$($type$ value) {\n"
731                  "  copyOnWrite();\n"
732                  "  instance.add$capitalized_name$(value);\n"
733                  "  return this;\n"
734                  "}\n");
735   printer->Annotate("{", "}", descriptor_);
736   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
737                                /* builder */ true);
738   printer->Print(variables_,
739                  "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
740                  "    java.lang.Iterable<? extends $type$> values) {\n"
741                  "  copyOnWrite();\n"
742                  "  instance.addAll$capitalized_name$(values);"
743                  "  return this;\n"
744                  "}\n");
745   printer->Annotate("{", "}", descriptor_);
746   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
747                                /* builder */ true);
748   printer->Print(
749       variables_,
750       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
751       "  copyOnWrite();\n"
752       "  instance.clear$capitalized_name$();\n"
753       "  return this;\n"
754       "}\n");
755   printer->Annotate("{", "}", descriptor_);
756 
757   if (SupportUnknownEnumValue(descriptor_->file())) {
758     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
759     printer->Print(variables_,
760                    "@java.lang.Override\n"
761                    "$deprecation$public java.util.List<java.lang.Integer>\n"
762                    "${$get$capitalized_name$ValueList$}$() {\n"
763                    "  return java.util.Collections.unmodifiableList(\n"
764                    "      instance.get$capitalized_name$ValueList());\n"
765                    "}\n");
766     printer->Annotate("{", "}", descriptor_);
767     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
768                                           LIST_INDEXED_GETTER);
769     printer->Print(variables_,
770                    "@java.lang.Override\n"
771                    "$deprecation$public int "
772                    "${$get$capitalized_name$Value$}$(int index) {\n"
773                    "  return instance.get$capitalized_name$Value(index);\n"
774                    "}\n");
775     printer->Annotate("{", "}", descriptor_);
776     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
777                                           LIST_INDEXED_SETTER,
778                                           /* builder */ true);
779     printer->Print(
780         variables_,
781         "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
782         "    int index, int value) {\n"
783         "  copyOnWrite();\n"
784         "  instance.set$capitalized_name$Value(index, value);\n"
785         "  return this;\n"
786         "}\n");
787     printer->Annotate("{", "}", descriptor_);
788     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER,
789                                           /* builder */ true);
790     printer->Print(variables_,
791                    "$deprecation$public Builder "
792                    "${$add$capitalized_name$Value$}$(int value) {\n"
793                    "  instance.add$capitalized_name$Value(value);\n"
794                    "  return this;\n"
795                    "}\n");
796     printer->Annotate("{", "}", descriptor_);
797     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
798                                           LIST_MULTI_ADDER,
799                                           /* builder */ true);
800     printer->Print(
801         variables_,
802         "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
803         "    java.lang.Iterable<java.lang.Integer> values) {\n"
804         "  copyOnWrite();\n"
805         "  instance.addAll$capitalized_name$Value(values);\n"
806         "  return this;\n"
807         "}\n");
808     printer->Annotate("{", "}", descriptor_);
809   }
810 }
811 
GenerateInitializationCode(io::Printer * printer) const812 void RepeatedImmutableEnumFieldLiteGenerator::GenerateInitializationCode(
813     io::Printer* printer) const {
814   printer->Print(variables_, "$name$_ = emptyIntList();\n");
815 }
816 
GenerateKotlinDslMembers(io::Printer * printer) const817 void RepeatedImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
818     io::Printer* printer) const {
819   printer->Print(
820       variables_,
821       "/**\n"
822       " * An uninstantiable, behaviorless type to represent the field in\n"
823       " * generics.\n"
824       " */\n"
825       "@kotlin.OptIn"
826       "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
827       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
828       " : com.google.protobuf.kotlin.DslProxy()\n");
829 
830   WriteFieldDocComment(printer, descriptor_);
831   printer->Print(variables_,
832                  "$kt_deprecation$ public val $kt_name$: "
833                  "com.google.protobuf.kotlin.DslList"
834                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
835                  "  @kotlin.jvm.JvmSynthetic\n"
836                  "  get() = com.google.protobuf.kotlin.DslList(\n"
837                  "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
838                  "  )\n");
839 
840   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
841                                /* builder */ false);
842   printer->Print(variables_,
843                  "@kotlin.jvm.JvmSynthetic\n"
844                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
845                  "public fun com.google.protobuf.kotlin.DslList"
846                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
847                  "add(value: $kt_type$) {\n"
848                  "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
849                  "}");
850 
851   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
852                                /* builder */ false);
853   printer->Print(variables_,
854                  "@kotlin.jvm.JvmSynthetic\n"
855                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
856                  "@Suppress(\"NOTHING_TO_INLINE\")\n"
857                  "public inline operator fun com.google.protobuf.kotlin.DslList"
858                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
859                  "plusAssign(value: $kt_type$) {\n"
860                  "  add(value)\n"
861                  "}");
862 
863   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
864                                /* builder */ false);
865   printer->Print(variables_,
866                  "@kotlin.jvm.JvmSynthetic\n"
867                  "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
868                  "public fun com.google.protobuf.kotlin.DslList"
869                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
870                  "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
871                  "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
872                  "}");
873 
874   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
875                                /* builder */ false);
876   printer->Print(
877       variables_,
878       "@kotlin.jvm.JvmSynthetic\n"
879       "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
880       "@Suppress(\"NOTHING_TO_INLINE\")\n"
881       "public inline operator fun com.google.protobuf.kotlin.DslList"
882       "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
883       "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
884       "  addAll(values)\n"
885       "}");
886 
887   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
888                                /* builder */ false);
889   printer->Print(
890       variables_,
891       "@kotlin.jvm.JvmSynthetic\n"
892       "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
893       "public operator fun com.google.protobuf.kotlin.DslList"
894       "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
895       "set(index: kotlin.Int, value: $kt_type$) {\n"
896       "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
897       "}");
898 
899   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
900                                /* builder */ false);
901   printer->Print(variables_,
902                  "@kotlin.jvm.JvmSynthetic\n"
903                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
904                  "public fun com.google.protobuf.kotlin.DslList"
905                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
906                  "clear() {\n"
907                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
908                  "}");
909 }
910 
GetBoxedType() const911 std::string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const {
912   return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
913 }
914 
915 }  // namespace java
916 }  // namespace compiler
917 }  // namespace protobuf
918 }  // namespace google
919