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