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