• 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.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 {
57 
SetEnumVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,std::map<std::string,std::string> * variables)58 void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
59                       int builderBitIndex, const FieldGeneratorInfo* info,
60                       ClassNameResolver* name_resolver,
61                       std::map<std::string, std::string>* variables) {
62   SetCommonFieldVariables(descriptor, info, variables);
63 
64   (*variables)["type"] =
65       name_resolver->GetImmutableClassName(descriptor->enum_type());
66   (*variables)["kt_type"] = (*variables)["type"];
67   (*variables)["mutable_type"] =
68       name_resolver->GetMutableClassName(descriptor->enum_type());
69   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
70   (*variables)["default_number"] =
71       StrCat(descriptor->default_value_enum()->number());
72   (*variables)["tag"] = StrCat(
73       static_cast<int32_t>(internal::WireFormat::MakeTag(descriptor)));
74   (*variables)["tag_size"] = StrCat(
75       internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
76   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
77   // by the proto compiler
78   (*variables)["deprecation"] =
79       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
80   (*variables)["kt_deprecation"] =
81       descriptor->options().deprecated()
82           ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
83                 " is deprecated\") "
84           : "";
85   (*variables)["on_changed"] = "onChanged();";
86   // Use deprecated valueOf() method to be compatible with old generated code
87   // for v2.5.0/v2.6.1.
88   // TODO(xiaofeng): Use "forNumber" when we no longer support compatibility
89   // with v2.5.0/v2.6.1, and remove the @SuppressWarnings annotations.
90   (*variables)["for_number"] = "valueOf";
91 
92   if (HasHasbit(descriptor)) {
93     // For singular messages and builders, one bit is used for the hasField bit.
94     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
95     (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
96 
97     // Note that these have a trailing ";".
98     (*variables)["set_has_field_bit_message"] =
99         GenerateSetBit(messageBitIndex) + ";";
100     (*variables)["set_has_field_bit_builder"] =
101         GenerateSetBit(builderBitIndex) + ";";
102     (*variables)["clear_has_field_bit_builder"] =
103         GenerateClearBit(builderBitIndex) + ";";
104 
105     (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
106   } else {
107     (*variables)["set_has_field_bit_message"] = "";
108     (*variables)["set_has_field_bit_builder"] = "";
109     (*variables)["clear_has_field_bit_builder"] = "";
110 
111     (*variables)["is_field_present_message"] =
112         (*variables)["name"] + "_ != " + (*variables)["default"] +
113         ".getNumber()";
114   }
115 
116   // For repeated builders, one bit is used for whether the array is immutable.
117   (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
118   (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
119   (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
120 
121   (*variables)["get_has_field_bit_from_local"] =
122       GenerateGetBitFromLocal(builderBitIndex);
123   (*variables)["set_has_field_bit_to_local"] =
124       GenerateSetBitToLocal(messageBitIndex);
125 
126   if (SupportUnknownEnumValue(descriptor->file())) {
127     (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
128   } else {
129     (*variables)["unknown"] = (*variables)["default"];
130   }
131 }
132 
133 }  // namespace
134 
135 // ===================================================================
136 
ImmutableEnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)137 ImmutableEnumFieldGenerator::ImmutableEnumFieldGenerator(
138     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
139     Context* context)
140     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
141   SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
142                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
143                    &variables_);
144 }
145 
~ImmutableEnumFieldGenerator()146 ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {}
147 
GetNumBitsForMessage() const148 int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
149   return HasHasbit(descriptor_) ? 1 : 0;
150 }
151 
GetNumBitsForBuilder() const152 int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
153   return GetNumBitsForMessage();
154 }
155 
GenerateInterfaceMembers(io::Printer * printer) const156 void ImmutableEnumFieldGenerator::GenerateInterfaceMembers(
157     io::Printer* printer) const {
158   if (HasHazzer(descriptor_)) {
159     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
160     printer->Print(variables_,
161                    "$deprecation$boolean has$capitalized_name$();\n");
162   }
163   if (SupportUnknownEnumValue(descriptor_->file())) {
164     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
165     printer->Print(variables_,
166                    "$deprecation$int get$capitalized_name$Value();\n");
167   }
168   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
169   printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
170 }
171 
GenerateMembers(io::Printer * printer) const172 void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const {
173   printer->Print(variables_, "private int $name$_;\n");
174   PrintExtraFieldInfo(variables_, printer);
175   if (HasHazzer(descriptor_)) {
176     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
177     printer->Print(variables_,
178                    "@java.lang.Override $deprecation$public boolean "
179                    "${$has$capitalized_name$$}$() {\n"
180                    "  return $get_has_field_bit_message$;\n"
181                    "}\n");
182     printer->Annotate("{", "}", descriptor_);
183   }
184   if (SupportUnknownEnumValue(descriptor_->file())) {
185     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
186     printer->Print(variables_,
187                    "@java.lang.Override $deprecation$public int "
188                    "${$get$capitalized_name$Value$}$() {\n"
189                    "  return $name$_;\n"
190                    "}\n");
191     printer->Annotate("{", "}", descriptor_);
192   }
193   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
194   printer->Print(variables_,
195                  "@java.lang.Override $deprecation$public $type$ "
196                  "${$get$capitalized_name$$}$() {\n"
197                  "  @SuppressWarnings(\"deprecation\")\n"
198                  "  $type$ result = $type$.$for_number$($name$_);\n"
199                  "  return result == null ? $unknown$ : result;\n"
200                  "}\n");
201   printer->Annotate("{", "}", descriptor_);
202 }
203 
GenerateBuilderMembers(io::Printer * printer) const204 void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
205     io::Printer* printer) const {
206   printer->Print(variables_, "private int $name$_ = $default_number$;\n");
207   if (HasHazzer(descriptor_)) {
208     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
209     printer->Print(variables_,
210                    "@java.lang.Override $deprecation$public boolean "
211                    "${$has$capitalized_name$$}$() {\n"
212                    "  return $get_has_field_bit_builder$;\n"
213                    "}\n");
214     printer->Annotate("{", "}", descriptor_);
215   }
216   if (SupportUnknownEnumValue(descriptor_->file())) {
217     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
218     printer->Print(variables_,
219                    "@java.lang.Override $deprecation$public int "
220                    "${$get$capitalized_name$Value$}$() {\n"
221                    "  return $name$_;\n"
222                    "}\n");
223     printer->Annotate("{", "}", descriptor_);
224     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
225                                           /* builder */ true);
226     printer->Print(variables_,
227                    "$deprecation$public Builder "
228                    "${$set$capitalized_name$Value$}$(int value) {\n"
229                    "  $set_has_field_bit_builder$\n"
230                    "  $name$_ = value;\n"
231                    "  $on_changed$\n"
232                    "  return this;\n"
233                    "}\n");
234     printer->Annotate("{", "}", descriptor_);
235   }
236   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
237   printer->Print(variables_,
238                  "@java.lang.Override\n"
239                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
240                  "  @SuppressWarnings(\"deprecation\")\n"
241                  "  $type$ result = $type$.$for_number$($name$_);\n"
242                  "  return result == null ? $unknown$ : result;\n"
243                  "}\n");
244   printer->Annotate("{", "}", descriptor_);
245   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
246                                /* builder */ true);
247   printer->Print(variables_,
248                  "$deprecation$public Builder "
249                  "${$set$capitalized_name$$}$($type$ value) {\n"
250                  "  if (value == null) {\n"
251                  "    throw new NullPointerException();\n"
252                  "  }\n"
253                  "  $set_has_field_bit_builder$\n"
254                  "  $name$_ = value.getNumber();\n"
255                  "  $on_changed$\n"
256                  "  return this;\n"
257                  "}\n");
258   printer->Annotate("{", "}", descriptor_);
259   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
260                                /* builder */ true);
261   printer->Print(
262       variables_,
263       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
264       "  $clear_has_field_bit_builder$\n"
265       "  $name$_ = $default_number$;\n"
266       "  $on_changed$\n"
267       "  return this;\n"
268       "}\n");
269   printer->Annotate("{", "}", descriptor_);
270 }
271 
GenerateKotlinDslMembers(io::Printer * printer) const272 void ImmutableEnumFieldGenerator::GenerateKotlinDslMembers(
273     io::Printer* printer) const {
274   WriteFieldDocComment(printer, descriptor_);
275   printer->Print(variables_,
276                  "$kt_deprecation$public var $kt_name$: $kt_type$\n"
277                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
278                  "  get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n"
279                  "  @JvmName(\"${$set$kt_capitalized_name$$}$\")\n"
280                  "  set(value) {\n"
281                  "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
282                  "  }\n");
283 
284   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
285                                /* builder */ false);
286   printer->Print(variables_,
287                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
288                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
289                  "}\n");
290 
291   if (HasHazzer(descriptor_)) {
292     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
293     printer->Print(
294         variables_,
295         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
296         "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
297         "}\n");
298   }
299 }
300 
GenerateFieldBuilderInitializationCode(io::Printer * printer) const301 void ImmutableEnumFieldGenerator::GenerateFieldBuilderInitializationCode(
302     io::Printer* printer) const {
303   // noop for enums
304 }
305 
GenerateInitializationCode(io::Printer * printer) const306 void ImmutableEnumFieldGenerator::GenerateInitializationCode(
307     io::Printer* printer) const {
308   printer->Print(variables_, "$name$_ = $default_number$;\n");
309 }
310 
GenerateBuilderClearCode(io::Printer * printer) const311 void ImmutableEnumFieldGenerator::GenerateBuilderClearCode(
312     io::Printer* printer) const {
313   printer->Print(variables_,
314                  "$name$_ = $default_number$;\n"
315                  "$clear_has_field_bit_builder$\n");
316 }
317 
GenerateMergingCode(io::Printer * printer) const318 void ImmutableEnumFieldGenerator::GenerateMergingCode(
319     io::Printer* printer) const {
320   if (HasHazzer(descriptor_)) {
321     printer->Print(variables_,
322                    "if (other.has$capitalized_name$()) {\n"
323                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
324                    "}\n");
325   } else if (SupportUnknownEnumValue(descriptor_->file())) {
326     printer->Print(
327         variables_,
328         "if (other.$name$_ != $default_number$) {\n"
329         "  set$capitalized_name$Value(other.get$capitalized_name$Value());\n"
330         "}\n");
331   } else {
332     GOOGLE_LOG(FATAL) << "Can't reach here.";
333   }
334 }
335 
GenerateBuildingCode(io::Printer * printer) const336 void ImmutableEnumFieldGenerator::GenerateBuildingCode(
337     io::Printer* printer) const {
338   if (HasHazzer(descriptor_)) {
339     printer->Print(variables_,
340                    "if ($get_has_field_bit_from_local$) {\n"
341                    "  $set_has_field_bit_to_local$;\n"
342                    "}\n");
343   }
344   printer->Print(variables_, "result.$name$_ = $name$_;\n");
345 }
346 
GenerateBuilderParsingCode(io::Printer * printer) const347 void ImmutableEnumFieldGenerator::GenerateBuilderParsingCode(
348     io::Printer* printer) const {
349   if (SupportUnknownEnumValue(descriptor_->file())) {
350     printer->Print(variables_,
351                    "$name$_ = input.readEnum();\n"
352                    "$set_has_field_bit_builder$\n");
353   } else {
354     printer->Print(variables_,
355                    "int tmpRaw = input.readEnum();\n"
356                    "$type$ tmpValue =\n"
357                    "    $type$.forNumber(tmpRaw);\n"
358                    "if (tmpValue == null) {\n"
359                    "  mergeUnknownVarintField($number$, tmpRaw);\n"
360                    "} else {\n"
361                    "  $name$_ = tmpRaw;\n"
362                    "  $set_has_field_bit_builder$\n"
363                    "}\n");
364   }
365 }
366 
GenerateSerializationCode(io::Printer * printer) const367 void ImmutableEnumFieldGenerator::GenerateSerializationCode(
368     io::Printer* printer) const {
369   printer->Print(variables_,
370                  "if ($is_field_present_message$) {\n"
371                  "  output.writeEnum($number$, $name$_);\n"
372                  "}\n");
373 }
374 
GenerateSerializedSizeCode(io::Printer * printer) const375 void ImmutableEnumFieldGenerator::GenerateSerializedSizeCode(
376     io::Printer* printer) const {
377   printer->Print(variables_,
378                  "if ($is_field_present_message$) {\n"
379                  "  size += com.google.protobuf.CodedOutputStream\n"
380                  "    .computeEnumSize($number$, $name$_);\n"
381                  "}\n");
382 }
383 
GenerateEqualsCode(io::Printer * printer) const384 void ImmutableEnumFieldGenerator::GenerateEqualsCode(
385     io::Printer* printer) const {
386   printer->Print(variables_, "if ($name$_ != other.$name$_) return false;\n");
387 }
388 
GenerateHashCode(io::Printer * printer) const389 void ImmutableEnumFieldGenerator::GenerateHashCode(io::Printer* printer) const {
390   printer->Print(variables_,
391                  "hash = (37 * hash) + $constant_name$;\n"
392                  "hash = (53 * hash) + $name$_;\n");
393 }
394 
GetBoxedType() const395 std::string ImmutableEnumFieldGenerator::GetBoxedType() const {
396   return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
397 }
398 
399 // ===================================================================
400 
ImmutableEnumOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)401 ImmutableEnumOneofFieldGenerator::ImmutableEnumOneofFieldGenerator(
402     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
403     Context* context)
404     : ImmutableEnumFieldGenerator(descriptor, messageBitIndex, builderBitIndex,
405                                   context) {
406   const OneofGeneratorInfo* info =
407       context->GetOneofGeneratorInfo(descriptor->containing_oneof());
408   SetCommonOneofVariables(descriptor, info, &variables_);
409 }
410 
~ImmutableEnumOneofFieldGenerator()411 ImmutableEnumOneofFieldGenerator::~ImmutableEnumOneofFieldGenerator() {}
412 
GenerateMembers(io::Printer * printer) const413 void ImmutableEnumOneofFieldGenerator::GenerateMembers(
414     io::Printer* printer) const {
415   PrintExtraFieldInfo(variables_, printer);
416   GOOGLE_DCHECK(HasHazzer(descriptor_));
417   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
418   printer->Print(variables_,
419                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
420                  "  return $has_oneof_case_message$;\n"
421                  "}\n");
422   printer->Annotate("{", "}", descriptor_);
423 
424   if (SupportUnknownEnumValue(descriptor_->file())) {
425     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
426     printer->Print(
427         variables_,
428         "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
429         "  if ($has_oneof_case_message$) {\n"
430         "    return (java.lang.Integer) $oneof_name$_;\n"
431         "  }\n"
432         "  return $default_number$;\n"
433         "}\n");
434     printer->Annotate("{", "}", descriptor_);
435   }
436   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
437   printer->Print(variables_,
438                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
439                  "  if ($has_oneof_case_message$) {\n"
440                  "    @SuppressWarnings(\"deprecation\")\n"
441                  "    $type$ result = $type$.$for_number$(\n"
442                  "        (java.lang.Integer) $oneof_name$_);\n"
443                  "    return result == null ? $unknown$ : result;\n"
444                  "  }\n"
445                  "  return $default$;\n"
446                  "}\n");
447   printer->Annotate("{", "}", descriptor_);
448 }
449 
GenerateBuilderMembers(io::Printer * printer) const450 void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
451     io::Printer* printer) const {
452   GOOGLE_DCHECK(HasHazzer(descriptor_));
453   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
454   printer->Print(variables_,
455                  "@java.lang.Override\n"
456                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
457                  "  return $has_oneof_case_message$;\n"
458                  "}\n");
459   printer->Annotate("{", "}", descriptor_);
460 
461   if (SupportUnknownEnumValue(descriptor_->file())) {
462     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
463     printer->Print(
464         variables_,
465         "@java.lang.Override\n"
466         "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
467         "  if ($has_oneof_case_message$) {\n"
468         "    return ((java.lang.Integer) $oneof_name$_).intValue();\n"
469         "  }\n"
470         "  return $default_number$;\n"
471         "}\n");
472     printer->Annotate("{", "}", descriptor_);
473     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
474                                           /* builder */ true);
475     printer->Print(variables_,
476                    "$deprecation$public Builder "
477                    "${$set$capitalized_name$Value$}$(int value) {\n"
478                    "  $set_oneof_case_message$;\n"
479                    "  $oneof_name$_ = value;\n"
480                    "  $on_changed$\n"
481                    "  return this;\n"
482                    "}\n");
483     printer->Annotate("{", "}", descriptor_);
484   }
485   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
486   printer->Print(variables_,
487                  "@java.lang.Override\n"
488                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
489                  "  if ($has_oneof_case_message$) {\n"
490                  "    @SuppressWarnings(\"deprecation\")\n"
491                  "    $type$ result = $type$.$for_number$(\n"
492                  "        (java.lang.Integer) $oneof_name$_);\n"
493                  "    return result == null ? $unknown$ : result;\n"
494                  "  }\n"
495                  "  return $default$;\n"
496                  "}\n");
497   printer->Annotate("{", "}", descriptor_);
498   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
499                                /* builder */ true);
500   printer->Print(variables_,
501                  "$deprecation$public Builder "
502                  "${$set$capitalized_name$$}$($type$ value) {\n"
503                  "  if (value == null) {\n"
504                  "    throw new NullPointerException();\n"
505                  "  }\n"
506                  "  $set_oneof_case_message$;\n"
507                  "  $oneof_name$_ = value.getNumber();\n"
508                  "  $on_changed$\n"
509                  "  return this;\n"
510                  "}\n");
511   printer->Annotate("{", "}", descriptor_);
512   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
513                                /* builder */ true);
514   printer->Print(
515       variables_,
516       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
517       "  if ($has_oneof_case_message$) {\n"
518       "    $clear_oneof_case_message$;\n"
519       "    $oneof_name$_ = null;\n"
520       "    $on_changed$\n"
521       "  }\n"
522       "  return this;\n"
523       "}\n");
524   printer->Annotate("{", "}", descriptor_);
525 }
526 
GenerateBuilderClearCode(io::Printer * printer) const527 void ImmutableEnumOneofFieldGenerator::GenerateBuilderClearCode(
528     io::Printer* printer) const {
529   // No-op: Enum fields in oneofs are correctly cleared by clearing the oneof
530 }
531 
GenerateBuildingCode(io::Printer * printer) const532 void ImmutableEnumOneofFieldGenerator::GenerateBuildingCode(
533     io::Printer* printer) const {
534   printer->Print(variables_,
535                  "if ($has_oneof_case_message$) {\n"
536                  "  result.$oneof_name$_ = $oneof_name$_;\n"
537                  "}\n");
538 }
539 
GenerateMergingCode(io::Printer * printer) const540 void ImmutableEnumOneofFieldGenerator::GenerateMergingCode(
541     io::Printer* printer) const {
542   if (SupportUnknownEnumValue(descriptor_->file())) {
543     printer->Print(
544         variables_,
545         "set$capitalized_name$Value(other.get$capitalized_name$Value());\n");
546   } else {
547     printer->Print(variables_,
548                    "set$capitalized_name$(other.get$capitalized_name$());\n");
549   }
550 }
551 
GenerateBuilderParsingCode(io::Printer * printer) const552 void ImmutableEnumOneofFieldGenerator::GenerateBuilderParsingCode(
553     io::Printer* printer) const {
554   if (SupportUnknownEnumValue(descriptor_->file())) {
555     printer->Print(variables_,
556                    "int rawValue = input.readEnum();\n"
557                    "$set_oneof_case_message$;\n"
558                    "$oneof_name$_ = rawValue;\n");
559   } else {
560     printer->Print(variables_,
561                    "int rawValue = input.readEnum();\n"
562                    "$type$ value =\n"
563                    "    $type$.forNumber(rawValue);\n"
564                    "if (value == null) {\n"
565                    "  mergeUnknownVarintField($number$, rawValue);\n"
566                    "} else {\n"
567                    "  $set_oneof_case_message$;\n"
568                    "  $oneof_name$_ = rawValue;\n"
569                    "}\n");
570   }
571 }
572 
GenerateSerializationCode(io::Printer * printer) const573 void ImmutableEnumOneofFieldGenerator::GenerateSerializationCode(
574     io::Printer* printer) const {
575   printer->Print(
576       variables_,
577       "if ($has_oneof_case_message$) {\n"
578       "  output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
579       "}\n");
580 }
581 
GenerateSerializedSizeCode(io::Printer * printer) const582 void ImmutableEnumOneofFieldGenerator::GenerateSerializedSizeCode(
583     io::Printer* printer) const {
584   printer->Print(
585       variables_,
586       "if ($has_oneof_case_message$) {\n"
587       "  size += com.google.protobuf.CodedOutputStream\n"
588       "    .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
589       "}\n");
590 }
591 
GenerateEqualsCode(io::Printer * printer) const592 void ImmutableEnumOneofFieldGenerator::GenerateEqualsCode(
593     io::Printer* printer) const {
594   if (SupportUnknownEnumValue(descriptor_->file())) {
595     printer->Print(
596         variables_,
597         "if (get$capitalized_name$Value()\n"
598         "    != other.get$capitalized_name$Value()) return false;\n");
599   } else {
600     printer->Print(
601         variables_,
602         "if (!get$capitalized_name$()\n"
603         "    .equals(other.get$capitalized_name$())) return false;\n");
604   }
605 }
606 
GenerateHashCode(io::Printer * printer) const607 void ImmutableEnumOneofFieldGenerator::GenerateHashCode(
608     io::Printer* printer) const {
609   if (SupportUnknownEnumValue(descriptor_->file())) {
610     printer->Print(variables_,
611                    "hash = (37 * hash) + $constant_name$;\n"
612                    "hash = (53 * hash) + get$capitalized_name$Value();\n");
613   } else {
614     printer->Print(
615         variables_,
616         "hash = (37 * hash) + $constant_name$;\n"
617         "hash = (53 * hash) + get$capitalized_name$().getNumber();\n");
618   }
619 }
620 
621 // ===================================================================
622 
RepeatedImmutableEnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)623 RepeatedImmutableEnumFieldGenerator::RepeatedImmutableEnumFieldGenerator(
624     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
625     Context* context)
626     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
627   SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
628                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
629                    &variables_);
630 }
631 
~RepeatedImmutableEnumFieldGenerator()632 RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {}
633 
GetNumBitsForMessage() const634 int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
635   return 0;
636 }
637 
GetNumBitsForBuilder() const638 int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
639   return 1;
640 }
641 
GenerateInterfaceMembers(io::Printer * printer) const642 void RepeatedImmutableEnumFieldGenerator::GenerateInterfaceMembers(
643     io::Printer* printer) const {
644   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
645   printer->Print(
646       variables_,
647       "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
648   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
649   printer->Print(variables_,
650                  "$deprecation$int get$capitalized_name$Count();\n");
651   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
652   printer->Print(variables_,
653                  "$deprecation$$type$ get$capitalized_name$(int index);\n");
654   if (SupportUnknownEnumValue(descriptor_->file())) {
655     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
656     printer->Print(variables_,
657                    "$deprecation$java.util.List<java.lang.Integer>\n"
658                    "get$capitalized_name$ValueList();\n");
659     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
660                                           LIST_INDEXED_GETTER);
661     printer->Print(variables_,
662                    "$deprecation$int get$capitalized_name$Value(int index);\n");
663   }
664 }
665 
GenerateMembers(io::Printer * printer) const666 void RepeatedImmutableEnumFieldGenerator::GenerateMembers(
667     io::Printer* printer) const {
668   printer->Print(
669       variables_,
670       "private java.util.List<java.lang.Integer> $name$_;\n"
671       "private static final "
672       "com.google.protobuf.Internal.ListAdapter.Converter<\n"
673       "    java.lang.Integer, $type$> $name$_converter_ =\n"
674       "        new com.google.protobuf.Internal.ListAdapter.Converter<\n"
675       "            java.lang.Integer, $type$>() {\n"
676       "          public $type$ convert(java.lang.Integer from) {\n"
677       "            @SuppressWarnings(\"deprecation\")\n"
678       "            $type$ result = $type$.$for_number$(from);\n"
679       "            return result == null ? $unknown$ : result;\n"
680       "          }\n"
681       "        };\n");
682   PrintExtraFieldInfo(variables_, printer);
683   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
684   printer->Print(
685       variables_,
686       "@java.lang.Override\n"
687       "$deprecation$public java.util.List<$type$> "
688       "${$get$capitalized_name$List$}$() {\n"
689       "  return new com.google.protobuf.Internal.ListAdapter<\n"
690       "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
691       "}\n");
692   printer->Annotate("{", "}", descriptor_);
693   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
694   printer->Print(
695       variables_,
696       "@java.lang.Override\n"
697       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
698       "  return $name$_.size();\n"
699       "}\n");
700   printer->Annotate("{", "}", descriptor_);
701   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
702   printer->Print(
703       variables_,
704       "@java.lang.Override\n"
705       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
706       "  return $name$_converter_.convert($name$_.get(index));\n"
707       "}\n");
708   printer->Annotate("{", "}", descriptor_);
709   if (SupportUnknownEnumValue(descriptor_->file())) {
710     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
711     printer->Print(variables_,
712                    "@java.lang.Override\n"
713                    "$deprecation$public java.util.List<java.lang.Integer>\n"
714                    "${$get$capitalized_name$ValueList$}$() {\n"
715                    "  return $name$_;\n"
716                    "}\n");
717     printer->Annotate("{", "}", descriptor_);
718     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
719                                           LIST_INDEXED_GETTER);
720     printer->Print(variables_,
721                    "@java.lang.Override\n"
722                    "$deprecation$public int "
723                    "${$get$capitalized_name$Value$}$(int index) {\n"
724                    "  return $name$_.get(index);\n"
725                    "}\n");
726     printer->Annotate("{", "}", descriptor_);
727   }
728 
729   if (descriptor_->is_packed()) {
730     printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n");
731   }
732 }
733 
GenerateBuilderMembers(io::Printer * printer) const734 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers(
735     io::Printer* printer) const {
736   printer->Print(
737       variables_,
738       // One field is the list and the other field keeps track of whether the
739       // list is immutable. If it's immutable, the invariant is that it must
740       // either an instance of Collections.emptyList() or it's an ArrayList
741       // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
742       // a reference to the underlying ArrayList. This invariant allows us to
743       // share instances of lists between protocol buffers avoiding expensive
744       // memory allocations. Note, immutable is a strong guarantee here -- not
745       // just that the list cannot be modified via the reference but that the
746       // list can never be modified.
747       "private java.util.List<java.lang.Integer> $name$_ =\n"
748       "  java.util.Collections.emptyList();\n"
749 
750       "private void ensure$capitalized_name$IsMutable() {\n"
751       "  if (!$get_mutable_bit_builder$) {\n"
752       "    $name$_ = new java.util.ArrayList<java.lang.Integer>($name$_);\n"
753       "    $set_mutable_bit_builder$;\n"
754       "  }\n"
755       "}\n");
756 
757   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
758   printer->Print(
759       variables_,
760       // Note:  We return an unmodifiable list because otherwise the caller
761       //   could hold on to the returned list and modify it after the message
762       //   has been built, thus mutating the message which is supposed to be
763       //   immutable.
764       "$deprecation$public java.util.List<$type$> "
765       "${$get$capitalized_name$List$}$() {\n"
766       "  return new com.google.protobuf.Internal.ListAdapter<\n"
767       "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
768       "}\n");
769   printer->Annotate("{", "}", descriptor_);
770   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
771   printer->Print(
772       variables_,
773       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
774       "  return $name$_.size();\n"
775       "}\n");
776   printer->Annotate("{", "}", descriptor_);
777   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
778   printer->Print(
779       variables_,
780       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
781       "  return $name$_converter_.convert($name$_.get(index));\n"
782       "}\n");
783   printer->Annotate("{", "}", descriptor_);
784   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
785                                /* builder */ true);
786   printer->Print(variables_,
787                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
788                  "    int index, $type$ value) {\n"
789                  "  if (value == null) {\n"
790                  "    throw new NullPointerException();\n"
791                  "  }\n"
792                  "  ensure$capitalized_name$IsMutable();\n"
793                  "  $name$_.set(index, value.getNumber());\n"
794                  "  $on_changed$\n"
795                  "  return this;\n"
796                  "}\n");
797   printer->Annotate("{", "}", descriptor_);
798   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
799                                /* builder */ true);
800   printer->Print(variables_,
801                  "$deprecation$public Builder "
802                  "${$add$capitalized_name$$}$($type$ value) {\n"
803                  "  if (value == null) {\n"
804                  "    throw new NullPointerException();\n"
805                  "  }\n"
806                  "  ensure$capitalized_name$IsMutable();\n"
807                  "  $name$_.add(value.getNumber());\n"
808                  "  $on_changed$\n"
809                  "  return this;\n"
810                  "}\n");
811   printer->Annotate("{", "}", descriptor_);
812   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
813                                /* builder */ true);
814   printer->Print(variables_,
815                  "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
816                  "    java.lang.Iterable<? extends $type$> values) {\n"
817                  "  ensure$capitalized_name$IsMutable();\n"
818                  "  for ($type$ value : values) {\n"
819                  "    $name$_.add(value.getNumber());\n"
820                  "  }\n"
821                  "  $on_changed$\n"
822                  "  return this;\n"
823                  "}\n");
824   printer->Annotate("{", "}", descriptor_);
825   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
826                                /* builder */ true);
827   printer->Print(
828       variables_,
829       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
830       "  $name$_ = java.util.Collections.emptyList();\n"
831       "  $clear_mutable_bit_builder$;\n"
832       "  $on_changed$\n"
833       "  return this;\n"
834       "}\n");
835   printer->Annotate("{", "}", descriptor_);
836 
837   if (SupportUnknownEnumValue(descriptor_->file())) {
838     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
839     printer->Print(variables_,
840                    "$deprecation$public java.util.List<java.lang.Integer>\n"
841                    "${$get$capitalized_name$ValueList$}$() {\n"
842                    "  return java.util.Collections.unmodifiableList($name$_);\n"
843                    "}\n");
844     printer->Annotate("{", "}", descriptor_);
845     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
846                                           LIST_INDEXED_GETTER);
847     printer->Print(variables_,
848                    "$deprecation$public int "
849                    "${$get$capitalized_name$Value$}$(int index) {\n"
850                    "  return $name$_.get(index);\n"
851                    "}\n");
852     printer->Annotate("{", "}", descriptor_);
853     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
854                                           LIST_INDEXED_GETTER,
855                                           /* builder */ true);
856     printer->Print(
857         variables_,
858         "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
859         "    int index, int value) {\n"
860         "  ensure$capitalized_name$IsMutable();\n"
861         "  $name$_.set(index, value);\n"
862         "  $on_changed$\n"
863         "  return this;\n"
864         "}\n");
865     printer->Annotate("{", "}", descriptor_);
866     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER,
867                                           /* builder */ true);
868     printer->Print(variables_,
869                    "$deprecation$public Builder "
870                    "${$add$capitalized_name$Value$}$(int value) {\n"
871                    "  ensure$capitalized_name$IsMutable();\n"
872                    "  $name$_.add(value);\n"
873                    "  $on_changed$\n"
874                    "  return this;\n"
875                    "}\n");
876     printer->Annotate("{", "}", descriptor_);
877     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
878                                           LIST_MULTI_ADDER, /* builder */ true);
879     printer->Print(
880         variables_,
881         "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
882         "    java.lang.Iterable<java.lang.Integer> values) {\n"
883         "  ensure$capitalized_name$IsMutable();\n"
884         "  for (int value : values) {\n"
885         "    $name$_.add(value);\n"
886         "  }\n"
887         "  $on_changed$\n"
888         "  return this;\n"
889         "}\n");
890     printer->Annotate("{", "}", descriptor_);
891   }
892 }
893 
894 void RepeatedImmutableEnumFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const895     GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
896   // noop for enums
897 }
898 
GenerateInitializationCode(io::Printer * printer) const899 void RepeatedImmutableEnumFieldGenerator::GenerateInitializationCode(
900     io::Printer* printer) const {
901   printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
902 }
903 
GenerateBuilderClearCode(io::Printer * printer) const904 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderClearCode(
905     io::Printer* printer) const {
906   printer->Print(variables_,
907                  "$name$_ = java.util.Collections.emptyList();\n"
908                  "$clear_mutable_bit_builder$;\n");
909 }
910 
GenerateMergingCode(io::Printer * printer) const911 void RepeatedImmutableEnumFieldGenerator::GenerateMergingCode(
912     io::Printer* printer) const {
913   // The code below does two optimizations:
914   //   1. If the other list is empty, there's nothing to do. This ensures we
915   //      don't allocate a new array if we already have an immutable one.
916   //   2. If the other list is non-empty and our current list is empty, we can
917   //      reuse the other list which is guaranteed to be immutable.
918   printer->Print(variables_,
919                  "if (!other.$name$_.isEmpty()) {\n"
920                  "  if ($name$_.isEmpty()) {\n"
921                  "    $name$_ = other.$name$_;\n"
922                  "    $clear_mutable_bit_builder$;\n"
923                  "  } else {\n"
924                  "    ensure$capitalized_name$IsMutable();\n"
925                  "    $name$_.addAll(other.$name$_);\n"
926                  "  }\n"
927                  "  $on_changed$\n"
928                  "}\n");
929 }
930 
GenerateBuildingCode(io::Printer * printer) const931 void RepeatedImmutableEnumFieldGenerator::GenerateBuildingCode(
932     io::Printer* printer) const {
933   // The code below ensures that the result has an immutable list. If our
934   // list is immutable, we can just reuse it. If not, we make it immutable.
935   printer->Print(
936       variables_,
937       "if ($get_mutable_bit_builder$) {\n"
938       "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
939       "  $clear_mutable_bit_builder$;\n"
940       "}\n"
941       "result.$name$_ = $name$_;\n");
942 }
943 
GenerateBuilderParsingCode(io::Printer * printer) const944 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderParsingCode(
945     io::Printer* printer) const {
946   // Read and store the enum
947   if (SupportUnknownEnumValue(descriptor_->file())) {
948     printer->Print(variables_,
949                    "int tmpRaw = input.readEnum();\n"
950                    "ensure$capitalized_name$IsMutable();\n"
951                    "$name$_.add(tmpRaw);\n");
952   } else {
953     printer->Print(variables_,
954                    "int tmpRaw = input.readEnum();\n"
955                    "$type$ tmpValue =\n"
956                    "    $type$.forNumber(tmpRaw);\n"
957                    "if (tmpValue == null) {\n"
958                    "  mergeUnknownVarintField($number$, tmpRaw);\n"
959                    "} else {\n"
960                    "  ensure$capitalized_name$IsMutable();\n"
961                    "  $name$_.add(tmpRaw);\n"
962                    "}\n");
963   }
964 }
965 
GenerateBuilderParsingCodeFromPacked(io::Printer * printer) const966 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderParsingCodeFromPacked(
967     io::Printer* printer) const {
968   // Wrap GenerateParsingCode's contents with a while loop.
969 
970   printer->Print(variables_,
971                  "int length = input.readRawVarint32();\n"
972                  "int oldLimit = input.pushLimit(length);\n"
973                  "while(input.getBytesUntilLimit() > 0) {\n");
974   printer->Indent();
975 
976   GenerateBuilderParsingCode(printer);
977 
978   printer->Outdent();
979   printer->Print(variables_,
980                  "}\n"
981                  "input.popLimit(oldLimit);\n");
982 }
983 
GenerateSerializationCode(io::Printer * printer) const984 void RepeatedImmutableEnumFieldGenerator::GenerateSerializationCode(
985     io::Printer* printer) const {
986   if (descriptor_->is_packed()) {
987     printer->Print(variables_,
988                    "if (get$capitalized_name$List().size() > 0) {\n"
989                    "  output.writeUInt32NoTag($tag$);\n"
990                    "  output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
991                    "}\n"
992                    "for (int i = 0; i < $name$_.size(); i++) {\n"
993                    "  output.writeEnumNoTag($name$_.get(i));\n"
994                    "}\n");
995   } else {
996     printer->Print(variables_,
997                    "for (int i = 0; i < $name$_.size(); i++) {\n"
998                    "  output.writeEnum($number$, $name$_.get(i));\n"
999                    "}\n");
1000   }
1001 }
1002 
GenerateSerializedSizeCode(io::Printer * printer) const1003 void RepeatedImmutableEnumFieldGenerator::GenerateSerializedSizeCode(
1004     io::Printer* printer) const {
1005   printer->Print(variables_,
1006                  "{\n"
1007                  "  int dataSize = 0;\n");
1008   printer->Indent();
1009 
1010   printer->Print(variables_,
1011                  "for (int i = 0; i < $name$_.size(); i++) {\n"
1012                  "  dataSize += com.google.protobuf.CodedOutputStream\n"
1013                  "    .computeEnumSizeNoTag($name$_.get(i));\n"
1014                  "}\n");
1015   printer->Print("size += dataSize;\n");
1016   if (descriptor_->is_packed()) {
1017     printer->Print(variables_,
1018                    "if (!get$capitalized_name$List().isEmpty()) {"
1019                    "  size += $tag_size$;\n"
1020                    "  size += com.google.protobuf.CodedOutputStream\n"
1021                    "    .computeUInt32SizeNoTag(dataSize);\n"
1022                    "}");
1023   } else {
1024     printer->Print(variables_, "size += $tag_size$ * $name$_.size();\n");
1025   }
1026 
1027   // cache the data size for packed fields.
1028   if (descriptor_->is_packed()) {
1029     printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
1030   }
1031 
1032   printer->Outdent();
1033   printer->Print("}\n");
1034 }
1035 
GenerateEqualsCode(io::Printer * printer) const1036 void RepeatedImmutableEnumFieldGenerator::GenerateEqualsCode(
1037     io::Printer* printer) const {
1038   printer->Print(variables_,
1039                  "if (!$name$_.equals(other.$name$_)) return false;\n");
1040 }
1041 
GenerateHashCode(io::Printer * printer) const1042 void RepeatedImmutableEnumFieldGenerator::GenerateHashCode(
1043     io::Printer* printer) const {
1044   printer->Print(variables_,
1045                  "if (get$capitalized_name$Count() > 0) {\n"
1046                  "  hash = (37 * hash) + $constant_name$;\n"
1047                  "  hash = (53 * hash) + $name$_.hashCode();\n"
1048                  "}\n");
1049 }
1050 
GenerateKotlinDslMembers(io::Printer * printer) const1051 void RepeatedImmutableEnumFieldGenerator::GenerateKotlinDslMembers(
1052     io::Printer* printer) const {
1053   printer->Print(
1054       variables_,
1055       "/**\n"
1056       " * An uninstantiable, behaviorless type to represent the field in\n"
1057       " * generics.\n"
1058       " */\n"
1059       "@kotlin.OptIn"
1060       "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
1061       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
1062       " : com.google.protobuf.kotlin.DslProxy()\n");
1063 
1064   WriteFieldDocComment(printer, descriptor_);
1065   printer->Print(variables_,
1066                  "$kt_deprecation$ public val $kt_name$: "
1067                  "com.google.protobuf.kotlin.DslList"
1068                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
1069                  "  @kotlin.jvm.JvmSynthetic\n"
1070                  "  get() = com.google.protobuf.kotlin.DslList(\n"
1071                  "    $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n"
1072                  "  )\n");
1073 
1074   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
1075                                /* builder */ false);
1076   printer->Print(variables_,
1077                  "@kotlin.jvm.JvmSynthetic\n"
1078                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
1079                  "public fun com.google.protobuf.kotlin.DslList"
1080                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
1081                  "add(value: $kt_type$) {\n"
1082                  "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
1083                  "}");
1084 
1085   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
1086                                /* builder */ false);
1087   printer->Print(variables_,
1088                  "@kotlin.jvm.JvmSynthetic\n"
1089                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
1090                  "@Suppress(\"NOTHING_TO_INLINE\")\n"
1091                  "public inline operator fun com.google.protobuf.kotlin.DslList"
1092                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
1093                  "plusAssign(value: $kt_type$) {\n"
1094                  "  add(value)\n"
1095                  "}");
1096 
1097   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
1098                                /* builder */ false);
1099   printer->Print(variables_,
1100                  "@kotlin.jvm.JvmSynthetic\n"
1101                  "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
1102                  "public fun com.google.protobuf.kotlin.DslList"
1103                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
1104                  "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n"
1105                  "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
1106                  "}");
1107 
1108   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
1109                                /* builder */ false);
1110   printer->Print(
1111       variables_,
1112       "@kotlin.jvm.JvmSynthetic\n"
1113       "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n"
1114       "@Suppress(\"NOTHING_TO_INLINE\")\n"
1115       "public inline operator fun com.google.protobuf.kotlin.DslList"
1116       "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
1117       "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n"
1118       "  addAll(values)\n"
1119       "}");
1120 
1121   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
1122                                /* builder */ false);
1123   printer->Print(
1124       variables_,
1125       "@kotlin.jvm.JvmSynthetic\n"
1126       "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n"
1127       "public operator fun com.google.protobuf.kotlin.DslList"
1128       "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
1129       "set(index: kotlin.Int, value: $kt_type$) {\n"
1130       "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
1131       "}");
1132 
1133   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
1134                                /* builder */ false);
1135   printer->Print(variables_,
1136                  "@kotlin.jvm.JvmSynthetic\n"
1137                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
1138                  "public fun com.google.protobuf.kotlin.DslList"
1139                  "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>."
1140                  "clear() {\n"
1141                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
1142                  "}");
1143 }
1144 
GetBoxedType() const1145 std::string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const {
1146   return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
1147 }
1148 
1149 }  // namespace java
1150 }  // namespace compiler
1151 }  // namespace protobuf
1152 }  // namespace google
1153