• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #include "google/protobuf/compiler/java/lite/map_field.h"
9 
10 #include <cstdint>
11 #include <string>
12 
13 #include "google/protobuf/compiler/java/context.h"
14 #include "google/protobuf/compiler/java/doc_comment.h"
15 #include "google/protobuf/compiler/java/field_common.h"
16 #include "google/protobuf/compiler/java/helpers.h"
17 #include "google/protobuf/compiler/java/internal_helpers.h"
18 #include "google/protobuf/compiler/java/name_resolver.h"
19 #include "google/protobuf/io/printer.h"
20 
21 // Must be last.
22 #include "google/protobuf/port_def.inc"
23 
24 namespace google {
25 namespace protobuf {
26 namespace compiler {
27 namespace java {
28 
29 namespace {
30 using Semantic = ::google::protobuf::io::AnnotationCollector::Semantic;
31 
TypeName(const FieldDescriptor * field,ClassNameResolver * name_resolver,bool boxed)32 std::string TypeName(const FieldDescriptor* field,
33                      ClassNameResolver* name_resolver, bool boxed) {
34   if (GetJavaType(field) == JAVATYPE_MESSAGE) {
35     return name_resolver->GetImmutableClassName(field->message_type());
36   } else if (GetJavaType(field) == JAVATYPE_ENUM) {
37     return name_resolver->GetImmutableClassName(field->enum_type());
38   } else {
39     return std::string(boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
40                              : PrimitiveTypeName(GetJavaType(field)));
41   }
42 }
43 
KotlinTypeName(const FieldDescriptor * field,ClassNameResolver * name_resolver)44 std::string KotlinTypeName(const FieldDescriptor* field,
45                            ClassNameResolver* name_resolver) {
46   if (GetJavaType(field) == JAVATYPE_MESSAGE) {
47     return name_resolver->GetImmutableClassName(field->message_type());
48   } else if (GetJavaType(field) == JAVATYPE_ENUM) {
49     return name_resolver->GetImmutableClassName(field->enum_type());
50   } else {
51     return std::string(KotlinTypeName(GetJavaType(field)));
52   }
53 }
54 
WireType(const FieldDescriptor * field)55 std::string WireType(const FieldDescriptor* field) {
56   return absl::StrCat("com.google.protobuf.WireFormat.FieldType.",
57                       FieldTypeName(field->type()));
58 }
59 
SetMessageVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,Context * context,absl::flat_hash_map<absl::string_view,std::string> * variables)60 void SetMessageVariables(
61     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
62     const FieldGeneratorInfo* info, Context* context,
63     absl::flat_hash_map<absl::string_view, std::string>* variables) {
64   SetCommonFieldVariables(descriptor, info, variables);
65 
66   ClassNameResolver* name_resolver = context->GetNameResolver();
67   (*variables)["type"] =
68       name_resolver->GetImmutableClassName(descriptor->message_type());
69   const FieldDescriptor* key = MapKeyField(descriptor);
70   const FieldDescriptor* value = MapValueField(descriptor);
71   const JavaType keyJavaType = GetJavaType(key);
72   const JavaType valueJavaType = GetJavaType(value);
73 
74   std::string pass_through_nullness =
75       context->options().opensource_runtime
76           ? "/* nullable */\n"
77           : "@com.google.protobuf.Internal.ProtoPassThroughNullness ";
78 
79   (*variables)["key_type"] = TypeName(key, name_resolver, false);
80   (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
81   (*variables)["kt_key_type"] = KotlinTypeName(key, name_resolver);
82   (*variables)["kt_value_type"] = KotlinTypeName(value, name_resolver);
83   (*variables)["key_wire_type"] = WireType(key);
84   (*variables)["key_default_value"] =
85       DefaultValue(key, true, name_resolver, context->options());
86   // We use `x.getClass()` as a null check because it generates less bytecode
87   // than an `if (x == null) { throw ... }` statement.
88   (*variables)["key_null_check"] =
89       IsReferenceType(keyJavaType)
90           ? "java.lang.Class<?> keyClass = key.getClass();"
91           : "";
92   (*variables)["value_null_check"] =
93       IsReferenceType(valueJavaType)
94           ? "java.lang.Class<?> valueClass = value.getClass();"
95           : "";
96 
97   if (GetJavaType(value) == JAVATYPE_ENUM) {
98     // We store enums as Integers internally.
99     (*variables)["value_type"] = "int";
100     (*variables)["value_type_pass_through_nullness"] = "int";
101     (*variables)["boxed_value_type"] = "java.lang.Integer";
102     (*variables)["value_wire_type"] = WireType(value);
103     (*variables)["value_default_value"] =
104         DefaultValue(value, true, name_resolver, context->options()) +
105         ".getNumber()";
106 
107     (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
108 
109     variables->insert(
110         {"value_enum_type_pass_through_nullness",
111          absl::StrCat(pass_through_nullness, (*variables)["value_enum_type"])});
112 
113     if (SupportUnknownEnumValue(value)) {
114       // Map unknown values to a special UNRECOGNIZED value if supported.
115       variables->insert(
116           {"unrecognized_value",
117            absl::StrCat((*variables)["value_enum_type"], ".UNRECOGNIZED")});
118     } else {
119       // Map unknown values to the default value if we don't have UNRECOGNIZED.
120       (*variables)["unrecognized_value"] =
121           DefaultValue(value, true, name_resolver, context->options());
122     }
123   } else {
124     (*variables)["value_type"] = TypeName(value, name_resolver, false);
125 
126     variables->insert(
127         {"value_type_pass_through_nullness",
128          absl::StrCat(
129              (IsReferenceType(valueJavaType) ? pass_through_nullness : ""),
130              (*variables)["value_type"])});
131 
132     (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
133     (*variables)["value_wire_type"] = WireType(value);
134     (*variables)["value_default_value"] =
135         DefaultValue(value, true, name_resolver, context->options());
136   }
137   variables->insert(
138       {"type_parameters", absl::StrCat((*variables)["boxed_key_type"], ", ",
139                                        (*variables)["boxed_value_type"])});
140   // TODO: Add @deprecated javadoc when generating javadoc is supported
141   // by the proto compiler
142   (*variables)["deprecation"] =
143       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
144   variables->insert(
145       {"kt_deprecation",
146        descriptor->options().deprecated()
147            ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
148                           (*variables)["name"], " is deprecated\") ")
149            : ""});
150 
151   variables->insert(
152       {"default_entry", absl::StrCat((*variables)["capitalized_name"],
153                                      "DefaultEntryHolder.defaultEntry")});
154   // { and } variables are used as delimiters when emitting annotations.
155   (*variables)["{"] = "";
156   (*variables)["}"] = "";
157 }
158 
159 }  // namespace
160 
ImmutableMapFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)161 ImmutableMapFieldLiteGenerator::ImmutableMapFieldLiteGenerator(
162     const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
163     : descriptor_(descriptor),
164       context_(context),
165       name_resolver_(context->GetNameResolver()) {
166   SetMessageVariables(descriptor, messageBitIndex, 0,
167                       context->GetFieldGeneratorInfo(descriptor), context,
168                       &variables_);
169 }
170 
~ImmutableMapFieldLiteGenerator()171 ImmutableMapFieldLiteGenerator::~ImmutableMapFieldLiteGenerator() {}
172 
GetNumBitsForMessage() const173 int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const { return 0; }
174 
GenerateInterfaceMembers(io::Printer * printer) const175 void ImmutableMapFieldLiteGenerator::GenerateInterfaceMembers(
176     io::Printer* printer) const {
177   WriteFieldDocComment(printer, descriptor_, context_->options());
178   printer->Print(variables_,
179                  "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
180   printer->Annotate("{", "}", descriptor_);
181   WriteFieldDocComment(printer, descriptor_, context_->options());
182   printer->Print(variables_,
183                  "$deprecation$boolean ${$contains$capitalized_name$$}$(\n"
184                  "    $key_type$ key);\n");
185   printer->Annotate("{", "}", descriptor_);
186   const FieldDescriptor* value = MapValueField(descriptor_);
187   if (GetJavaType(value) == JAVATYPE_ENUM) {
188     if (context_->options().opensource_runtime) {
189       printer->Print(variables_,
190                      "/**\n"
191                      " * Use {@link #get$capitalized_name$Map()} instead.\n"
192                      " */\n"
193                      "@java.lang.Deprecated\n"
194                      "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
195                      "${$get$capitalized_name$$}$();\n");
196       printer->Annotate("{", "}", descriptor_);
197     }
198     WriteFieldDocComment(printer, descriptor_, context_->options());
199     printer->Print(
200         variables_,
201         "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
202         "${$get$capitalized_name$Map$}$();\n");
203     printer->Annotate("{", "}", descriptor_);
204     WriteFieldDocComment(printer, descriptor_, context_->options());
205     printer->Print(variables_,
206                    "$deprecation$$value_enum_type_pass_through_nullness$ "
207                    "${$get$capitalized_name$OrDefault$}$(\n"
208                    "    $key_type$ key,\n"
209                    "    $value_enum_type_pass_through_nullness$ "
210                    "        defaultValue);\n");
211     printer->Annotate("{", "}", descriptor_);
212     WriteFieldDocComment(printer, descriptor_, context_->options());
213     printer->Print(
214         variables_,
215         "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
216         "    $key_type$ key);\n");
217     printer->Annotate("{", "}", descriptor_);
218     if (SupportUnknownEnumValue(value)) {
219       printer->Print(
220           variables_,
221           "/**\n"
222           " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
223           " */\n"
224           "@java.lang.Deprecated\n"
225           "java.util.Map<$type_parameters$>\n"
226           "${$get$capitalized_name$Value$}$();\n");
227       printer->Annotate("{", "}", descriptor_);
228       WriteFieldDocComment(printer, descriptor_, context_->options());
229       printer->Print(variables_,
230                      "$deprecation$java.util.Map<$type_parameters$>\n"
231                      "${$get$capitalized_name$ValueMap$}$();\n");
232       printer->Annotate("{", "}", descriptor_);
233       WriteFieldDocComment(printer, descriptor_, context_->options());
234       printer->Print(variables_,
235                      "$deprecation$\n"
236                      "$value_type_pass_through_nullness$ "
237                      "${$get$capitalized_name$ValueOrDefault$}$(\n"
238                      "    $key_type$ key,\n"
239                      "    $value_type_pass_through_nullness$ defaultValue);\n");
240       printer->Annotate("{", "}", descriptor_);
241       WriteFieldDocComment(printer, descriptor_, context_->options());
242       printer->Print(variables_,
243                      "$deprecation$\n"
244                      "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
245                      "    $key_type$ key);\n");
246       printer->Annotate("{", "}", descriptor_);
247     }
248   } else {
249     if (context_->options().opensource_runtime) {
250       printer->Print(variables_,
251                      "/**\n"
252                      " * Use {@link #get$capitalized_name$Map()} instead.\n"
253                      " */\n"
254                      "@java.lang.Deprecated\n"
255                      "java.util.Map<$type_parameters$>\n"
256                      "${$get$capitalized_name$$}$();\n");
257       printer->Annotate("{", "}", descriptor_);
258     }
259     WriteFieldDocComment(printer, descriptor_, context_->options());
260     printer->Print(variables_,
261                    "$deprecation$java.util.Map<$type_parameters$>\n"
262                    "${$get$capitalized_name$Map$}$();\n");
263     printer->Annotate("{", "}", descriptor_);
264     WriteFieldDocComment(printer, descriptor_, context_->options());
265     printer->Print(variables_,
266                    "$deprecation$\n"
267                    "$value_type_pass_through_nullness$ "
268                    "${$get$capitalized_name$OrDefault$}$(\n"
269                    "    $key_type$ key,\n"
270                    "    $value_type_pass_through_nullness$ defaultValue);\n");
271     printer->Annotate("{", "}", descriptor_);
272     WriteFieldDocComment(printer, descriptor_, context_->options());
273     printer->Print(variables_,
274                    "$deprecation$\n"
275                    "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
276                    "    $key_type$ key);\n");
277     printer->Annotate("{", "}", descriptor_);
278   }
279 }
280 
GenerateMembers(io::Printer * printer) const281 void ImmutableMapFieldLiteGenerator::GenerateMembers(
282     io::Printer* printer) const {
283   printer->Print(
284       variables_,
285       "private static final class $capitalized_name$DefaultEntryHolder {\n"
286       "  static final com.google.protobuf.MapEntryLite<\n"
287       "      $type_parameters$> defaultEntry =\n"
288       "          com.google.protobuf.MapEntryLite\n"
289       "          .<$type_parameters$>newDefaultInstance(\n"
290       "              $key_wire_type$,\n"
291       "              $key_default_value$,\n"
292       "              $value_wire_type$,\n"
293       "              $value_default_value$);\n"
294       "}\n");
295   printer->Print(variables_,
296                  "private com.google.protobuf.MapFieldLite<\n"
297                  "    $type_parameters$> $name$_ =\n"
298                  "        com.google.protobuf.MapFieldLite.emptyMapField();\n"
299                  "private com.google.protobuf.MapFieldLite<$type_parameters$>\n"
300                  "internalGet$capitalized_name$() {\n"
301                  "  return $name$_;\n"
302                  "}\n"
303                  "private com.google.protobuf.MapFieldLite<$type_parameters$>\n"
304                  "internalGetMutable$capitalized_name$() {\n"
305                  "  if (!$name$_.isMutable()) {\n"
306                  "    $name$_ = $name$_.mutableCopy();\n"
307                  "  }\n"
308                  "  return $name$_;\n"
309                  "}\n");
310   printer->Print(variables_,
311                  "@java.lang.Override\n"
312                  "$deprecation$\n"
313                  "public int ${$get$capitalized_name$Count$}$() {\n"
314                  "  return internalGet$capitalized_name$().size();\n"
315                  "}\n");
316   printer->Annotate("{", "}", descriptor_);
317   WriteFieldDocComment(printer, descriptor_, context_->options());
318   printer->Print(variables_,
319                  "@java.lang.Override\n"
320                  "$deprecation$\n"
321                  "public boolean ${$contains$capitalized_name$$}$(\n"
322                  "    $key_type$ key) {\n"
323                  "  $key_null_check$\n"
324                  "  return internalGet$capitalized_name$().containsKey(key);\n"
325                  "}\n");
326   printer->Annotate("{", "}", descriptor_);
327 
328   const FieldDescriptor* value = MapValueField(descriptor_);
329   if (GetJavaType(value) == JAVATYPE_ENUM) {
330     printer->Print(
331         variables_,
332         "private static final\n"
333         "com.google.protobuf.Internal.MapAdapter.Converter<\n"
334         "    java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
335         "        com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
336         "            $value_enum_type$.internalGetValueMap(),\n"
337         "            $unrecognized_value$);\n");
338     if (context_->options().opensource_runtime) {
339       printer->Print(
340           variables_,
341           "/**\n"
342           " * Use {@link #get$capitalized_name$Map()} instead.\n"
343           " */\n"
344           "@java.lang.Deprecated\n"
345           "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
346           "${$get$capitalized_name$$}$() {\n"
347           "  return get$capitalized_name$Map();\n"
348           "}\n");
349       printer->Annotate("{", "}", descriptor_);
350     }
351     WriteFieldDocComment(printer, descriptor_, context_->options());
352     printer->Print(
353         variables_,
354         "@java.lang.Override\n"
355         "$deprecation$\n"
356         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
357         "${$get$capitalized_name$Map$}$() {\n"
358         "  return java.util.Collections.unmodifiableMap(\n"
359         "      new com.google.protobuf.Internal.MapAdapter<\n"
360         "        $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
361         "            internalGet$capitalized_name$(),\n"
362         "            $name$ValueConverter));\n"
363         "}\n");
364     printer->Annotate("{", "}", descriptor_);
365     WriteFieldDocComment(printer, descriptor_, context_->options());
366     printer->Print(
367         variables_,
368         "@java.lang.Override\n"
369         "$deprecation$\n"
370         "public $value_enum_type_pass_through_nullness$ "
371         "${$get$capitalized_name$OrDefault$}$(\n"
372         "    $key_type$ key,\n"
373         "    $value_enum_type_pass_through_nullness$ defaultValue) {\n"
374         "  $key_null_check$\n"
375         "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
376         "      internalGet$capitalized_name$();\n"
377         "  return map.containsKey(key)\n"
378         "         ? $name$ValueConverter.doForward(map.get(key))\n"
379         "         : defaultValue;\n"
380         "}\n");
381     printer->Annotate("{", "}", descriptor_);
382     WriteFieldDocComment(printer, descriptor_, context_->options());
383     printer->Print(
384         variables_,
385         "@java.lang.Override\n"
386         "$deprecation$\n"
387         "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
388         "    $key_type$ key) {\n"
389         "  $key_null_check$\n"
390         "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
391         "      internalGet$capitalized_name$();\n"
392         "  if (!map.containsKey(key)) {\n"
393         "    throw new java.lang.IllegalArgumentException();\n"
394         "  }\n"
395         "  return $name$ValueConverter.doForward(map.get(key));\n"
396         "}\n");
397     printer->Annotate("{", "}", descriptor_);
398     if (SupportUnknownEnumValue(value)) {
399       printer->Print(
400           variables_,
401           "/**\n"
402           " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
403           " */\n"
404           "@java.lang.Override\n"
405           "@java.lang.Deprecated\n"
406           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
407           "${$get$capitalized_name$Value$}$() {\n"
408           "  return get$capitalized_name$ValueMap();\n"
409           "}\n");
410       printer->Annotate("{", "}", descriptor_);
411       WriteFieldDocComment(printer, descriptor_, context_->options());
412       printer->Print(
413           variables_,
414           "@java.lang.Override\n"
415           "$deprecation$\n"
416           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
417           "${$get$capitalized_name$ValueMap$}$() {\n"
418           "  return java.util.Collections.unmodifiableMap(\n"
419           "      internalGet$capitalized_name$());\n"
420           "}\n");
421       printer->Annotate("{", "}", descriptor_);
422       WriteFieldDocComment(printer, descriptor_, context_->options());
423       printer->Print(
424           variables_,
425           "@java.lang.Override\n"
426           "$deprecation$\n"
427           "public $value_type_pass_through_nullness$ "
428           "${$get$capitalized_name$ValueOrDefault$}$(\n"
429           "    $key_type$ key,\n"
430           "    $value_type_pass_through_nullness$ defaultValue) {\n"
431           "  $key_null_check$\n"
432           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
433           "      internalGet$capitalized_name$();\n"
434           "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
435           "}\n");
436       printer->Annotate("{", "}", descriptor_);
437       WriteFieldDocComment(printer, descriptor_, context_->options());
438       printer->Print(
439           variables_,
440           "@java.lang.Override\n"
441           "$deprecation$\n"
442           "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
443           "    $key_type$ key) {\n"
444           "  $key_null_check$\n"
445           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
446           "      internalGet$capitalized_name$();\n"
447           "  if (!map.containsKey(key)) {\n"
448           "    throw new java.lang.IllegalArgumentException();\n"
449           "  }\n"
450           "  return map.get(key);\n"
451           "}\n");
452       printer->Annotate("{", "}", descriptor_);
453     }
454   } else {
455     if (context_->options().opensource_runtime) {
456       printer->Print(variables_,
457                      "/**\n"
458                      " * Use {@link #get$capitalized_name$Map()} instead.\n"
459                      " */\n"
460                      "@java.lang.Override\n"
461                      "@java.lang.Deprecated\n"
462                      "public java.util.Map<$type_parameters$> "
463                      "${$get$capitalized_name$$}$() {\n"
464                      "  return get$capitalized_name$Map();\n"
465                      "}\n");
466       printer->Annotate("{", "}", descriptor_);
467     }
468     WriteFieldDocComment(printer, descriptor_, context_->options());
469     printer->Print(variables_,
470                    "@java.lang.Override\n"
471                    "$deprecation$\n"
472                    "public java.util.Map<$type_parameters$> "
473                    "${$get$capitalized_name$Map$}$() {\n"
474                    "  return java.util.Collections.unmodifiableMap(\n"
475                    "      internalGet$capitalized_name$());\n"
476                    "}\n");
477     printer->Annotate("{", "}", descriptor_);
478     WriteFieldDocComment(printer, descriptor_, context_->options());
479     printer->Print(
480         variables_,
481         "@java.lang.Override\n"
482         "$deprecation$\n"
483         "public $value_type_pass_through_nullness$ "
484         "${$get$capitalized_name$OrDefault$}$(\n"
485         "    $key_type$ key,\n"
486         "    $value_type_pass_through_nullness$ defaultValue) {\n"
487         "  $key_null_check$\n"
488         "  java.util.Map<$type_parameters$> map =\n"
489         "      internalGet$capitalized_name$();\n"
490         "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
491         "}\n");
492     printer->Annotate("{", "}", descriptor_);
493     WriteFieldDocComment(printer, descriptor_, context_->options());
494     printer->Print(variables_,
495                    "@java.lang.Override\n"
496                    "$deprecation$\n"
497                    "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
498                    "    $key_type$ key) {\n"
499                    "  $key_null_check$\n"
500                    "  java.util.Map<$type_parameters$> map =\n"
501                    "      internalGet$capitalized_name$();\n"
502                    "  if (!map.containsKey(key)) {\n"
503                    "    throw new java.lang.IllegalArgumentException();\n"
504                    "  }\n"
505                    "  return map.get(key);\n"
506                    "}\n");
507     printer->Annotate("{", "}", descriptor_);
508   }
509 
510   // Generate private setters for the builder to proxy into.
511   if (GetJavaType(value) == JAVATYPE_ENUM) {
512     WriteFieldDocComment(printer, descriptor_, context_->options());
513     printer->Print(
514         variables_,
515         "private java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
516         "getMutable$capitalized_name$Map() {\n"
517         "  return new com.google.protobuf.Internal.MapAdapter<\n"
518         "      $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
519         "          internalGetMutable$capitalized_name$(),\n"
520         "          $name$ValueConverter);\n"
521         "}\n");
522     if (SupportUnknownEnumValue(value)) {
523       WriteFieldDocComment(printer, descriptor_, context_->options());
524       printer->Print(
525           variables_,
526           "private java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
527           "getMutable$capitalized_name$ValueMap() {\n"
528           "  return internalGetMutable$capitalized_name$();\n"
529           "}\n");
530     }
531   } else {
532     WriteFieldDocComment(printer, descriptor_, context_->options());
533     printer->Print(variables_,
534                    "private java.util.Map<$type_parameters$>\n"
535                    "getMutable$capitalized_name$Map() {\n"
536                    "  return internalGetMutable$capitalized_name$();\n"
537                    "}\n");
538   }
539 }
540 
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const541 void ImmutableMapFieldLiteGenerator::GenerateFieldInfo(
542     io::Printer* printer, std::vector<uint16_t>* output) const {
543   WriteIntToUtf16CharSequence(descriptor_->number(), output);
544   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
545                               output);
546   printer->Print(variables_,
547                  "\"$name$_\",\n"
548                  "$default_entry$,\n");
549   const FieldDescriptor* value = MapValueField(descriptor_);
550   if (!SupportUnknownEnumValue(value) && GetJavaType(value) == JAVATYPE_ENUM) {
551     PrintEnumVerifierLogic(printer, MapValueField(descriptor_), variables_,
552                            /*var_name=*/"$value_enum_type$",
553                            /*terminating_string=*/",\n",
554                            /*enforce_lite=*/context_->EnforceLite());
555   }
556 }
557 
GenerateBuilderMembers(io::Printer * printer) const558 void ImmutableMapFieldLiteGenerator::GenerateBuilderMembers(
559     io::Printer* printer) const {
560   printer->Print(variables_,
561                  "@java.lang.Override\n"
562                  "$deprecation$\n"
563                  "public int ${$get$capitalized_name$Count$}$() {\n"
564                  "  return instance.get$capitalized_name$Map().size();\n"
565                  "}\n");
566   printer->Annotate("{", "}", descriptor_);
567   WriteFieldDocComment(printer, descriptor_, context_->options());
568   printer->Print(
569       variables_,
570       "@java.lang.Override\n"
571       "$deprecation$\n"
572       "public boolean ${$contains$capitalized_name$$}$(\n"
573       "    $key_type$ key) {\n"
574       "  $key_null_check$\n"
575       "  return instance.get$capitalized_name$Map().containsKey(key);\n"
576       "}\n");
577   printer->Annotate("{", "}", descriptor_);
578   printer->Print(variables_,
579                  "$deprecation$\n"
580                  "public Builder ${$clear$capitalized_name$$}$() {\n"
581                  "  copyOnWrite();\n"
582                  "  instance.getMutable$capitalized_name$Map().clear();\n"
583                  "  return this;\n"
584                  "}\n");
585   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
586   WriteFieldDocComment(printer, descriptor_, context_->options());
587   printer->Print(variables_,
588                  "$deprecation$\n"
589                  "public Builder ${$remove$capitalized_name$$}$(\n"
590                  "    $key_type$ key) {\n"
591                  "  $key_null_check$\n"
592                  "  copyOnWrite();\n"
593                  "  instance.getMutable$capitalized_name$Map().remove(key);\n"
594                  "  return this;\n"
595                  "}\n");
596   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
597   const FieldDescriptor* value = MapValueField(descriptor_);
598   if (GetJavaType(value) == JAVATYPE_ENUM) {
599     if (context_->options().opensource_runtime) {
600       printer->Print(
601           variables_,
602           "/**\n"
603           " * Use {@link #get$capitalized_name$Map()} instead.\n"
604           " */\n"
605           "@java.lang.Deprecated\n"
606           "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
607           "${$get$capitalized_name$$}$() {\n"
608           "  return get$capitalized_name$Map();\n"
609           "}\n");
610       printer->Annotate("{", "}", descriptor_);
611     }
612     WriteFieldDocComment(printer, descriptor_, context_->options());
613     printer->Print(variables_,
614                    "@java.lang.Override\n"
615                    "$deprecation$\n"
616                    "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
617                    "${$get$capitalized_name$Map$}$() {\n"
618                    "  return java.util.Collections.unmodifiableMap(\n"
619                    "      instance.get$capitalized_name$Map());\n"
620                    "}\n");
621     printer->Annotate("{", "}", descriptor_);
622     WriteFieldDocComment(printer, descriptor_, context_->options());
623     printer->Print(
624         variables_,
625         "@java.lang.Override\n"
626         "$deprecation$\n"
627         "public $value_enum_type_pass_through_nullness$ "
628         "${$get$capitalized_name$OrDefault$}$(\n"
629         "    $key_type$ key,\n"
630         "    $value_enum_type_pass_through_nullness$ defaultValue) {\n"
631         "  $key_null_check$\n"
632         "  java.util.Map<$boxed_key_type$, $value_enum_type$> map =\n"
633         "      instance.get$capitalized_name$Map();\n"
634         "  return map.containsKey(key)\n"
635         "         ? map.get(key)\n"
636         "         : defaultValue;\n"
637         "}\n");
638     printer->Annotate("{", "}", descriptor_);
639     WriteFieldDocComment(printer, descriptor_, context_->options());
640     printer->Print(
641         variables_,
642         "@java.lang.Override\n"
643         "$deprecation$\n"
644         "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
645         "    $key_type$ key) {\n"
646         "  $key_null_check$\n"
647         "  java.util.Map<$boxed_key_type$, $value_enum_type$> map =\n"
648         "      instance.get$capitalized_name$Map();\n"
649         "  if (!map.containsKey(key)) {\n"
650         "    throw new java.lang.IllegalArgumentException();\n"
651         "  }\n"
652         "  return map.get(key);\n"
653         "}\n");
654     printer->Annotate("{", "}", descriptor_);
655     WriteFieldDocComment(printer, descriptor_, context_->options());
656     printer->Print(
657         variables_,
658         "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
659         "    $key_type$ key,\n"
660         "    $value_enum_type$ value) {\n"
661         "  $key_null_check$\n"
662         "  $value_null_check$\n"
663         "  copyOnWrite();\n"
664         "  instance.getMutable$capitalized_name$Map().put(key, value);\n"
665         "  return this;\n"
666         "}\n");
667     printer->Annotate("{", "}", descriptor_);
668     WriteFieldDocComment(printer, descriptor_, context_->options());
669     printer->Print(
670         variables_,
671         "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
672         "    java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
673         "  copyOnWrite();\n"
674         "  instance.getMutable$capitalized_name$Map().putAll(values);\n"
675         "  return this;\n"
676         "}\n");
677     printer->Annotate("{", "}", descriptor_, Semantic::kSet);
678     if (SupportUnknownEnumValue(value)) {
679       printer->Print(
680           variables_,
681           "/**\n"
682           " * Use {@link #get$capitalized_name$ValueMap()} instead.\n"
683           " */\n"
684           "@java.lang.Override\n"
685           "@java.lang.Deprecated\n"
686           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
687           "${$get$capitalized_name$Value$}$() {\n"
688           "  return get$capitalized_name$ValueMap();\n"
689           "}\n");
690       printer->Annotate("{", "}", descriptor_);
691       WriteFieldDocComment(printer, descriptor_, context_->options());
692       printer->Print(
693           variables_,
694           "@java.lang.Override\n"
695           "$deprecation$\n"
696           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
697           "${$get$capitalized_name$ValueMap$}$() {\n"
698           "  return java.util.Collections.unmodifiableMap(\n"
699           "      instance.get$capitalized_name$ValueMap());\n"
700           "}\n");
701       printer->Annotate("{", "}", descriptor_);
702       WriteFieldDocComment(printer, descriptor_, context_->options());
703       printer->Print(
704           variables_,
705           "@java.lang.Override\n"
706           "$deprecation$\n"
707           "public $value_type_pass_through_nullness$ "
708           "${$get$capitalized_name$ValueOrDefault$}$(\n"
709           "    $key_type$ key,\n"
710           "    $value_type_pass_through_nullness$ defaultValue) {\n"
711           "  $key_null_check$\n"
712           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
713           "      instance.get$capitalized_name$ValueMap();\n"
714           "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
715           "}\n");
716       printer->Annotate("{", "}", descriptor_);
717       WriteFieldDocComment(printer, descriptor_, context_->options());
718       printer->Print(
719           variables_,
720           "@java.lang.Override\n"
721           "$deprecation$\n"
722           "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
723           "    $key_type$ key) {\n"
724           "  $key_null_check$\n"
725           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
726           "      instance.get$capitalized_name$ValueMap();\n"
727           "  if (!map.containsKey(key)) {\n"
728           "    throw new java.lang.IllegalArgumentException();\n"
729           "  }\n"
730           "  return map.get(key);\n"
731           "}\n");
732       printer->Annotate("{", "}", descriptor_);
733       WriteFieldDocComment(printer, descriptor_, context_->options());
734       printer->Print(
735           variables_,
736           "$deprecation$public Builder ${$put$capitalized_name$Value$}$(\n"
737           "    $key_type$ key,\n"
738           "    $value_type$ value) {\n"
739           "  $key_null_check$\n"
740           "  copyOnWrite();\n"
741           "  instance.getMutable$capitalized_name$ValueMap().put(key, value);\n"
742           "  return this;\n"
743           "}\n");
744       printer->Annotate("{", "}", descriptor_);
745       WriteFieldDocComment(printer, descriptor_, context_->options());
746       printer->Print(
747           variables_,
748           "$deprecation$public Builder ${$putAll$capitalized_name$Value$}$(\n"
749           "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
750           "  copyOnWrite();\n"
751           "  instance.getMutable$capitalized_name$ValueMap().putAll(values);\n"
752           "  return this;\n"
753           "}\n");
754       printer->Annotate("{", "}", descriptor_, Semantic::kSet);
755     }
756   } else {
757     if (context_->options().opensource_runtime) {
758       printer->Print(variables_,
759                      "/**\n"
760                      " * Use {@link #get$capitalized_name$Map()} instead.\n"
761                      " */\n"
762                      "@java.lang.Override\n"
763                      "@java.lang.Deprecated\n"
764                      "public java.util.Map<$type_parameters$> "
765                      "${$get$capitalized_name$$}$() {\n"
766                      "  return get$capitalized_name$Map();\n"
767                      "}\n");
768       printer->Annotate("{", "}", descriptor_);
769     }
770     WriteFieldDocComment(printer, descriptor_, context_->options());
771     printer->Print(variables_,
772                    "@java.lang.Override\n"
773                    "$deprecation$"
774                    "public java.util.Map<$type_parameters$> "
775                    "${$get$capitalized_name$Map$}$() {\n"
776                    "  return java.util.Collections.unmodifiableMap(\n"
777                    "      instance.get$capitalized_name$Map());\n"
778                    "}\n");
779     printer->Annotate("{", "}", descriptor_);
780     WriteFieldDocComment(printer, descriptor_, context_->options());
781     printer->Print(
782         variables_,
783         "@java.lang.Override\n"
784         "$deprecation$\n"
785         "public $value_type_pass_through_nullness$ "
786         "${$get$capitalized_name$OrDefault$}$(\n"
787         "    $key_type$ key,\n"
788         "    $value_type_pass_through_nullness$ defaultValue) {\n"
789         "  $key_null_check$\n"
790         "  java.util.Map<$type_parameters$> map =\n"
791         "      instance.get$capitalized_name$Map();\n"
792         "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
793         "}\n");
794     printer->Annotate("{", "}", descriptor_);
795     WriteFieldDocComment(printer, descriptor_, context_->options());
796     printer->Print(variables_,
797                    "@java.lang.Override\n"
798                    "$deprecation$\n"
799                    "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
800                    "    $key_type$ key) {\n"
801                    "  $key_null_check$\n"
802                    "  java.util.Map<$type_parameters$> map =\n"
803                    "      instance.get$capitalized_name$Map();\n"
804                    "  if (!map.containsKey(key)) {\n"
805                    "    throw new java.lang.IllegalArgumentException();\n"
806                    "  }\n"
807                    "  return map.get(key);\n"
808                    "}\n");
809     printer->Annotate("{", "}", descriptor_);
810     WriteFieldDocComment(printer, descriptor_, context_->options());
811     printer->Print(
812         variables_,
813         "$deprecation$"
814         "public Builder ${$put$capitalized_name$$}$(\n"
815         "    $key_type$ key,\n"
816         "    $value_type$ value) {\n"
817         "  $key_null_check$\n"
818         "  $value_null_check$\n"
819         "  copyOnWrite();\n"
820         "  instance.getMutable$capitalized_name$Map().put(key, value);\n"
821         "  return this;\n"
822         "}\n");
823     printer->Annotate("{", "}", descriptor_, Semantic::kSet);
824     WriteFieldDocComment(printer, descriptor_, context_->options());
825     printer->Print(
826         variables_,
827         "$deprecation$"
828         "public Builder ${$putAll$capitalized_name$$}$(\n"
829         "    java.util.Map<$type_parameters$> values) {\n"
830         "  copyOnWrite();\n"
831         "  instance.getMutable$capitalized_name$Map().putAll(values);\n"
832         "  return this;\n"
833         "}\n");
834     printer->Annotate("{", "}", descriptor_, Semantic::kSet);
835   }
836 }
837 
GenerateKotlinDslMembers(io::Printer * printer) const838 void ImmutableMapFieldLiteGenerator::GenerateKotlinDslMembers(
839     io::Printer* printer) const {
840   auto vars = printer->WithVars(variables_);
841   JvmNameContext name_ctx = {context_->options(), printer};
842   printer->Print(
843       "/**\n"
844       " * An uninstantiable, behaviorless type to represent the field in\n"
845       " * generics.\n"
846       " */\n"
847       "@kotlin.OptIn"
848       "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
849       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
850       " : com.google.protobuf.kotlin.DslProxy()\n");
851 
852   WriteFieldDocComment(printer, descriptor_, context_->options(),
853                        /* kdoc */ true);
854   printer->Emit(
855       {
856           {"jvm_name",
857            [&] { JvmName("get$kt_capitalized_name$Map", name_ctx); }},
858       },
859       "$kt_deprecation$ public val $kt_name$: "
860       "com.google.protobuf.kotlin.DslMap"
861       "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
862       "$  jvm_synthetic$"
863       "$jvm_name$"
864       "  get() = com.google.protobuf.kotlin.DslMap(\n"
865       "    $kt_dsl_builder$.${$$kt_property_name$Map$}$\n"
866       "  )\n");
867 
868   WriteFieldDocComment(printer, descriptor_, context_->options(),
869                        /* kdoc */ true);
870   printer->Emit(
871       {
872           {"jvm_name", [&] { JvmName("put$kt_capitalized_name$", name_ctx); }},
873       },
874       "$jvm_name$"
875       "public fun com.google.protobuf.kotlin.DslMap"
876       "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
877       "  .put(key: $kt_key_type$, value: $kt_value_type$) {\n"
878       "     $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n"
879       "   }\n");
880 
881   WriteFieldDocComment(printer, descriptor_, context_->options(),
882                        /* kdoc */ true);
883   printer->Emit(
884       {
885           {"jvm_name", [&] { JvmName("set$kt_capitalized_name$", name_ctx); }},
886       },
887       "$jvm_synthetic$"
888       "$jvm_name$"
889       "@Suppress(\"NOTHING_TO_INLINE\")\n"
890       "public inline operator fun com.google.protobuf.kotlin.DslMap"
891       "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
892       "  .set(key: $kt_key_type$, value: $kt_value_type$) {\n"
893       "     put(key, value)\n"
894       "   }\n");
895 
896   WriteFieldDocComment(printer, descriptor_, context_->options(),
897                        /* kdoc */ true);
898   printer->Emit(
899       {
900           {"jvm_name",
901            [&] { JvmName("remove$kt_capitalized_name$", name_ctx); }},
902       },
903       "$jvm_synthetic$"
904       "$jvm_name$"
905       "public fun com.google.protobuf.kotlin.DslMap"
906       "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
907       "  .remove(key: $kt_key_type$) {\n"
908       "     $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n"
909       "   }\n");
910 
911   WriteFieldDocComment(printer, descriptor_, context_->options(),
912                        /* kdoc */ true);
913   printer->Emit(
914       {
915           {"jvm_name",
916            [&] { JvmName("putAll$kt_capitalized_name$", name_ctx); }},
917       },
918       "$jvm_synthetic$"
919       "$jvm_name$"
920       "public fun com.google.protobuf.kotlin.DslMap"
921       "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
922       "  .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) "
923       "{\n"
924       "     $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n"
925       "   }\n");
926 
927   WriteFieldDocComment(printer, descriptor_, context_->options(),
928                        /* kdoc */ true);
929   printer->Emit(
930       {
931           {"jvm_name",
932            [&] { JvmName("clear$kt_capitalized_name$", name_ctx); }},
933       },
934       "$jvm_synthetic$"
935       "$jvm_name$"
936       "public fun com.google.protobuf.kotlin.DslMap"
937       "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n"
938       "  .clear() {\n"
939       "     $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
940       "   }\n");
941 }
942 
GenerateInitializationCode(io::Printer * printer) const943 void ImmutableMapFieldLiteGenerator::GenerateInitializationCode(
944     io::Printer* printer) const {
945   // Nothing to initialize.
946 }
947 
GetBoxedType() const948 std::string ImmutableMapFieldLiteGenerator::GetBoxedType() const {
949   return name_resolver_->GetImmutableClassName(descriptor_->message_type());
950 }
951 
952 }  // namespace java
953 }  // namespace compiler
954 }  // namespace protobuf
955 }  // namespace google
956 
957 #include "google/protobuf/port_undef.inc"
958