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