• 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 // Author: kenton@google.com (Kenton Varda)
9 // Author: jonp@google.com (Jon Perlow)
10 //  Based on original Protocol Buffers design by
11 //  Sanjay Ghemawat, Jeff Dean, and others.
12 
13 #include "google/protobuf/compiler/java/lite/string_field.h"
14 
15 #include <cstdint>
16 #include <string>
17 
18 #include "absl/container/flat_hash_map.h"
19 #include "absl/log/absl_check.h"
20 #include "absl/strings/str_cat.h"
21 #include "google/protobuf/compiler/java/context.h"
22 #include "google/protobuf/compiler/java/doc_comment.h"
23 #include "google/protobuf/compiler/java/field_common.h"
24 #include "google/protobuf/compiler/java/helpers.h"
25 #include "google/protobuf/compiler/java/internal_helpers.h"
26 #include "google/protobuf/compiler/java/name_resolver.h"
27 #include "google/protobuf/wire_format.h"
28 
29 namespace google {
30 namespace protobuf {
31 namespace compiler {
32 namespace java {
33 
34 using internal::WireFormat;
35 using internal::WireFormatLite;
36 using Semantic = ::google::protobuf::io::AnnotationCollector::Semantic;
37 
38 namespace {
39 
SetPrimitiveVariables(const FieldDescriptor * descriptor,int messageBitIndex,int builderBitIndex,const FieldGeneratorInfo * info,ClassNameResolver * name_resolver,absl::flat_hash_map<absl::string_view,std::string> * variables,Context * context)40 void SetPrimitiveVariables(
41     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
42     const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
43     absl::flat_hash_map<absl::string_view, std::string>* variables,
44     Context* context) {
45   SetCommonFieldVariables(descriptor, info, variables);
46 
47   (*variables)["empty_list"] =
48       "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()";
49 
50   (*variables)["default"] =
51       ImmutableDefaultValue(descriptor, name_resolver, context->options());
52   (*variables)["default_init"] = absl::StrCat(
53       "= ",
54       ImmutableDefaultValue(descriptor, name_resolver, context->options()));
55   (*variables)["capitalized_type"] = "java.lang.String";
56   (*variables)["tag"] =
57       absl::StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
58   (*variables)["tag_size"] = absl::StrCat(
59       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
60 
61   // TODO: Add @deprecated javadoc when generating javadoc is supported
62   // by the proto compiler
63   (*variables)["deprecation"] =
64       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
65   variables->insert(
66       {"kt_deprecation",
67        descriptor->options().deprecated()
68            ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
69                           (*variables)["name"], " is deprecated\") ")
70            : ""});
71   (*variables)["required"] = descriptor->is_required() ? "true" : "false";
72   if (!context->options().opensource_runtime) {
73     (*variables)["enforce_utf8"] = CheckUtf8(descriptor) ? "true" : "false";
74   }
75 
76   if (HasHasbit(descriptor)) {
77     if (!context->options().opensource_runtime) {
78       (*variables)["bit_field_id"] = absl::StrCat(messageBitIndex / 32);
79       (*variables)["bit_field_name"] = GetBitFieldNameForBit(messageBitIndex);
80       (*variables)["bit_field_mask"] =
81           absl::StrCat(1 << (messageBitIndex % 32));
82     }
83     // For singular messages and builders, one bit is used for the hasField bit.
84     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
85 
86     // Note that these have a trailing ";".
87     (*variables)["set_has_field_bit_message"] =
88         absl::StrCat(GenerateSetBit(messageBitIndex), ";");
89     (*variables)["clear_has_field_bit_message"] =
90         absl::StrCat(GenerateClearBit(messageBitIndex), ";");
91 
92     (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
93   } else {
94     (*variables)["set_has_field_bit_message"] = "";
95     (*variables)["clear_has_field_bit_message"] = "";
96 
97     variables->insert({"is_field_present_message",
98                        absl::StrCat("!", (*variables)["name"], "_.isEmpty()")});
99   }
100 
101   // Annotations often use { and } variables to denote text ranges.
102   (*variables)["{"] = "";
103   (*variables)["}"] = "";
104 }
105 
106 }  // namespace
107 
108 // ===================================================================
109 
ImmutableStringFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)110 ImmutableStringFieldLiteGenerator::ImmutableStringFieldLiteGenerator(
111     const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
112     : descriptor_(descriptor),
113       messageBitIndex_(messageBitIndex),
114       name_resolver_(context->GetNameResolver()),
115       context_(context) {
116   SetPrimitiveVariables(descriptor, messageBitIndex, 0,
117                         context->GetFieldGeneratorInfo(descriptor),
118                         name_resolver_, &variables_, context);
119 }
120 
~ImmutableStringFieldLiteGenerator()121 ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
122 
GetNumBitsForMessage() const123 int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
124   return HasHasbit(descriptor_) ? 1 : 0;
125 }
126 
127 // A note about how strings are handled. In the SPEED and CODE_SIZE runtimes,
128 // strings are not stored as java.lang.String in the Message because of two
129 // issues:
130 //
131 //  1. It wouldn't roundtrip byte arrays that were not valid UTF-8 encoded
132 //     strings, but rather fields that were raw bytes incorrectly marked
133 //     as strings in the proto file. This is common because in the proto1
134 //     syntax, string was the way to indicate bytes and C++ engineers can
135 //     easily make this mistake without affecting the C++ API. By converting to
136 //     strings immediately, some java code might corrupt these byte arrays as
137 //     it passes through a java server even if the field was never accessed by
138 //     application code.
139 //
140 //  2. There's a performance hit to converting between bytes and strings and
141 //     it many cases, the field is never even read by the application code. This
142 //     avoids unnecessary conversions in the common use cases.
143 //
144 // In the LITE_RUNTIME, we store strings as java.lang.String because we assume
145 // that the users of this runtime are not subject to proto1 constraints and are
146 // running code on devices that are user facing. That is, the developers are
147 // properly incentivized to only fetch the data they need to read and wish to
148 // reduce the number of allocations incurred when running on a user's device.
149 
150 // TODO: Consider dropping all of the *Bytes() methods. They really
151 //     shouldn't be necessary or used on devices.
GenerateInterfaceMembers(io::Printer * printer) const152 void ImmutableStringFieldLiteGenerator::GenerateInterfaceMembers(
153     io::Printer* printer) const {
154   if (descriptor_->has_presence()) {
155     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
156                                  context_->options());
157     printer->Print(variables_,
158                    "$deprecation$boolean ${$has$capitalized_name$$}$();\n");
159     printer->Annotate("{", "}", descriptor_);
160   }
161   WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
162                                context_->options());
163   printer->Print(
164       variables_,
165       "$deprecation$java.lang.String ${$get$capitalized_name$$}$();\n");
166   printer->Annotate("{", "}", descriptor_);
167   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER,
168                                           context_->options());
169   printer->Print(variables_,
170                  "$deprecation$com.google.protobuf.ByteString\n"
171                  "    ${$get$capitalized_name$Bytes$}$();\n");
172   printer->Annotate("{", "}", descriptor_);
173 }
174 
GenerateMembers(io::Printer * printer) const175 void ImmutableStringFieldLiteGenerator::GenerateMembers(
176     io::Printer* printer) const {
177   if (!context_->options().opensource_runtime) {
178     printer->Print(
179         variables_,
180         "@com.google.protobuf.ProtoField(\n"
181         "  isRequired=$required$)\n");
182     if (HasHasbit(descriptor_)) {
183       printer->Print(variables_,
184                      "@com.google.protobuf.ProtoPresenceCheckedField(\n"
185                      "  presenceBitsId=$bit_field_id$,\n"
186                      "  mask=$bit_field_mask$)\n");
187     }
188   }
189   printer->Print(variables_, "private java.lang.String $name$_;\n");
190   PrintExtraFieldInfo(variables_, printer);
191 
192   if (descriptor_->has_presence()) {
193     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
194                                  context_->options());
195     printer->Print(
196         variables_,
197         "@java.lang.Override\n"
198         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
199         "  return $get_has_field_bit_message$;\n"
200         "}\n");
201     printer->Annotate("{", "}", descriptor_);
202   }
203 
204   WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
205                                context_->options());
206   printer->Print(
207       variables_,
208       "@java.lang.Override\n"
209       "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
210       "  return $name$_;\n"
211       "}\n");
212   printer->Annotate("{", "}", descriptor_);
213   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER,
214                                           context_->options());
215   printer->Print(
216       variables_,
217       "@java.lang.Override\n"
218       "$deprecation$public com.google.protobuf.ByteString\n"
219       "    ${$get$capitalized_name$Bytes$}$() {\n"
220       "  return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n"
221       "}\n");
222   printer->Annotate("{", "}", descriptor_);
223 
224   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
225                                context_->options());
226   printer->Print(variables_,
227                  "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
228                  "private void set$capitalized_name$(\n"
229                  "    java.lang.String value) {\n"
230                  "  value.getClass();  // minimal bytecode null check\n"
231                  "  $set_has_field_bit_message$\n"
232                  "  $name$_ = value;\n"
233                  "}\n");
234   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
235                                context_->options());
236   printer->Print(variables_,
237                  "private void clear$capitalized_name$() {\n"
238                  "  $clear_has_field_bit_message$\n"
239                  // The default value is not a simple literal so we want to
240                  // avoid executing it multiple times.  Instead, get the default
241                  // out of the default instance.
242                  "  $name$_ = getDefaultInstance().get$capitalized_name$();\n"
243                  "}\n");
244 
245   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
246                                           context_->options());
247   printer->Print(variables_,
248                  "private void set$capitalized_name$Bytes(\n"
249                  "    com.google.protobuf.ByteString value) {\n");
250   if (CheckUtf8(descriptor_)) {
251     printer->Print(variables_, "  checkByteStringIsUtf8(value);\n");
252   }
253   printer->Print(variables_,
254                  "  $name$_ = value.toStringUtf8();\n"
255                  "  $set_has_field_bit_message$\n"
256                  "}\n");
257 }
258 
GenerateBuilderMembers(io::Printer * printer) const259 void ImmutableStringFieldLiteGenerator::GenerateBuilderMembers(
260     io::Printer* printer) const {
261   if (descriptor_->has_presence()) {
262     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
263                                  context_->options());
264     printer->Print(
265         variables_,
266         "@java.lang.Override\n"
267         "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
268         "  return instance.has$capitalized_name$();\n"
269         "}\n");
270     printer->Annotate("{", "}", descriptor_);
271   }
272 
273   WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
274                                context_->options());
275   printer->Print(
276       variables_,
277       "@java.lang.Override\n"
278       "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
279       "  return instance.get$capitalized_name$();\n"
280       "}\n");
281   printer->Annotate("{", "}", descriptor_);
282 
283   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER,
284                                           context_->options());
285   printer->Print(variables_,
286                  "@java.lang.Override\n"
287                  "$deprecation$public com.google.protobuf.ByteString\n"
288                  "    ${$get$capitalized_name$Bytes$}$() {\n"
289                  "  return instance.get$capitalized_name$Bytes();\n"
290                  "}\n");
291   printer->Annotate("{", "}", descriptor_);
292 
293   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
294                                context_->options(),
295                                /* builder */ true);
296   printer->Print(variables_,
297                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
298                  "    java.lang.String value) {\n"
299                  "  copyOnWrite();\n"
300                  "  instance.set$capitalized_name$(value);\n"
301                  "  return this;\n"
302                  "}\n");
303   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
304   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
305                                context_->options(),
306                                /* builder */ true);
307   printer->Print(
308       variables_,
309       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
310       "  copyOnWrite();\n"
311       "  instance.clear$capitalized_name$();\n"
312       "  return this;\n"
313       "}\n");
314   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
315 
316   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
317                                           context_->options(),
318                                           /* builder */ true);
319   printer->Print(
320       variables_,
321       "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
322       "    com.google.protobuf.ByteString value) {\n"
323       "  copyOnWrite();\n"
324       "  instance.set$capitalized_name$Bytes(value);\n"
325       "  return this;\n"
326       "}\n");
327   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
328 }
329 
GenerateKotlinDslMembers(io::Printer * printer) const330 void ImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers(
331     io::Printer* printer) const {
332   auto vars = printer->WithVars(variables_);
333   JvmNameContext name_ctx = {context_->options(), printer};
334   WriteFieldDocComment(printer, descriptor_, context_->options(),
335                        /* kdoc */ true);
336   printer->Emit(
337       {
338           {"jvm_name_get",
339            [&] { JvmName("${$get$kt_capitalized_name$$}$", name_ctx); }},
340           {"jvm_name_set",
341            [&] { JvmName("${$set$kt_capitalized_name$$}$", name_ctx); }},
342       },
343       "$kt_deprecation$public var $kt_name$: kotlin.String\n"
344       "  $jvm_name_get$"
345       "  get() = $kt_dsl_builder$.${$$kt_safe_name$$}$\n"
346       "  $jvm_name_set$"
347       "  set(value) {\n"
348       "    $kt_dsl_builder$.${$$kt_safe_name$$}$ = value\n"
349       "  }\n");
350 
351   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
352                                context_->options(),
353                                /* builder */ false, /* kdoc */ true);
354   printer->Print(
355       "public fun ${$clear$kt_capitalized_name$$}$() {\n"
356       "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
357       "}\n");
358 
359   if (descriptor_->has_presence()) {
360     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
361                                  context_->options(),
362                                  /* builder */ false, /* kdoc */ true);
363     printer->Print(
364         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
365         "  return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n"
366         "}\n");
367   }
368 }
369 
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const370 void ImmutableStringFieldLiteGenerator::GenerateFieldInfo(
371     io::Printer* printer, std::vector<uint16_t>* output) const {
372   WriteIntToUtf16CharSequence(descriptor_->number(), output);
373   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
374                               output);
375   if (HasHasbit(descriptor_)) {
376     WriteIntToUtf16CharSequence(messageBitIndex_, output);
377   }
378   printer->Print(variables_, "\"$name$_\",\n");
379 }
380 
GenerateInitializationCode(io::Printer * printer) const381 void ImmutableStringFieldLiteGenerator::GenerateInitializationCode(
382     io::Printer* printer) const {
383   printer->Print(variables_, "$name$_ = $default$;\n");
384 }
385 
GetBoxedType() const386 std::string ImmutableStringFieldLiteGenerator::GetBoxedType() const {
387   return "java.lang.String";
388 }
389 
390 // ===================================================================
391 
ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)392 ImmutableStringOneofFieldLiteGenerator::ImmutableStringOneofFieldLiteGenerator(
393     const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
394     : ImmutableStringFieldLiteGenerator(descriptor, messageBitIndex, context) {
395   const OneofGeneratorInfo* info =
396       context->GetOneofGeneratorInfo(descriptor->containing_oneof());
397   SetCommonOneofVariables(descriptor, info, &variables_);
398 }
399 
400 ImmutableStringOneofFieldLiteGenerator::
~ImmutableStringOneofFieldLiteGenerator()401     ~ImmutableStringOneofFieldLiteGenerator() {}
402 
GenerateMembers(io::Printer * printer) const403 void ImmutableStringOneofFieldLiteGenerator::GenerateMembers(
404     io::Printer* printer) const {
405   PrintExtraFieldInfo(variables_, printer);
406   ABSL_DCHECK(descriptor_->has_presence());
407   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
408                                context_->options());
409   printer->Print(variables_,
410                  "@java.lang.Override\n"
411                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
412                  "  return $has_oneof_case_message$;\n"
413                  "}\n");
414   printer->Annotate("{", "}", descriptor_);
415 
416   WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
417                                context_->options());
418   printer->Print(
419       variables_,
420       "@java.lang.Override\n"
421       "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
422       "  java.lang.String ref $default_init$;\n"
423       "  if ($has_oneof_case_message$) {\n"
424       "    ref = (java.lang.String) $oneof_name$_;\n"
425       "  }\n"
426       "  return ref;\n"
427       "}\n");
428   printer->Annotate("{", "}", descriptor_);
429 
430   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER,
431                                           context_->options());
432   printer->Print(variables_,
433                  "@java.lang.Override\n"
434                  "$deprecation$public com.google.protobuf.ByteString\n"
435                  "    ${$get$capitalized_name$Bytes$}$() {\n"
436                  "  java.lang.String ref $default_init$;\n"
437                  "  if ($has_oneof_case_message$) {\n"
438                  "    ref = (java.lang.String) $oneof_name$_;\n"
439                  "  }\n"
440                  "  return com.google.protobuf.ByteString.copyFromUtf8(ref);\n"
441                  "}\n");
442   printer->Annotate("{", "}", descriptor_);
443 
444   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
445                                context_->options());
446   printer->Print(variables_,
447                  "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
448                  "private void ${$set$capitalized_name$$}$(\n"
449                  "    java.lang.String value) {\n"
450                  "  value.getClass();  // minimal bytecode null check\n"
451                  "  $set_oneof_case_message$;\n"
452                  "  $oneof_name$_ = value;\n"
453                  "}\n");
454   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
455   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
456                                context_->options());
457   printer->Print(variables_,
458                  "private void ${$clear$capitalized_name$$}$() {\n"
459                  "  if ($has_oneof_case_message$) {\n"
460                  "    $clear_oneof_case_message$;\n"
461                  "    $oneof_name$_ = null;\n"
462                  "  }\n"
463                  "}\n");
464   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
465 
466   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
467                                           context_->options());
468   printer->Print(variables_,
469                  "private void ${$set$capitalized_name$Bytes$}$(\n"
470                  "    com.google.protobuf.ByteString value) {\n");
471   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
472   if (CheckUtf8(descriptor_)) {
473     printer->Print(variables_, "  checkByteStringIsUtf8(value);\n");
474   }
475   printer->Print(variables_,
476                  "  $oneof_name$_ = value.toStringUtf8();\n"
477                  "  $set_oneof_case_message$;\n"
478                  "}\n");
479 }
480 
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const481 void ImmutableStringOneofFieldLiteGenerator::GenerateFieldInfo(
482     io::Printer* printer, std::vector<uint16_t>* output) const {
483   WriteIntToUtf16CharSequence(descriptor_->number(), output);
484   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
485                               output);
486   WriteIntToUtf16CharSequence(descriptor_->containing_oneof()->index(), output);
487 }
488 
GenerateBuilderMembers(io::Printer * printer) const489 void ImmutableStringOneofFieldLiteGenerator::GenerateBuilderMembers(
490     io::Printer* printer) const {
491   ABSL_DCHECK(descriptor_->has_presence());
492   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
493                                context_->options());
494   printer->Print(variables_,
495                  "@java.lang.Override\n"
496                  "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
497                  "  return instance.has$capitalized_name$();\n"
498                  "}\n");
499   printer->Annotate("{", "}", descriptor_);
500 
501   WriteFieldAccessorDocComment(printer, descriptor_, GETTER,
502                                context_->options());
503   printer->Print(
504       variables_,
505       "@java.lang.Override\n"
506       "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
507       "  return instance.get$capitalized_name$();\n"
508       "}\n");
509   printer->Annotate("{", "}", descriptor_);
510 
511   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER,
512                                           context_->options());
513   printer->Print(variables_,
514                  "@java.lang.Override\n"
515                  "$deprecation$public com.google.protobuf.ByteString\n"
516                  "    ${$get$capitalized_name$Bytes$}$() {\n"
517                  "  return instance.get$capitalized_name$Bytes();\n"
518                  "}\n");
519   printer->Annotate("{", "}", descriptor_);
520 
521   WriteFieldAccessorDocComment(printer, descriptor_, SETTER,
522                                context_->options(),
523                                /* builder */ true);
524   printer->Print(variables_,
525                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
526                  "    java.lang.String value) {\n"
527                  "  copyOnWrite();\n"
528                  "  instance.set$capitalized_name$(value);\n"
529                  "  return this;\n"
530                  "}\n");
531   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
532   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
533                                context_->options(),
534                                /* builder */ true);
535   printer->Print(
536       variables_,
537       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
538       "  copyOnWrite();\n"
539       "  instance.clear$capitalized_name$();\n"
540       "  return this;\n"
541       "}\n");
542   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
543 
544   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, SETTER,
545                                           context_->options(),
546                                           /* builder */ true);
547   printer->Print(
548       variables_,
549       "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
550       "    com.google.protobuf.ByteString value) {\n"
551       "  copyOnWrite();\n"
552       "  instance.set$capitalized_name$Bytes(value);\n"
553       "  return this;\n"
554       "}\n");
555   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
556 }
557 
558 // ===================================================================
559 
560 RepeatedImmutableStringFieldLiteGenerator::
RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor * descriptor,int messageBitIndex,Context * context)561     RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
562                                               int messageBitIndex,
563                                               Context* context)
564     : descriptor_(descriptor),
565       context_(context),
566       name_resolver_(context->GetNameResolver()) {
567   SetPrimitiveVariables(descriptor, messageBitIndex, 0,
568                         context->GetFieldGeneratorInfo(descriptor),
569                         name_resolver_, &variables_, context);
570 }
571 
572 RepeatedImmutableStringFieldLiteGenerator::
~RepeatedImmutableStringFieldLiteGenerator()573     ~RepeatedImmutableStringFieldLiteGenerator() {}
574 
GetNumBitsForMessage() const575 int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
576   return 0;
577 }
578 
GenerateInterfaceMembers(io::Printer * printer) const579 void RepeatedImmutableStringFieldLiteGenerator::GenerateInterfaceMembers(
580     io::Printer* printer) const {
581   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
582                                context_->options());
583   printer->Print(variables_,
584                  "$deprecation$java.util.List<java.lang.String>\n"
585                  "    ${$get$capitalized_name$List$}$();\n");
586   printer->Annotate("{", "}", descriptor_);
587   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT,
588                                context_->options());
589   printer->Print(variables_,
590                  "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
591   printer->Annotate("{", "}", descriptor_);
592   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER,
593                                context_->options());
594   printer->Print(variables_,
595                  "$deprecation$java.lang.String "
596                  "${$get$capitalized_name$$}$(int index);\n");
597   printer->Annotate("{", "}", descriptor_);
598   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER,
599                                context_->options());
600   printer->Print(variables_,
601                  "$deprecation$com.google.protobuf.ByteString\n"
602                  "    ${$get$capitalized_name$Bytes$}$(int index);\n");
603   printer->Annotate("{", "}", descriptor_);
604 }
605 
GenerateMembers(io::Printer * printer) const606 void RepeatedImmutableStringFieldLiteGenerator::GenerateMembers(
607     io::Printer* printer) const {
608   printer->Print(
609       variables_,
610       "private com.google.protobuf.Internal.ProtobufList<java.lang.String> "
611       "$name$_;\n");
612   PrintExtraFieldInfo(variables_, printer);
613   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
614                                context_->options());
615   printer->Print(variables_,
616                  "@java.lang.Override\n"
617                  "$deprecation$public java.util.List<java.lang.String> "
618                  "${$get$capitalized_name$List$}$() {\n"
619                  "  return $name$_;\n"  // note:  unmodifiable list
620                  "}\n");
621   printer->Annotate("{", "}", descriptor_);
622   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT,
623                                context_->options());
624   printer->Print(
625       variables_,
626       "@java.lang.Override\n"
627       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
628       "  return $name$_.size();\n"
629       "}\n");
630   printer->Annotate("{", "}", descriptor_);
631   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER,
632                                context_->options());
633   printer->Print(variables_,
634                  "@java.lang.Override\n"
635                  "$deprecation$public java.lang.String "
636                  "${$get$capitalized_name$$}$(int index) {\n"
637                  "  return $name$_.get(index);\n"
638                  "}\n");
639   printer->Annotate("{", "}", descriptor_);
640   WriteFieldStringBytesAccessorDocComment(
641       printer, descriptor_, LIST_INDEXED_GETTER, context_->options());
642   printer->Print(variables_,
643                  "@java.lang.Override\n"
644                  "$deprecation$public com.google.protobuf.ByteString\n"
645                  "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
646                  "  return com.google.protobuf.ByteString.copyFromUtf8(\n"
647                  "      $name$_.get(index));\n"
648                  "}\n");
649   printer->Annotate("{", "}", descriptor_);
650 
651   printer->Print(
652       variables_,
653       "private void ensure$capitalized_name$IsMutable() {\n"
654       // Use a temporary to avoid a redundant iget-object.
655       "  com.google.protobuf.Internal.ProtobufList<java.lang.String> tmp =\n"
656       "      $name$_;"
657       "  if (!tmp.isModifiable()) {\n"
658       "    $name$_ =\n"
659       "        com.google.protobuf.GeneratedMessageLite.mutableCopy(tmp);\n"
660       "   }\n"
661       "}\n");
662 
663   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
664                                context_->options());
665   printer->Print(variables_,
666                  "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
667                  "private void set$capitalized_name$(\n"
668                  "    int index, java.lang.String value) {\n"
669                  "  value.getClass();  // minimal bytecode null check\n"
670                  "  ensure$capitalized_name$IsMutable();\n"
671                  "  $name$_.set(index, value);\n"
672                  "}\n");
673   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
674                                context_->options());
675   printer->Print(variables_,
676                  "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n"
677                  "private void add$capitalized_name$(\n"
678                  "    java.lang.String value) {\n"
679                  "  value.getClass();  // minimal bytecode null check\n"
680                  "  ensure$capitalized_name$IsMutable();\n"
681                  "  $name$_.add(value);\n"
682                  "}\n");
683   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
684                                context_->options());
685   printer->Print(variables_,
686                  "private void addAll$capitalized_name$(\n"
687                  "    java.lang.Iterable<java.lang.String> values) {\n"
688                  "  ensure$capitalized_name$IsMutable();\n"
689                  "  com.google.protobuf.AbstractMessageLite.addAll(\n"
690                  "      values, $name$_);\n"
691                  "}\n");
692   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
693                                context_->options());
694   printer->Print(variables_,
695                  "private void clear$capitalized_name$() {\n"
696                  "  $name$_ = $empty_list$;\n"
697                  "}\n");
698 
699   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER,
700                                           context_->options());
701   printer->Print(variables_,
702                  "private void add$capitalized_name$Bytes(\n"
703                  "    com.google.protobuf.ByteString value) {\n");
704   if (CheckUtf8(descriptor_)) {
705     printer->Print(variables_, "  checkByteStringIsUtf8(value);\n");
706   }
707   printer->Print(variables_,
708                  "  ensure$capitalized_name$IsMutable();\n"
709                  "  $name$_.add(value.toStringUtf8());\n"
710                  "}\n");
711 }
712 
GenerateBuilderMembers(io::Printer * printer) const713 void RepeatedImmutableStringFieldLiteGenerator::GenerateBuilderMembers(
714     io::Printer* printer) const {
715   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
716                                context_->options());
717   printer->Print(variables_,
718                  "@java.lang.Override\n"
719                  "$deprecation$public java.util.List<java.lang.String>\n"
720                  "    ${$get$capitalized_name$List$}$() {\n"
721                  "  return java.util.Collections.unmodifiableList(\n"
722                  "      instance.get$capitalized_name$List());\n"
723                  "}\n");
724   printer->Annotate("{", "}", descriptor_);
725   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT,
726                                context_->options());
727   printer->Print(
728       variables_,
729       "@java.lang.Override\n"
730       "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
731       "  return instance.get$capitalized_name$Count();\n"
732       "}\n");
733   printer->Annotate("{", "}", descriptor_);
734   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER,
735                                context_->options());
736   printer->Print(variables_,
737                  "@java.lang.Override\n"
738                  "$deprecation$public java.lang.String "
739                  "${$get$capitalized_name$$}$(int index) {\n"
740                  "  return instance.get$capitalized_name$(index);\n"
741                  "}\n");
742   printer->Annotate("{", "}", descriptor_);
743   WriteFieldStringBytesAccessorDocComment(
744       printer, descriptor_, LIST_INDEXED_GETTER, context_->options());
745   printer->Print(variables_,
746                  "@java.lang.Override\n"
747                  "$deprecation$public com.google.protobuf.ByteString\n"
748                  "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
749                  "  return instance.get$capitalized_name$Bytes(index);\n"
750                  "}\n");
751   printer->Annotate("{", "}", descriptor_);
752   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
753                                context_->options(),
754                                /* builder */ true);
755   printer->Print(variables_,
756                  "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
757                  "    int index, java.lang.String value) {\n"
758                  "  copyOnWrite();\n"
759                  "  instance.set$capitalized_name$(index, value);\n"
760                  "  return this;\n"
761                  "}\n");
762   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
763   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
764                                context_->options(),
765                                /* builder */ true);
766   printer->Print(variables_,
767                  "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
768                  "    java.lang.String value) {\n"
769                  "  copyOnWrite();\n"
770                  "  instance.add$capitalized_name$(value);\n"
771                  "  return this;\n"
772                  "}\n");
773   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
774   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
775                                context_->options(),
776                                /* builder */ true);
777   printer->Print(variables_,
778                  "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
779                  "    java.lang.Iterable<java.lang.String> values) {\n"
780                  "  copyOnWrite();\n"
781                  "  instance.addAll$capitalized_name$(values);\n"
782                  "  return this;\n"
783                  "}\n");
784   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
785   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
786                                context_->options(),
787                                /* builder */ true);
788   printer->Print(
789       variables_,
790       "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
791       "  copyOnWrite();\n"
792       "  instance.clear$capitalized_name$();\n"
793       "  return this;\n"
794       "}\n");
795   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
796 
797   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER,
798                                           context_->options(),
799                                           /* builder */ true);
800   printer->Print(
801       variables_,
802       "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
803       "    com.google.protobuf.ByteString value) {\n"
804       "  copyOnWrite();\n"
805       "  instance.add$capitalized_name$Bytes(value);\n"
806       "  return this;\n"
807       "}\n");
808   printer->Annotate("{", "}", descriptor_, Semantic::kSet);
809 }
810 
GenerateKotlinDslMembers(io::Printer * printer) const811 void RepeatedImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers(
812     io::Printer* printer) const {
813   auto vars = printer->WithVars(variables_);
814   JvmNameContext name_ctx = {context_->options(), printer};
815   printer->Print(
816       "/**\n"
817       " * An uninstantiable, behaviorless type to represent the field in\n"
818       " * generics.\n"
819       " */\n"
820       "@kotlin.OptIn"
821       "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
822       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
823       " : com.google.protobuf.kotlin.DslProxy()\n");
824 
825   // property for List<String>
826   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
827                                context_->options(),
828                                /* builder */ false, /* kdoc */ true);
829   printer->Print(
830       "$kt_deprecation$public val $kt_name$: "
831       "com.google.protobuf.kotlin.DslList"
832       "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>\n"
833       "@kotlin.OptIn"
834       "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
835       "  get() = com.google.protobuf.kotlin.DslList(\n"
836       "    $kt_dsl_builder$.${$$kt_property_name$List$}$\n"
837       "  )\n");
838 
839   // List<String>.add(String)
840   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
841                                context_->options(),
842                                /* builder */ false, /* kdoc */ true);
843   printer->Emit(
844       {
845           {"jvm_name", [&] { JvmName("add$kt_capitalized_name$", name_ctx); }},
846       },
847       "$jvm_synthetic$"
848       "$jvm_name$"
849       "public fun com.google.protobuf.kotlin.DslList"
850       "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
851       "add(value: kotlin.String) {\n"
852       "  $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n"
853       "}\n");
854 
855   // List<String> += String
856   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
857                                context_->options(),
858                                /* builder */ false, /* kdoc */ true);
859   printer->Emit(
860       {
861           {"jvm_name",
862            [&] { JvmName("plusAssign$kt_capitalized_name$", name_ctx); }},
863       },
864       "$jvm_synthetic$"
865       "$jvm_name$"
866       "@Suppress(\"NOTHING_TO_INLINE\")\n"
867       "public inline operator fun com.google.protobuf.kotlin.DslList"
868       "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
869       "plusAssign(value: kotlin.String) {\n"
870       "  add(value)\n"
871       "}\n");
872 
873   // List<String>.addAll(Iterable<String>)
874   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
875                                context_->options(),
876                                /* builder */ false, /* kdoc */ true);
877   printer->Emit(
878       {
879           {"jvm_name",
880            [&] { JvmName("addAll$kt_capitalized_name$", name_ctx); }},
881       },
882       "$jvm_synthetic$"
883       "$jvm_name$"
884       "public fun com.google.protobuf.kotlin.DslList"
885       "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
886       "addAll(values: kotlin.collections.Iterable<kotlin.String>) {\n"
887       "  $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n"
888       "}\n");
889 
890   // List<String> += Iterable<String>
891   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
892                                context_->options(),
893                                /* builder */ false, /* kdoc */ true);
894   printer->Emit(
895       {
896           {"jvm_name",
897            [&] { JvmName("plusAssignAll$kt_capitalized_name$", name_ctx); }},
898       },
899       "$jvm_synthetic$"
900       "$jvm_name$"
901       "@Suppress(\"NOTHING_TO_INLINE\")\n"
902       "public inline operator fun com.google.protobuf.kotlin.DslList"
903       "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
904       "plusAssign(values: kotlin.collections.Iterable<kotlin.String>) {\n"
905       "  addAll(values)\n"
906       "}\n");
907 
908   // List<String>[Int] = String
909   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
910                                context_->options(),
911                                /* builder */ false, /* kdoc */ true);
912   printer->Emit(
913       {
914           {"jvm_name", [&] { JvmName("set$kt_capitalized_name$", name_ctx); }},
915       },
916       "$jvm_synthetic$"
917       "$jvm_name$"
918       "public operator fun com.google.protobuf.kotlin.DslList"
919       "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
920       "set(index: kotlin.Int, value: kotlin.String) {\n"
921       "  $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n"
922       "}");
923 
924   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
925                                context_->options(),
926                                /* builder */ false, /* kdoc */ true);
927   printer->Emit(
928       {
929           {"jvm_name", [&] { JvmName("set$kt_capitalized_name$", name_ctx); }},
930       },
931       "$jvm_synthetic$"
932       "$jvm_name$"
933       "public fun com.google.protobuf.kotlin.DslList"
934       "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>."
935       "clear() {\n"
936       "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
937       "}");
938 }
939 
GenerateFieldInfo(io::Printer * printer,std::vector<uint16_t> * output) const940 void RepeatedImmutableStringFieldLiteGenerator::GenerateFieldInfo(
941     io::Printer* printer, std::vector<uint16_t>* output) const {
942   WriteIntToUtf16CharSequence(descriptor_->number(), output);
943   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
944                               output);
945   printer->Print(variables_, "\"$name$_\",\n");
946 }
947 
GenerateInitializationCode(io::Printer * printer) const948 void RepeatedImmutableStringFieldLiteGenerator::GenerateInitializationCode(
949     io::Printer* printer) const {
950   printer->Print(variables_, "$name$_ = $empty_list$;\n");
951 }
952 
GetBoxedType() const953 std::string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
954   return "java.lang.String";
955 }
956 
957 }  // namespace java
958 }  // namespace compiler
959 }  // namespace protobuf
960 }  // namespace google
961