• 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 <map>
36 #include <string>
37 
38 #include <google/protobuf/stubs/logging.h>
39 #include <google/protobuf/stubs/common.h>
40 #include <google/protobuf/compiler/java/java_context.h>
41 #include <google/protobuf/compiler/java/java_doc_comment.h>
42 #include <google/protobuf/compiler/java/java_enum_field.h>
43 #include <google/protobuf/compiler/java/java_helpers.h>
44 #include <google/protobuf/compiler/java/java_name_resolver.h>
45 #include <google/protobuf/io/printer.h>
46 #include <google/protobuf/wire_format.h>
47 #include <google/protobuf/stubs/strutil.h>
48 
49 namespace google {
50 namespace protobuf {
51 namespace compiler {
52 namespace java {
53 
54 namespace {
55 
SetEnumVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,std::map<std::string,std::string> * variables)56 void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
57                       int builderBitIndex, const FieldGeneratorInfo* info,
58                       ClassNameResolver* name_resolver,
59                       std::map<std::string, std::string>* variables) {
60   SetCommonFieldVariables(descriptor, info, variables);
61 
62   (*variables)["type"] =
63       name_resolver->GetImmutableClassName(descriptor->enum_type());
64   (*variables)["mutable_type"] =
65       name_resolver->GetMutableClassName(descriptor->enum_type());
66   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
67   (*variables)["default_number"] =
68       StrCat(descriptor->default_value_enum()->number());
69   (*variables)["tag"] = StrCat(
70       static_cast<int32>(internal::WireFormat::MakeTag(descriptor)));
71   (*variables)["tag_size"] = StrCat(
72       internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
73   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
74   // by the proto compiler
75   (*variables)["deprecation"] =
76       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
77   (*variables)["on_changed"] = "onChanged();";
78   // Use deprecated valueOf() method to be compatible with old generated code
79   // for v2.5.0/v2.6.1.
80   // TODO(xiaofeng): Use "forNumber" when we no longer support compatibility
81   // with v2.5.0/v2.6.1, and remove the @SuppressWarnings annotations.
82   (*variables)["for_number"] = "valueOf";
83 
84   if (HasHasbit(descriptor)) {
85     // For singular messages and builders, one bit is used for the hasField bit.
86     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
87     (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
88 
89     // Note that these have a trailing ";".
90     (*variables)["set_has_field_bit_message"] =
91         GenerateSetBit(messageBitIndex) + ";";
92     (*variables)["set_has_field_bit_builder"] =
93         GenerateSetBit(builderBitIndex) + ";";
94     (*variables)["clear_has_field_bit_builder"] =
95         GenerateClearBit(builderBitIndex) + ";";
96 
97     (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
98   } else {
99     (*variables)["set_has_field_bit_message"] = "";
100     (*variables)["set_has_field_bit_builder"] = "";
101     (*variables)["clear_has_field_bit_builder"] = "";
102 
103     (*variables)["is_field_present_message"] =
104         (*variables)["name"] + "_ != " + (*variables)["default"] +
105         ".getNumber()";
106   }
107 
108   // For repeated builders, one bit is used for whether the array is immutable.
109   (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
110   (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
111   (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
112 
113   (*variables)["get_has_field_bit_from_local"] =
114       GenerateGetBitFromLocal(builderBitIndex);
115   (*variables)["set_has_field_bit_to_local"] =
116       GenerateSetBitToLocal(messageBitIndex);
117 
118   if (SupportUnknownEnumValue(descriptor->file())) {
119     (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
120   } else {
121     (*variables)["unknown"] = (*variables)["default"];
122   }
123 }
124 
125 }  // namespace
126 
127 // ===================================================================
128 
ImmutableEnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)129 ImmutableEnumFieldGenerator::ImmutableEnumFieldGenerator(
130     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
131     Context* context)
132     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
133   SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
134                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
135                    &variables_);
136 }
137 
~ImmutableEnumFieldGenerator()138 ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {}
139 
GetNumBitsForMessage() const140 int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
141   return HasHasbit(descriptor_) ? 1 : 0;
142 }
143 
GetNumBitsForBuilder() const144 int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
145   return GetNumBitsForMessage();
146 }
147 
GenerateInterfaceMembers(io::Printer * printer) const148 void ImmutableEnumFieldGenerator::GenerateInterfaceMembers(
149     io::Printer* printer) const {
150   if (SupportFieldPresence(descriptor_)) {
151     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
152     printer->Print(variables_,
153                    "$deprecation$boolean has$capitalized_name$();\n");
154   }
155   if (SupportUnknownEnumValue(descriptor_->file())) {
156     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
157     printer->Print(variables_,
158                    "$deprecation$int get$capitalized_name$Value();\n");
159   }
160   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
161   printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
162 }
163 
GenerateMembers(io::Printer * printer) const164 void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const {
165   printer->Print(variables_, "private int $name$_;\n");
166   PrintExtraFieldInfo(variables_, printer);
167   if (SupportFieldPresence(descriptor_)) {
168     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
169     printer->Print(variables_,
170                    "@java.lang.Override $deprecation$public boolean "
171                    "${$has$capitalized_name$$}$() {\n"
172                    "  return $get_has_field_bit_message$;\n"
173                    "}\n");
174     printer->Annotate("{", "}", descriptor_);
175   }
176   if (SupportUnknownEnumValue(descriptor_->file())) {
177     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
178     printer->Print(variables_,
179                    "@java.lang.Override $deprecation$public int "
180                    "${$get$capitalized_name$Value$}$() {\n"
181                    "  return $name$_;\n"
182                    "}\n");
183     printer->Annotate("{", "}", descriptor_);
184   }
185   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
186   printer->Print(variables_,
187                  "@java.lang.Override $deprecation$public $type$ "
188                  "${$get$capitalized_name$$}$() {\n"
189                  "  @SuppressWarnings(\"deprecation\")\n"
190                  "  $type$ result = $type$.$for_number$($name$_);\n"
191                  "  return result == null ? $unknown$ : result;\n"
192                  "}\n");
193   printer->Annotate("{", "}", descriptor_);
194 }
195 
GenerateBuilderMembers(io::Printer * printer) const196 void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
197     io::Printer* printer) const {
198   printer->Print(variables_, "private int $name$_ = $default_number$;\n");
199   if (SupportFieldPresence(descriptor_)) {
200     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
201     printer->Print(variables_,
202                    "@java.lang.Override $deprecation$public boolean "
203                    "${$has$capitalized_name$$}$() {\n"
204                    "  return $get_has_field_bit_builder$;\n"
205                    "}\n");
206     printer->Annotate("{", "}", descriptor_);
207   }
208   if (SupportUnknownEnumValue(descriptor_->file())) {
209     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
210     printer->Print(variables_,
211                    "@java.lang.Override $deprecation$public int "
212                    "${$get$capitalized_name$Value$}$() {\n"
213                    "  return $name$_;\n"
214                    "}\n");
215     printer->Annotate("{", "}", descriptor_);
216     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
217                                           /* builder */ true);
218     printer->Print(variables_,
219                    "$deprecation$public Builder "
220                    "${$set$capitalized_name$Value$}$(int value) {\n"
221                    "  $set_has_field_bit_builder$\n"
222                    "  $name$_ = value;\n"
223                    "  $on_changed$\n"
224                    "  return this;\n"
225                    "}\n");
226     printer->Annotate("{", "}", descriptor_);
227   }
228   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
229   printer->Print(variables_,
230                  "@java.lang.Override\n"
231                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
232                  "  @SuppressWarnings(\"deprecation\")\n"
233                  "  $type$ result = $type$.$for_number$($name$_);\n"
234                  "  return result == null ? $unknown$ : result;\n"
235                  "}\n");
236   printer->Annotate("{", "}", descriptor_);
237   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
238                                /* builder */ true);
239   printer->Print(variables_,
240                  "$deprecation$public Builder "
241                  "${$set$capitalized_name$$}$($type$ value) {\n"
242                  "  if (value == null) {\n"
243                  "    throw new NullPointerException();\n"
244                  "  }\n"
245                  "  $set_has_field_bit_builder$\n"
246                  "  $name$_ = value.getNumber();\n"
247                  "  $on_changed$\n"
248                  "  return this;\n"
249                  "}\n");
250   printer->Annotate("{", "}", descriptor_);
251   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
252                                /* builder */ true);
253   printer->Print(
254       variables_,
255       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
256       "  $clear_has_field_bit_builder$\n"
257       "  $name$_ = $default_number$;\n"
258       "  $on_changed$\n"
259       "  return this;\n"
260       "}\n");
261   printer->Annotate("{", "}", descriptor_);
262 }
263 
GenerateFieldBuilderInitializationCode(io::Printer * printer) const264 void ImmutableEnumFieldGenerator::GenerateFieldBuilderInitializationCode(
265     io::Printer* printer) const {
266   // noop for enums
267 }
268 
GenerateInitializationCode(io::Printer * printer) const269 void ImmutableEnumFieldGenerator::GenerateInitializationCode(
270     io::Printer* printer) const {
271   printer->Print(variables_, "$name$_ = $default_number$;\n");
272 }
273 
GenerateBuilderClearCode(io::Printer * printer) const274 void ImmutableEnumFieldGenerator::GenerateBuilderClearCode(
275     io::Printer* printer) const {
276   printer->Print(variables_,
277                  "$name$_ = $default_number$;\n"
278                  "$clear_has_field_bit_builder$\n");
279 }
280 
GenerateMergingCode(io::Printer * printer) const281 void ImmutableEnumFieldGenerator::GenerateMergingCode(
282     io::Printer* printer) const {
283   if (SupportFieldPresence(descriptor_)) {
284     printer->Print(variables_,
285                    "if (other.has$capitalized_name$()) {\n"
286                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
287                    "}\n");
288   } else if (SupportUnknownEnumValue(descriptor_->file())) {
289     printer->Print(
290         variables_,
291         "if (other.$name$_ != $default_number$) {\n"
292         "  set$capitalized_name$Value(other.get$capitalized_name$Value());\n"
293         "}\n");
294   } else {
295     GOOGLE_LOG(FATAL) << "Can't reach here.";
296   }
297 }
298 
GenerateBuildingCode(io::Printer * printer) const299 void ImmutableEnumFieldGenerator::GenerateBuildingCode(
300     io::Printer* printer) const {
301   if (SupportFieldPresence(descriptor_)) {
302     printer->Print(variables_,
303                    "if ($get_has_field_bit_from_local$) {\n"
304                    "  $set_has_field_bit_to_local$;\n"
305                    "}\n");
306   }
307   printer->Print(variables_, "result.$name$_ = $name$_;\n");
308 }
309 
GenerateBuilderParsingCode(io::Printer * printer) const310 void ImmutableEnumFieldGenerator::GenerateBuilderParsingCode(
311     io::Printer* printer) const {
312   if (SupportUnknownEnumValue(descriptor_->file())) {
313     printer->Print(variables_,
314                    "$name$_ = input.readEnum();\n"
315                    "$set_has_field_bit_builder$\n");
316   } else {
317     printer->Print(variables_,
318                    "int tmpRaw = input.readEnum();\n"
319                    "$type$ tmpValue =\n"
320                    "    $type$.forNumber(tmpRaw);\n"
321                    "if (tmpValue == null) {\n"
322                    "  mergeUnknownVarintField($number$, tmpRaw);\n"
323                    "} else {\n"
324                    "  $name$_ = tmpRaw;\n"
325                    "  $set_has_field_bit_builder$\n"
326                    "}\n");
327   }
328 }
329 
GenerateSerializationCode(io::Printer * printer) const330 void ImmutableEnumFieldGenerator::GenerateSerializationCode(
331     io::Printer* printer) const {
332   printer->Print(variables_,
333                  "if ($is_field_present_message$) {\n"
334                  "  output.writeEnum($number$, $name$_);\n"
335                  "}\n");
336 }
337 
GenerateSerializedSizeCode(io::Printer * printer) const338 void ImmutableEnumFieldGenerator::GenerateSerializedSizeCode(
339     io::Printer* printer) const {
340   printer->Print(variables_,
341                  "if ($is_field_present_message$) {\n"
342                  "  size += com.google.protobuf.CodedOutputStream\n"
343                  "    .computeEnumSize($number$, $name$_);\n"
344                  "}\n");
345 }
346 
GenerateEqualsCode(io::Printer * printer) const347 void ImmutableEnumFieldGenerator::GenerateEqualsCode(
348     io::Printer* printer) const {
349   printer->Print(variables_, "if ($name$_ != other.$name$_) return false;\n");
350 }
351 
GenerateHashCode(io::Printer * printer) const352 void ImmutableEnumFieldGenerator::GenerateHashCode(io::Printer* printer) const {
353   printer->Print(variables_,
354                  "hash = (37 * hash) + $constant_name$;\n"
355                  "hash = (53 * hash) + $name$_;\n");
356 }
357 
GetBoxedType() const358 std::string ImmutableEnumFieldGenerator::GetBoxedType() const {
359   return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
360 }
361 
362 // ===================================================================
363 
ImmutableEnumOneofFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)364 ImmutableEnumOneofFieldGenerator::ImmutableEnumOneofFieldGenerator(
365     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
366     Context* context)
367     : ImmutableEnumFieldGenerator(descriptor, messageBitIndex, builderBitIndex,
368                                   context) {
369   const OneofGeneratorInfo* info =
370       context->GetOneofGeneratorInfo(descriptor->containing_oneof());
371   SetCommonOneofVariables(descriptor, info, &variables_);
372 }
373 
~ImmutableEnumOneofFieldGenerator()374 ImmutableEnumOneofFieldGenerator::~ImmutableEnumOneofFieldGenerator() {}
375 
GenerateMembers(io::Printer * printer) const376 void ImmutableEnumOneofFieldGenerator::GenerateMembers(
377     io::Printer* printer) const {
378   PrintExtraFieldInfo(variables_, printer);
379   if (SupportFieldPresence(descriptor_)) {
380     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
381     printer->Print(
382         variables_,
383         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
384         "  return $has_oneof_case_message$;\n"
385         "}\n");
386     printer->Annotate("{", "}", descriptor_);
387   }
388   if (SupportUnknownEnumValue(descriptor_->file())) {
389     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
390     printer->Print(
391         variables_,
392         "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
393         "  if ($has_oneof_case_message$) {\n"
394         "    return (java.lang.Integer) $oneof_name$_;\n"
395         "  }\n"
396         "  return $default_number$;\n"
397         "}\n");
398     printer->Annotate("{", "}", descriptor_);
399   }
400   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
401   printer->Print(variables_,
402                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
403                  "  if ($has_oneof_case_message$) {\n"
404                  "    @SuppressWarnings(\"deprecation\")\n"
405                  "    $type$ result = $type$.$for_number$(\n"
406                  "        (java.lang.Integer) $oneof_name$_);\n"
407                  "    return result == null ? $unknown$ : result;\n"
408                  "  }\n"
409                  "  return $default$;\n"
410                  "}\n");
411   printer->Annotate("{", "}", descriptor_);
412 }
413 
GenerateBuilderMembers(io::Printer * printer) const414 void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
415     io::Printer* printer) const {
416   if (SupportFieldPresence(descriptor_)) {
417     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
418     printer->Print(
419         variables_,
420         "@java.lang.Override\n"
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         "@java.lang.Override\n"
431         "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
432         "  if ($has_oneof_case_message$) {\n"
433         "    return ((java.lang.Integer) $oneof_name$_).intValue();\n"
434         "  }\n"
435         "  return $default_number$;\n"
436         "}\n");
437     printer->Annotate("{", "}", descriptor_);
438     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, SETTER,
439                                           /* builder */ true);
440     printer->Print(variables_,
441                    "$deprecation$public Builder "
442                    "${$set$capitalized_name$Value$}$(int value) {\n"
443                    "  $set_oneof_case_message$;\n"
444                    "  $oneof_name$_ = value;\n"
445                    "  $on_changed$\n"
446                    "  return this;\n"
447                    "}\n");
448     printer->Annotate("{", "}", descriptor_);
449   }
450   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
451   printer->Print(variables_,
452                  "@java.lang.Override\n"
453                  "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
454                  "  if ($has_oneof_case_message$) {\n"
455                  "    @SuppressWarnings(\"deprecation\")\n"
456                  "    $type$ result = $type$.$for_number$(\n"
457                  "        (java.lang.Integer) $oneof_name$_);\n"
458                  "    return result == null ? $unknown$ : result;\n"
459                  "  }\n"
460                  "  return $default$;\n"
461                  "}\n");
462   printer->Annotate("{", "}", descriptor_);
463   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
464                                /* builder */ true);
465   printer->Print(variables_,
466                  "$deprecation$public Builder "
467                  "${$set$capitalized_name$$}$($type$ value) {\n"
468                  "  if (value == null) {\n"
469                  "    throw new NullPointerException();\n"
470                  "  }\n"
471                  "  $set_oneof_case_message$;\n"
472                  "  $oneof_name$_ = value.getNumber();\n"
473                  "  $on_changed$\n"
474                  "  return this;\n"
475                  "}\n");
476   printer->Annotate("{", "}", descriptor_);
477   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
478                                /* builder */ true);
479   printer->Print(
480       variables_,
481       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
482       "  if ($has_oneof_case_message$) {\n"
483       "    $clear_oneof_case_message$;\n"
484       "    $oneof_name$_ = null;\n"
485       "    $on_changed$\n"
486       "  }\n"
487       "  return this;\n"
488       "}\n");
489   printer->Annotate("{", "}", descriptor_);
490 }
491 
GenerateBuilderClearCode(io::Printer * printer) const492 void ImmutableEnumOneofFieldGenerator::GenerateBuilderClearCode(
493     io::Printer* printer) const {
494   // No-op: Enum fields in oneofs are correctly cleared by clearing the oneof
495 }
496 
GenerateBuildingCode(io::Printer * printer) const497 void ImmutableEnumOneofFieldGenerator::GenerateBuildingCode(
498     io::Printer* printer) const {
499   printer->Print(variables_,
500                  "if ($has_oneof_case_message$) {\n"
501                  "  result.$oneof_name$_ = $oneof_name$_;\n"
502                  "}\n");
503 }
504 
GenerateMergingCode(io::Printer * printer) const505 void ImmutableEnumOneofFieldGenerator::GenerateMergingCode(
506     io::Printer* printer) const {
507   if (SupportUnknownEnumValue(descriptor_->file())) {
508     printer->Print(
509         variables_,
510         "set$capitalized_name$Value(other.get$capitalized_name$Value());\n");
511   } else {
512     printer->Print(variables_,
513                    "set$capitalized_name$(other.get$capitalized_name$());\n");
514   }
515 }
516 
GenerateBuilderParsingCode(io::Printer * printer) const517 void ImmutableEnumOneofFieldGenerator::GenerateBuilderParsingCode(
518     io::Printer* printer) const {
519   if (SupportUnknownEnumValue(descriptor_->file())) {
520     printer->Print(variables_,
521                    "int rawValue = input.readEnum();\n"
522                    "$set_oneof_case_message$;\n"
523                    "$oneof_name$_ = rawValue;\n");
524   } else {
525     printer->Print(variables_,
526                    "int rawValue = input.readEnum();\n"
527                    "$type$ value =\n"
528                    "    $type$.forNumber(rawValue);\n"
529                    "if (value == null) {\n"
530                    "  mergeUnknownVarintField($number$, rawValue);\n"
531                    "} else {\n"
532                    "  $set_oneof_case_message$;\n"
533                    "  $oneof_name$_ = rawValue;\n"
534                    "}\n");
535   }
536 }
537 
GenerateSerializationCode(io::Printer * printer) const538 void ImmutableEnumOneofFieldGenerator::GenerateSerializationCode(
539     io::Printer* printer) const {
540   printer->Print(
541       variables_,
542       "if ($has_oneof_case_message$) {\n"
543       "  output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
544       "}\n");
545 }
546 
GenerateSerializedSizeCode(io::Printer * printer) const547 void ImmutableEnumOneofFieldGenerator::GenerateSerializedSizeCode(
548     io::Printer* printer) const {
549   printer->Print(
550       variables_,
551       "if ($has_oneof_case_message$) {\n"
552       "  size += com.google.protobuf.CodedOutputStream\n"
553       "    .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
554       "}\n");
555 }
556 
GenerateEqualsCode(io::Printer * printer) const557 void ImmutableEnumOneofFieldGenerator::GenerateEqualsCode(
558     io::Printer* printer) const {
559   if (SupportUnknownEnumValue(descriptor_->file())) {
560     printer->Print(
561         variables_,
562         "if (get$capitalized_name$Value()\n"
563         "    != other.get$capitalized_name$Value()) return false;\n");
564   } else {
565     printer->Print(
566         variables_,
567         "if (!get$capitalized_name$()\n"
568         "    .equals(other.get$capitalized_name$())) return false;\n");
569   }
570 }
571 
GenerateHashCode(io::Printer * printer) const572 void ImmutableEnumOneofFieldGenerator::GenerateHashCode(
573     io::Printer* printer) const {
574   if (SupportUnknownEnumValue(descriptor_->file())) {
575     printer->Print(variables_,
576                    "hash = (37 * hash) + $constant_name$;\n"
577                    "hash = (53 * hash) + get$capitalized_name$Value();\n");
578   } else {
579     printer->Print(
580         variables_,
581         "hash = (37 * hash) + $constant_name$;\n"
582         "hash = (53 * hash) + get$capitalized_name$().getNumber();\n");
583   }
584 }
585 
586 // ===================================================================
587 
RepeatedImmutableEnumFieldGenerator(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,Context * context)588 RepeatedImmutableEnumFieldGenerator::RepeatedImmutableEnumFieldGenerator(
589     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
590     Context* context)
591     : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
592   SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
593                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
594                    &variables_);
595 }
596 
~RepeatedImmutableEnumFieldGenerator()597 RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {}
598 
GetNumBitsForMessage() const599 int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
600   return 0;
601 }
602 
GetNumBitsForBuilder() const603 int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
604   return 1;
605 }
606 
GenerateInterfaceMembers(io::Printer * printer) const607 void RepeatedImmutableEnumFieldGenerator::GenerateInterfaceMembers(
608     io::Printer* printer) const {
609   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
610   printer->Print(
611       variables_,
612       "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
613   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
614   printer->Print(variables_,
615                  "$deprecation$int get$capitalized_name$Count();\n");
616   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
617   printer->Print(variables_,
618                  "$deprecation$$type$ get$capitalized_name$(int index);\n");
619   if (SupportUnknownEnumValue(descriptor_->file())) {
620     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
621     printer->Print(variables_,
622                    "$deprecation$java.util.List<java.lang.Integer>\n"
623                    "get$capitalized_name$ValueList();\n");
624     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
625                                           LIST_INDEXED_GETTER);
626     printer->Print(variables_,
627                    "$deprecation$int get$capitalized_name$Value(int index);\n");
628   }
629 }
630 
GenerateMembers(io::Printer * printer) const631 void RepeatedImmutableEnumFieldGenerator::GenerateMembers(
632     io::Printer* printer) const {
633   printer->Print(
634       variables_,
635       "private java.util.List<java.lang.Integer> $name$_;\n"
636       "private static final "
637       "com.google.protobuf.Internal.ListAdapter.Converter<\n"
638       "    java.lang.Integer, $type$> $name$_converter_ =\n"
639       "        new com.google.protobuf.Internal.ListAdapter.Converter<\n"
640       "            java.lang.Integer, $type$>() {\n"
641       "          public $type$ convert(java.lang.Integer from) {\n"
642       "            @SuppressWarnings(\"deprecation\")\n"
643       "            $type$ result = $type$.$for_number$(from);\n"
644       "            return result == null ? $unknown$ : result;\n"
645       "          }\n"
646       "        };\n");
647   PrintExtraFieldInfo(variables_, printer);
648   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
649   printer->Print(
650       variables_,
651       "@java.lang.Override\n"
652       "$deprecation$public java.util.List<$type$> "
653       "${$get$capitalized_name$List$}$() {\n"
654       "  return new com.google.protobuf.Internal.ListAdapter<\n"
655       "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
656       "}\n");
657   printer->Annotate("{", "}", descriptor_);
658   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
659   printer->Print(
660       variables_,
661       "@java.lang.Override\n"
662       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
663       "  return $name$_.size();\n"
664       "}\n");
665   printer->Annotate("{", "}", descriptor_);
666   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
667   printer->Print(
668       variables_,
669       "@java.lang.Override\n"
670       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
671       "  return $name$_converter_.convert($name$_.get(index));\n"
672       "}\n");
673   printer->Annotate("{", "}", descriptor_);
674   if (SupportUnknownEnumValue(descriptor_->file())) {
675     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
676     printer->Print(variables_,
677                    "@java.lang.Override\n"
678                    "$deprecation$public java.util.List<java.lang.Integer>\n"
679                    "${$get$capitalized_name$ValueList$}$() {\n"
680                    "  return $name$_;\n"
681                    "}\n");
682     printer->Annotate("{", "}", descriptor_);
683     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
684                                           LIST_INDEXED_GETTER);
685     printer->Print(variables_,
686                    "@java.lang.Override\n"
687                    "$deprecation$public int "
688                    "${$get$capitalized_name$Value$}$(int index) {\n"
689                    "  return $name$_.get(index);\n"
690                    "}\n");
691     printer->Annotate("{", "}", descriptor_);
692   }
693 
694   if (descriptor_->is_packed()) {
695     printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n");
696   }
697 }
698 
GenerateBuilderMembers(io::Printer * printer) const699 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers(
700     io::Printer* printer) const {
701   printer->Print(
702       variables_,
703       // One field is the list and the other field keeps track of whether the
704       // list is immutable. If it's immutable, the invariant is that it must
705       // either an instance of Collections.emptyList() or it's an ArrayList
706       // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
707       // a reference to the underlying ArrayList. This invariant allows us to
708       // share instances of lists between protocol buffers avoiding expensive
709       // memory allocations. Note, immutable is a strong guarantee here -- not
710       // just that the list cannot be modified via the reference but that the
711       // list can never be modified.
712       "private java.util.List<java.lang.Integer> $name$_ =\n"
713       "  java.util.Collections.emptyList();\n"
714 
715       "private void ensure$capitalized_name$IsMutable() {\n"
716       "  if (!$get_mutable_bit_builder$) {\n"
717       "    $name$_ = new java.util.ArrayList<java.lang.Integer>($name$_);\n"
718       "    $set_mutable_bit_builder$;\n"
719       "  }\n"
720       "}\n");
721 
722   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
723   printer->Print(
724       variables_,
725       // Note:  We return an unmodifiable list because otherwise the caller
726       //   could hold on to the returned list and modify it after the message
727       //   has been built, thus mutating the message which is supposed to be
728       //   immutable.
729       "$deprecation$public java.util.List<$type$> "
730       "${$get$capitalized_name$List$}$() {\n"
731       "  return new com.google.protobuf.Internal.ListAdapter<\n"
732       "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
733       "}\n");
734   printer->Annotate("{", "}", descriptor_);
735   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
736   printer->Print(
737       variables_,
738       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
739       "  return $name$_.size();\n"
740       "}\n");
741   printer->Annotate("{", "}", descriptor_);
742   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
743   printer->Print(
744       variables_,
745       "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
746       "  return $name$_converter_.convert($name$_.get(index));\n"
747       "}\n");
748   printer->Annotate("{", "}", descriptor_);
749   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
750                                /* builder */ true);
751   printer->Print(variables_,
752                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
753                  "    int index, $type$ value) {\n"
754                  "  if (value == null) {\n"
755                  "    throw new NullPointerException();\n"
756                  "  }\n"
757                  "  ensure$capitalized_name$IsMutable();\n"
758                  "  $name$_.set(index, value.getNumber());\n"
759                  "  $on_changed$\n"
760                  "  return this;\n"
761                  "}\n");
762   printer->Annotate("{", "}", descriptor_);
763   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
764                                /* builder */ true);
765   printer->Print(variables_,
766                  "$deprecation$public Builder "
767                  "${$add$capitalized_name$$}$($type$ value) {\n"
768                  "  if (value == null) {\n"
769                  "    throw new NullPointerException();\n"
770                  "  }\n"
771                  "  ensure$capitalized_name$IsMutable();\n"
772                  "  $name$_.add(value.getNumber());\n"
773                  "  $on_changed$\n"
774                  "  return this;\n"
775                  "}\n");
776   printer->Annotate("{", "}", descriptor_);
777   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
778                                /* builder */ true);
779   printer->Print(variables_,
780                  "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
781                  "    java.lang.Iterable<? extends $type$> values) {\n"
782                  "  ensure$capitalized_name$IsMutable();\n"
783                  "  for ($type$ value : values) {\n"
784                  "    $name$_.add(value.getNumber());\n"
785                  "  }\n"
786                  "  $on_changed$\n"
787                  "  return this;\n"
788                  "}\n");
789   printer->Annotate("{", "}", descriptor_);
790   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
791                                /* builder */ true);
792   printer->Print(
793       variables_,
794       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
795       "  $name$_ = java.util.Collections.emptyList();\n"
796       "  $clear_mutable_bit_builder$;\n"
797       "  $on_changed$\n"
798       "  return this;\n"
799       "}\n");
800   printer->Annotate("{", "}", descriptor_);
801 
802   if (SupportUnknownEnumValue(descriptor_->file())) {
803     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
804     printer->Print(variables_,
805                    "$deprecation$public java.util.List<java.lang.Integer>\n"
806                    "${$get$capitalized_name$ValueList$}$() {\n"
807                    "  return java.util.Collections.unmodifiableList($name$_);\n"
808                    "}\n");
809     printer->Annotate("{", "}", descriptor_);
810     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
811                                           LIST_INDEXED_GETTER);
812     printer->Print(variables_,
813                    "$deprecation$public int "
814                    "${$get$capitalized_name$Value$}$(int index) {\n"
815                    "  return $name$_.get(index);\n"
816                    "}\n");
817     printer->Annotate("{", "}", descriptor_);
818     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
819                                           LIST_INDEXED_GETTER,
820                                           /* builder */ true);
821     printer->Print(
822         variables_,
823         "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
824         "    int index, int value) {\n"
825         "  ensure$capitalized_name$IsMutable();\n"
826         "  $name$_.set(index, value);\n"
827         "  $on_changed$\n"
828         "  return this;\n"
829         "}\n");
830     printer->Annotate("{", "}", descriptor_);
831     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_ADDER,
832                                           /* builder */ true);
833     printer->Print(variables_,
834                    "$deprecation$public Builder "
835                    "${$add$capitalized_name$Value$}$(int value) {\n"
836                    "  ensure$capitalized_name$IsMutable();\n"
837                    "  $name$_.add(value);\n"
838                    "  $on_changed$\n"
839                    "  return this;\n"
840                    "}\n");
841     printer->Annotate("{", "}", descriptor_);
842     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
843                                           LIST_MULTI_ADDER, /* builder */ true);
844     printer->Print(
845         variables_,
846         "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
847         "    java.lang.Iterable<java.lang.Integer> values) {\n"
848         "  ensure$capitalized_name$IsMutable();\n"
849         "  for (int value : values) {\n"
850         "    $name$_.add(value);\n"
851         "  }\n"
852         "  $on_changed$\n"
853         "  return this;\n"
854         "}\n");
855     printer->Annotate("{", "}", descriptor_);
856   }
857 }
858 
859 void RepeatedImmutableEnumFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer * printer) const860     GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
861   // noop for enums
862 }
863 
GenerateInitializationCode(io::Printer * printer) const864 void RepeatedImmutableEnumFieldGenerator::GenerateInitializationCode(
865     io::Printer* printer) const {
866   printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
867 }
868 
GenerateBuilderClearCode(io::Printer * printer) const869 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderClearCode(
870     io::Printer* printer) const {
871   printer->Print(variables_,
872                  "$name$_ = java.util.Collections.emptyList();\n"
873                  "$clear_mutable_bit_builder$;\n");
874 }
875 
GenerateMergingCode(io::Printer * printer) const876 void RepeatedImmutableEnumFieldGenerator::GenerateMergingCode(
877     io::Printer* printer) const {
878   // The code below does two optimizations:
879   //   1. If the other list is empty, there's nothing to do. This ensures we
880   //      don't allocate a new array if we already have an immutable one.
881   //   2. If the other list is non-empty and our current list is empty, we can
882   //      reuse the other list which is guaranteed to be immutable.
883   printer->Print(variables_,
884                  "if (!other.$name$_.isEmpty()) {\n"
885                  "  if ($name$_.isEmpty()) {\n"
886                  "    $name$_ = other.$name$_;\n"
887                  "    $clear_mutable_bit_builder$;\n"
888                  "  } else {\n"
889                  "    ensure$capitalized_name$IsMutable();\n"
890                  "    $name$_.addAll(other.$name$_);\n"
891                  "  }\n"
892                  "  $on_changed$\n"
893                  "}\n");
894 }
895 
GenerateBuildingCode(io::Printer * printer) const896 void RepeatedImmutableEnumFieldGenerator::GenerateBuildingCode(
897     io::Printer* printer) const {
898   // The code below ensures that the result has an immutable list. If our
899   // list is immutable, we can just reuse it. If not, we make it immutable.
900   printer->Print(
901       variables_,
902       "if ($get_mutable_bit_builder$) {\n"
903       "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
904       "  $clear_mutable_bit_builder$;\n"
905       "}\n"
906       "result.$name$_ = $name$_;\n");
907 }
908 
GenerateBuilderParsingCode(io::Printer * printer) const909 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderParsingCode(
910     io::Printer* printer) const {
911   // Read and store the enum
912   if (SupportUnknownEnumValue(descriptor_->file())) {
913     printer->Print(variables_,
914                    "int tmpRaw = input.readEnum();\n"
915                    "ensure$capitalized_name$IsMutable();\n"
916                    "$name$_.add(tmpRaw);\n");
917   } else {
918     printer->Print(variables_,
919                    "int tmpRaw = input.readEnum();\n"
920                    "$type$ tmpValue =\n"
921                    "    $type$.forNumber(tmpRaw);\n"
922                    "if (tmpValue == null) {\n"
923                    "  mergeUnknownVarintField($number$, tmpRaw);\n"
924                    "} else {\n"
925                    "  ensure$capitalized_name$IsMutable();\n"
926                    "  $name$_.add(tmpRaw);\n"
927                    "}\n");
928   }
929 }
930 
GenerateBuilderParsingCodeFromPacked(io::Printer * printer) const931 void RepeatedImmutableEnumFieldGenerator::GenerateBuilderParsingCodeFromPacked(
932     io::Printer* printer) const {
933   // Wrap GenerateParsingCode's contents with a while loop.
934 
935   printer->Print(variables_,
936                  "int length = input.readRawVarint32();\n"
937                  "int oldLimit = input.pushLimit(length);\n"
938                  "while(input.getBytesUntilLimit() > 0) {\n");
939   printer->Indent();
940 
941   GenerateBuilderParsingCode(printer);
942 
943   printer->Outdent();
944   printer->Print(variables_,
945                  "}\n"
946                  "input.popLimit(oldLimit);\n");
947 }
948 
GenerateSerializationCode(io::Printer * printer) const949 void RepeatedImmutableEnumFieldGenerator::GenerateSerializationCode(
950     io::Printer* printer) const {
951   if (descriptor_->is_packed()) {
952     printer->Print(variables_,
953                    "if (get$capitalized_name$List().size() > 0) {\n"
954                    "  output.writeUInt32NoTag($tag$);\n"
955                    "  output.writeUInt32NoTag($name$MemoizedSerializedSize);\n"
956                    "}\n"
957                    "for (int i = 0; i < $name$_.size(); i++) {\n"
958                    "  output.writeEnumNoTag($name$_.get(i));\n"
959                    "}\n");
960   } else {
961     printer->Print(variables_,
962                    "for (int i = 0; i < $name$_.size(); i++) {\n"
963                    "  output.writeEnum($number$, $name$_.get(i));\n"
964                    "}\n");
965   }
966 }
967 
GenerateSerializedSizeCode(io::Printer * printer) const968 void RepeatedImmutableEnumFieldGenerator::GenerateSerializedSizeCode(
969     io::Printer* printer) const {
970   printer->Print(variables_,
971                  "{\n"
972                  "  int dataSize = 0;\n");
973   printer->Indent();
974 
975   printer->Print(variables_,
976                  "for (int i = 0; i < $name$_.size(); i++) {\n"
977                  "  dataSize += com.google.protobuf.CodedOutputStream\n"
978                  "    .computeEnumSizeNoTag($name$_.get(i));\n"
979                  "}\n");
980   printer->Print("size += dataSize;\n");
981   if (descriptor_->is_packed()) {
982     printer->Print(variables_,
983                    "if (!get$capitalized_name$List().isEmpty()) {"
984                    "  size += $tag_size$;\n"
985                    "  size += com.google.protobuf.CodedOutputStream\n"
986                    "    .computeUInt32SizeNoTag(dataSize);\n"
987                    "}");
988   } else {
989     printer->Print(variables_, "size += $tag_size$ * $name$_.size();\n");
990   }
991 
992   // cache the data size for packed fields.
993   if (descriptor_->is_packed()) {
994     printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n");
995   }
996 
997   printer->Outdent();
998   printer->Print("}\n");
999 }
1000 
GenerateEqualsCode(io::Printer * printer) const1001 void RepeatedImmutableEnumFieldGenerator::GenerateEqualsCode(
1002     io::Printer* printer) const {
1003   printer->Print(variables_,
1004                  "if (!$name$_.equals(other.$name$_)) return false;\n");
1005 }
1006 
GenerateHashCode(io::Printer * printer) const1007 void RepeatedImmutableEnumFieldGenerator::GenerateHashCode(
1008     io::Printer* printer) const {
1009   printer->Print(variables_,
1010                  "if (get$capitalized_name$Count() > 0) {\n"
1011                  "  hash = (37 * hash) + $constant_name$;\n"
1012                  "  hash = (53 * hash) + $name$_.hashCode();\n"
1013                  "}\n");
1014 }
1015 
GetBoxedType() const1016 std::string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const {
1017   return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
1018 }
1019 
1020 }  // namespace java
1021 }  // namespace compiler
1022 }  // namespace protobuf
1023 }  // namespace google
1024