1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34
35 #include <google/protobuf/compiler/java/java_message.h>
36
37 #include <algorithm>
38 #include <cstdint>
39 #include <map>
40 #include <memory>
41 #include <vector>
42
43 #include <google/protobuf/io/coded_stream.h>
44 #include <google/protobuf/io/printer.h>
45 #include <google/protobuf/descriptor.h>
46 #include <google/protobuf/wire_format.h>
47 #include <google/protobuf/stubs/strutil.h>
48 #include <google/protobuf/stubs/substitute.h>
49 #include <google/protobuf/compiler/java/java_context.h>
50 #include <google/protobuf/compiler/java/java_doc_comment.h>
51 #include <google/protobuf/compiler/java/java_enum.h>
52 #include <google/protobuf/compiler/java/java_extension.h>
53 #include <google/protobuf/compiler/java/java_generator_factory.h>
54 #include <google/protobuf/compiler/java/java_helpers.h>
55 #include <google/protobuf/compiler/java/java_message_builder.h>
56 #include <google/protobuf/compiler/java/java_message_builder_lite.h>
57 #include <google/protobuf/compiler/java/java_name_resolver.h>
58 #include <google/protobuf/descriptor.pb.h>
59
60 namespace google {
61 namespace protobuf {
62 namespace compiler {
63 namespace java {
64
65 using internal::WireFormat;
66 using internal::WireFormatLite;
67
68 namespace {
MapValueImmutableClassdName(const Descriptor * descriptor,ClassNameResolver * name_resolver)69 std::string MapValueImmutableClassdName(const Descriptor* descriptor,
70 ClassNameResolver* name_resolver) {
71 const FieldDescriptor* value_field = descriptor->map_value();
72 GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
73 return name_resolver->GetImmutableClassName(value_field->message_type());
74 }
75 } // namespace
76
77 // ===================================================================
78
MessageGenerator(const Descriptor * descriptor)79 MessageGenerator::MessageGenerator(const Descriptor* descriptor)
80 : descriptor_(descriptor) {
81 for (int i = 0; i < descriptor_->field_count(); i++) {
82 if (IsRealOneof(descriptor_->field(i))) {
83 oneofs_.insert(descriptor_->field(i)->containing_oneof());
84 }
85 }
86 }
87
~MessageGenerator()88 MessageGenerator::~MessageGenerator() {}
89
90 // ===================================================================
ImmutableMessageGenerator(const Descriptor * descriptor,Context * context)91 ImmutableMessageGenerator::ImmutableMessageGenerator(
92 const Descriptor* descriptor, Context* context)
93 : MessageGenerator(descriptor),
94 context_(context),
95 name_resolver_(context->GetNameResolver()),
96 field_generators_(descriptor, context_) {
97 GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
98 << "Generator factory error: A non-lite message generator is used to "
99 "generate lite messages.";
100 }
101
~ImmutableMessageGenerator()102 ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
103
GenerateStaticVariables(io::Printer * printer,int * bytecode_estimate)104 void ImmutableMessageGenerator::GenerateStaticVariables(
105 io::Printer* printer, int* bytecode_estimate) {
106 // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
107 // used in the construction of descriptors, we have a tricky bootstrapping
108 // problem. To help control static initialization order, we make sure all
109 // descriptors and other static data that depends on them are members of
110 // the outermost class in the file. This way, they will be initialized in
111 // a deterministic order.
112
113 std::map<std::string, std::string> vars;
114 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
115 vars["index"] = StrCat(descriptor_->index());
116 vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
117 if (descriptor_->containing_type() != NULL) {
118 vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
119 }
120 if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
121 // We can only make these package-private since the classes that use them
122 // are in separate files.
123 vars["private"] = "";
124 } else {
125 vars["private"] = "private ";
126 }
127 if (*bytecode_estimate <= kMaxStaticSize) {
128 vars["final"] = "final ";
129 } else {
130 vars["final"] = "";
131 }
132
133 // The descriptor for this type.
134 printer->Print(
135 vars,
136 // TODO(teboring): final needs to be added back. The way to fix it is to
137 // generate methods that can construct the types, and then still declare
138 // the types, and then init them in clinit with the new method calls.
139 "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n"
140 " internal_$identifier$_descriptor;\n");
141 *bytecode_estimate += 30;
142
143 // And the FieldAccessorTable.
144 GenerateFieldAccessorTable(printer, bytecode_estimate);
145
146 // Generate static members for all nested types.
147 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
148 // TODO(kenton): Reuse MessageGenerator objects?
149 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
150 .GenerateStaticVariables(printer, bytecode_estimate);
151 }
152 }
153
GenerateStaticVariableInitializers(io::Printer * printer)154 int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
155 io::Printer* printer) {
156 int bytecode_estimate = 0;
157 std::map<std::string, std::string> vars;
158 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
159 vars["index"] = StrCat(descriptor_->index());
160 vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
161 if (descriptor_->containing_type() != NULL) {
162 vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
163 }
164
165 // The descriptor for this type.
166 if (descriptor_->containing_type() == NULL) {
167 printer->Print(vars,
168 "internal_$identifier$_descriptor =\n"
169 " getDescriptor().getMessageTypes().get($index$);\n");
170 bytecode_estimate += 30;
171 } else {
172 printer->Print(
173 vars,
174 "internal_$identifier$_descriptor =\n"
175 " internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
176 bytecode_estimate += 30;
177 }
178
179 // And the FieldAccessorTable.
180 bytecode_estimate += GenerateFieldAccessorTableInitializer(printer);
181
182 // Generate static member initializers for all nested types.
183 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
184 // TODO(kenton): Reuse MessageGenerator objects?
185 bytecode_estimate +=
186 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
187 .GenerateStaticVariableInitializers(printer);
188 }
189 return bytecode_estimate;
190 }
191
GenerateFieldAccessorTable(io::Printer * printer,int * bytecode_estimate)192 void ImmutableMessageGenerator::GenerateFieldAccessorTable(
193 io::Printer* printer, int* bytecode_estimate) {
194 std::map<std::string, std::string> vars;
195 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
196 if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
197 // We can only make these package-private since the classes that use them
198 // are in separate files.
199 vars["private"] = "";
200 } else {
201 vars["private"] = "private ";
202 }
203 if (*bytecode_estimate <= kMaxStaticSize) {
204 vars["final"] = "final ";
205 } else {
206 vars["final"] = "";
207 }
208 vars["ver"] = GeneratedCodeVersionSuffix();
209 printer->Print(
210 vars,
211 "$private$static $final$\n"
212 " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
213 " internal_$identifier$_fieldAccessorTable;\n");
214
215 // The following bytecode_estimate calculation logic must stay in sync with
216 // the similar logic in the GenerateFieldAccessorTableInitializer method below
217 // to make sure that the generated static final fields are initialized in the
218 // static initialization block directly.
219 //
220 // 6 bytes per field and oneof
221 *bytecode_estimate +=
222 10 + 6 * descriptor_->field_count() + 6 * descriptor_->oneof_decl_count();
223 }
224
GenerateFieldAccessorTableInitializer(io::Printer * printer)225 int ImmutableMessageGenerator::GenerateFieldAccessorTableInitializer(
226 io::Printer* printer) {
227 int bytecode_estimate = 10;
228 printer->Print(
229 "internal_$identifier$_fieldAccessorTable = new\n"
230 " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n"
231 " internal_$identifier$_descriptor,\n"
232 " new java.lang.String[] { ",
233 "identifier", UniqueFileScopeIdentifier(descriptor_), "ver",
234 GeneratedCodeVersionSuffix());
235 // All the bytecode_estimate calculation logic in this method must stay in
236 // sync with the similar logic in the GenerateFieldAccessorTable method
237 // above. See the corresponding comment in GenerateFieldAccessorTable for
238 // details.
239 for (int i = 0; i < descriptor_->field_count(); i++) {
240 const FieldDescriptor* field = descriptor_->field(i);
241 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
242 bytecode_estimate += 6;
243 printer->Print("\"$field_name$\", ", "field_name", info->capitalized_name);
244 }
245 // We reproduce synthetic oneofs here since proto reflection needs these.
246 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
247 const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
248 const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof);
249 bytecode_estimate += 6;
250 printer->Print("\"$oneof_name$\", ", "oneof_name", info->capitalized_name);
251 }
252 printer->Print("});\n");
253 return bytecode_estimate;
254 }
255
256 // ===================================================================
257
GenerateInterface(io::Printer * printer)258 void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
259 MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
260 /* immutable = */ true, "OrBuilder");
261 if (descriptor_->extension_range_count() > 0) {
262 printer->Print(
263 "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
264 " $extra_interfaces$\n"
265 " com.google.protobuf.GeneratedMessage$ver$.\n"
266 " ExtendableMessageOrBuilder<$classname$> {\n",
267 "deprecation",
268 descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
269 "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
270 "classname", descriptor_->name(), "{", "", "}", "", "ver",
271 GeneratedCodeVersionSuffix());
272 } else {
273 printer->Print(
274 "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
275 " $extra_interfaces$\n"
276 " com.google.protobuf.MessageOrBuilder {\n",
277 "deprecation",
278 descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
279 "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
280 "classname", descriptor_->name(), "{", "", "}", "");
281 }
282 printer->Annotate("{", "}", descriptor_);
283
284 printer->Indent();
285 for (int i = 0; i < descriptor_->field_count(); i++) {
286 printer->Print("\n");
287 field_generators_.get(descriptor_->field(i))
288 .GenerateInterfaceMembers(printer);
289 }
290 for (auto oneof : oneofs_) {
291 printer->Print(
292 "\n"
293 "public $classname$.$oneof_capitalized_name$Case "
294 "get$oneof_capitalized_name$Case();\n",
295 "oneof_capitalized_name",
296 context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "classname",
297 context_->GetNameResolver()->GetImmutableClassName(descriptor_));
298 }
299 printer->Outdent();
300
301 printer->Print("}\n");
302 }
303
304 // ===================================================================
305
Generate(io::Printer * printer)306 void ImmutableMessageGenerator::Generate(io::Printer* printer) {
307 bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
308
309 std::map<std::string, std::string> variables;
310 variables["static"] = is_own_file ? "" : "static ";
311 variables["classname"] = descriptor_->name();
312 variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
313 variables["ver"] = GeneratedCodeVersionSuffix();
314 variables["deprecation"] =
315 descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "";
316
317 WriteMessageDocComment(printer, descriptor_);
318 MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
319 /* immutable = */ true);
320 // The builder_type stores the super type name of the nested Builder class.
321 std::string builder_type;
322 if (descriptor_->extension_range_count() > 0) {
323 printer->Print(
324 variables,
325 "$deprecation$public $static$final class $classname$ extends\n");
326 printer->Annotate("classname", descriptor_);
327 printer->Print(
328 variables,
329 " com.google.protobuf.GeneratedMessage$ver$.ExtendableMessage<\n"
330 " $classname$> implements\n"
331 " $extra_interfaces$\n"
332 " $classname$OrBuilder {\n");
333 builder_type = strings::Substitute(
334 "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
335 name_resolver_->GetImmutableClassName(descriptor_),
336 GeneratedCodeVersionSuffix());
337 } else {
338 printer->Print(
339 variables,
340 "$deprecation$public $static$final class $classname$ extends\n");
341 printer->Annotate("classname", descriptor_);
342 printer->Print(variables,
343 " com.google.protobuf.GeneratedMessage$ver$ implements\n"
344 " $extra_interfaces$\n"
345 " $classname$OrBuilder {\n");
346 builder_type =
347 strings::Substitute("com.google.protobuf.GeneratedMessage$0.Builder<?>",
348 GeneratedCodeVersionSuffix());
349 }
350 printer->Print("private static final long serialVersionUID = 0L;\n");
351
352 printer->Indent();
353 // Using builder_type, instead of Builder, prevents the Builder class from
354 // being loaded into PermGen space when the default instance is created.
355 // This optimizes the PermGen space usage for clients that do not modify
356 // messages.
357 printer->Print(
358 "// Use $classname$.newBuilder() to construct.\n"
359 "private $classname$($buildertype$ builder) {\n"
360 " super(builder);\n"
361 "}\n",
362 "classname", descriptor_->name(), "buildertype", builder_type);
363 printer->Print("private $classname$() {\n", "classname", descriptor_->name());
364 printer->Indent();
365 GenerateInitializers(printer);
366 printer->Outdent();
367 printer->Print(
368 "}\n"
369 "\n");
370
371 printer->Print(variables,
372 "@java.lang.Override\n"
373 "@SuppressWarnings({\"unused\"})\n"
374 "protected java.lang.Object newInstance(\n"
375 " UnusedPrivateParameter unused) {\n"
376 " return new $classname$();\n"
377 "}\n"
378 "\n");
379
380 // TODO(b/248149118): Remove this superfluous override.
381 printer->Print(
382 "@java.lang.Override\n"
383 "public final com.google.protobuf.UnknownFieldSet\n"
384 "getUnknownFields() {\n"
385 " return this.unknownFields;\n"
386 "}\n");
387
388 GenerateDescriptorMethods(printer);
389
390 // Nested types
391 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
392 EnumGenerator(descriptor_->enum_type(i), true, context_).Generate(printer);
393 }
394
395 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
396 // Don't generate Java classes for map entry messages.
397 if (IsMapEntry(descriptor_->nested_type(i))) continue;
398 ImmutableMessageGenerator messageGenerator(descriptor_->nested_type(i),
399 context_);
400 messageGenerator.GenerateInterface(printer);
401 messageGenerator.Generate(printer);
402 }
403
404 // Integers for bit fields.
405 int totalBits = 0;
406 for (int i = 0; i < descriptor_->field_count(); i++) {
407 totalBits +=
408 field_generators_.get(descriptor_->field(i)).GetNumBitsForMessage();
409 }
410 int totalInts = (totalBits + 31) / 32;
411 for (int i = 0; i < totalInts; i++) {
412 printer->Print("private int $bit_field_name$;\n", "bit_field_name",
413 GetBitFieldName(i));
414 }
415
416 // oneof
417 std::map<std::string, std::string> vars;
418 for (auto oneof : oneofs_) {
419 vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
420 vars["oneof_capitalized_name"] =
421 context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
422 vars["oneof_index"] = StrCat((oneof)->index());
423 // oneofCase_ and oneof_
424 printer->Print(vars,
425 "private int $oneof_name$Case_ = 0;\n"
426 "private java.lang.Object $oneof_name$_;\n");
427 // OneofCase enum
428 printer->Print(
429 vars,
430 "public enum $oneof_capitalized_name$Case\n"
431 // TODO(dweis): Remove EnumLite when we want to break compatibility with
432 // 3.x users
433 " implements com.google.protobuf.Internal.EnumLite,\n"
434 " com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n");
435 printer->Indent();
436 for (int j = 0; j < (oneof)->field_count(); j++) {
437 const FieldDescriptor* field = (oneof)->field(j);
438 printer->Print(
439 "$deprecation$$field_name$($field_number$),\n", "deprecation",
440 field->options().deprecated() ? "@java.lang.Deprecated " : "",
441 "field_name", ToUpper(field->name()), "field_number",
442 StrCat(field->number()));
443 }
444 printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name",
445 ToUpper(vars["oneof_name"]));
446 printer->Print(vars,
447 "private final int value;\n"
448 "private $oneof_capitalized_name$Case(int value) {\n"
449 " this.value = value;\n"
450 "}\n");
451 printer->Print(
452 vars,
453 "/**\n"
454 " * @param value The number of the enum to look for.\n"
455 " * @return The enum associated with the given number.\n"
456 " * @deprecated Use {@link #forNumber(int)} instead.\n"
457 " */\n"
458 "@java.lang.Deprecated\n"
459 "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
460 " return forNumber(value);\n"
461 "}\n"
462 "\n"
463 "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
464 " switch (value) {\n");
465 for (int j = 0; j < (oneof)->field_count(); j++) {
466 const FieldDescriptor* field = (oneof)->field(j);
467 printer->Print(" case $field_number$: return $field_name$;\n",
468 "field_number", StrCat(field->number()),
469 "field_name", ToUpper(field->name()));
470 }
471 printer->Print(
472 " case 0: return $cap_oneof_name$_NOT_SET;\n"
473 " default: return null;\n"
474 " }\n"
475 "}\n"
476 "public int getNumber() {\n"
477 " return this.value;\n"
478 "}\n",
479 "cap_oneof_name", ToUpper(vars["oneof_name"]));
480 printer->Outdent();
481 printer->Print("};\n\n");
482 // oneofCase()
483 printer->Print(vars,
484 "public $oneof_capitalized_name$Case\n"
485 "get$oneof_capitalized_name$Case() {\n"
486 " return $oneof_capitalized_name$Case.forNumber(\n"
487 " $oneof_name$Case_);\n"
488 "}\n"
489 "\n");
490 }
491
492 if (IsAnyMessage(descriptor_)) {
493 GenerateAnyMethods(printer);
494 }
495
496 // Fields
497 for (int i = 0; i < descriptor_->field_count(); i++) {
498 printer->Print("public static final int $constant_name$ = $number$;\n",
499 "constant_name", FieldConstantName(descriptor_->field(i)),
500 "number", StrCat(descriptor_->field(i)->number()));
501 printer->Annotate("constant_name", descriptor_->field(i));
502 field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
503 printer->Print("\n");
504 }
505
506 if (context_->HasGeneratedMethods(descriptor_)) {
507 GenerateIsInitialized(printer);
508 GenerateMessageSerializationMethods(printer);
509 GenerateEqualsAndHashCode(printer);
510 }
511
512
513 GenerateParseFromMethods(printer);
514 GenerateBuilder(printer);
515
516 printer->Print(
517 "\n"
518 "// @@protoc_insertion_point(class_scope:$full_name$)\n",
519 "full_name", descriptor_->full_name());
520
521 // Carefully initialize the default instance in such a way that it doesn't
522 // conflict with other initialization.
523 printer->Print("private static final $classname$ DEFAULT_INSTANCE;\n",
524 "classname",
525 name_resolver_->GetImmutableClassName(descriptor_));
526 printer->Print(
527 "static {\n"
528 " DEFAULT_INSTANCE = new $classname$();\n"
529 "}\n"
530 "\n",
531 "classname", name_resolver_->GetImmutableClassName(descriptor_));
532
533 printer->Print(
534 "public static $classname$ getDefaultInstance() {\n"
535 " return DEFAULT_INSTANCE;\n"
536 "}\n"
537 "\n",
538 "classname", name_resolver_->GetImmutableClassName(descriptor_));
539
540 // 'of' method for Wrappers
541 if (IsWrappersProtoFile(descriptor_->file())) {
542 printer->Print(
543 "public static $classname$ of($field_type$ value) {\n"
544 " return newBuilder().setValue(value).build();\n"
545 "}\n"
546 "\n",
547 "classname", name_resolver_->GetImmutableClassName(descriptor_),
548 "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0))));
549 }
550
551 GenerateParser(printer);
552
553 printer->Print(
554 "@java.lang.Override\n"
555 "public $classname$ getDefaultInstanceForType() {\n"
556 " return DEFAULT_INSTANCE;\n"
557 "}\n"
558 "\n",
559 "classname", name_resolver_->GetImmutableClassName(descriptor_));
560
561 // Extensions must be declared after the DEFAULT_INSTANCE is initialized
562 // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
563 // the outer class's FileDescriptor.
564 for (int i = 0; i < descriptor_->extension_count(); i++) {
565 ImmutableExtensionGenerator(descriptor_->extension(i), context_)
566 .Generate(printer);
567 }
568
569 printer->Outdent();
570 printer->Print("}\n\n");
571 }
572
573 // ===================================================================
574
GenerateMessageSerializationMethods(io::Printer * printer)575 void ImmutableMessageGenerator::GenerateMessageSerializationMethods(
576 io::Printer* printer) {
577 std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
578 SortFieldsByNumber(descriptor_));
579
580 std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
581 sorted_extensions.reserve(descriptor_->extension_range_count());
582 for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
583 sorted_extensions.push_back(descriptor_->extension_range(i));
584 }
585 std::sort(sorted_extensions.begin(), sorted_extensions.end(),
586 ExtensionRangeOrdering());
587 printer->Print(
588 "@java.lang.Override\n"
589 "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
590 " throws java.io.IOException {\n");
591 printer->Indent();
592
593 if (HasPackedFields(descriptor_)) {
594 // writeTo(CodedOutputStream output) might be invoked without
595 // getSerializedSize() ever being called, but we need the memoized
596 // sizes in case this message has packed fields. Rather than emit checks
597 // for each packed field, just call getSerializedSize() up front. In most
598 // cases, getSerializedSize() will have already been called anyway by one
599 // of the wrapper writeTo() methods, making this call cheap.
600 printer->Print("getSerializedSize();\n");
601 }
602
603 if (descriptor_->extension_range_count() > 0) {
604 if (descriptor_->options().message_set_wire_format()) {
605 printer->Print(
606 "com.google.protobuf.GeneratedMessage$ver$\n"
607 " .ExtendableMessage<$classname$>.ExtensionWriter\n"
608 " extensionWriter = newMessageSetExtensionWriter();\n",
609 "classname", name_resolver_->GetImmutableClassName(descriptor_),
610 "ver", GeneratedCodeVersionSuffix());
611 } else {
612 printer->Print(
613 "com.google.protobuf.GeneratedMessage$ver$\n"
614 " .ExtendableMessage<$classname$>.ExtensionWriter\n"
615 " extensionWriter = newExtensionWriter();\n",
616 "classname", name_resolver_->GetImmutableClassName(descriptor_),
617 "ver", GeneratedCodeVersionSuffix());
618 }
619 }
620
621 // Merge the fields and the extension ranges, both sorted by field number.
622 for (int i = 0, j = 0;
623 i < descriptor_->field_count() || j < sorted_extensions.size();) {
624 if (i == descriptor_->field_count()) {
625 GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
626 } else if (j == sorted_extensions.size()) {
627 GenerateSerializeOneField(printer, sorted_fields[i++]);
628 } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
629 GenerateSerializeOneField(printer, sorted_fields[i++]);
630 } else {
631 GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
632 }
633 }
634
635 if (descriptor_->options().message_set_wire_format()) {
636 printer->Print("getUnknownFields().writeAsMessageSetTo(output);\n");
637 } else {
638 printer->Print("getUnknownFields().writeTo(output);\n");
639 }
640
641 printer->Outdent();
642 printer->Print(
643 "}\n"
644 "\n"
645 "@java.lang.Override\n"
646 "public int getSerializedSize() {\n"
647 " int size = memoizedSize;\n"
648 " if (size != -1) return size;\n"
649 "\n");
650 printer->Indent();
651
652 printer->Print("size = 0;\n");
653
654 for (int i = 0; i < descriptor_->field_count(); i++) {
655 field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
656 }
657
658 if (descriptor_->extension_range_count() > 0) {
659 if (descriptor_->options().message_set_wire_format()) {
660 printer->Print("size += extensionsSerializedSizeAsMessageSet();\n");
661 } else {
662 printer->Print("size += extensionsSerializedSize();\n");
663 }
664 }
665
666 if (descriptor_->options().message_set_wire_format()) {
667 printer->Print(
668 "size += getUnknownFields().getSerializedSizeAsMessageSet();\n");
669 } else {
670 printer->Print("size += getUnknownFields().getSerializedSize();\n");
671 }
672
673 printer->Print(
674 "memoizedSize = size;\n"
675 "return size;\n");
676
677 printer->Outdent();
678 printer->Print(
679 "}\n"
680 "\n");
681 }
682
GenerateParseFromMethods(io::Printer * printer)683 void ImmutableMessageGenerator::GenerateParseFromMethods(io::Printer* printer) {
684 // Note: These are separate from GenerateMessageSerializationMethods()
685 // because they need to be generated even for messages that are optimized
686 // for code size.
687 printer->Print(
688 "public static $classname$ parseFrom(\n"
689 " java.nio.ByteBuffer data)\n"
690 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
691 " return PARSER.parseFrom(data);\n"
692 "}\n"
693 "public static $classname$ parseFrom(\n"
694 " java.nio.ByteBuffer data,\n"
695 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
696 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
697 " return PARSER.parseFrom(data, extensionRegistry);\n"
698 "}\n"
699 "public static $classname$ parseFrom(\n"
700 " com.google.protobuf.ByteString data)\n"
701 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
702 " return PARSER.parseFrom(data);\n"
703 "}\n"
704 "public static $classname$ parseFrom(\n"
705 " com.google.protobuf.ByteString data,\n"
706 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
707 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
708 " return PARSER.parseFrom(data, extensionRegistry);\n"
709 "}\n"
710 "public static $classname$ parseFrom(byte[] data)\n"
711 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
712 " return PARSER.parseFrom(data);\n"
713 "}\n"
714 "public static $classname$ parseFrom(\n"
715 " byte[] data,\n"
716 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
717 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
718 " return PARSER.parseFrom(data, extensionRegistry);\n"
719 "}\n"
720 "public static $classname$ parseFrom(java.io.InputStream input)\n"
721 " throws java.io.IOException {\n"
722 " return com.google.protobuf.GeneratedMessage$ver$\n"
723 " .parseWithIOException(PARSER, input);\n"
724 "}\n"
725 "public static $classname$ parseFrom(\n"
726 " java.io.InputStream input,\n"
727 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
728 " throws java.io.IOException {\n"
729 " return com.google.protobuf.GeneratedMessage$ver$\n"
730 " .parseWithIOException(PARSER, input, extensionRegistry);\n"
731 "}\n"
732 "public static $classname$ parseDelimitedFrom(java.io.InputStream "
733 "input)\n"
734 " throws java.io.IOException {\n"
735 " return com.google.protobuf.GeneratedMessage$ver$\n"
736 " .parseDelimitedWithIOException(PARSER, input);\n"
737 "}\n"
738 "public static $classname$ parseDelimitedFrom(\n"
739 " java.io.InputStream input,\n"
740 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
741 " throws java.io.IOException {\n"
742 " return com.google.protobuf.GeneratedMessage$ver$\n"
743 " .parseDelimitedWithIOException(PARSER, input, "
744 "extensionRegistry);\n"
745 "}\n"
746 "public static $classname$ parseFrom(\n"
747 " com.google.protobuf.CodedInputStream input)\n"
748 " throws java.io.IOException {\n"
749 " return com.google.protobuf.GeneratedMessage$ver$\n"
750 " .parseWithIOException(PARSER, input);\n"
751 "}\n"
752 "public static $classname$ parseFrom(\n"
753 " com.google.protobuf.CodedInputStream input,\n"
754 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
755 " throws java.io.IOException {\n"
756 " return com.google.protobuf.GeneratedMessage$ver$\n"
757 " .parseWithIOException(PARSER, input, extensionRegistry);\n"
758 "}\n"
759 "\n",
760 "classname", name_resolver_->GetImmutableClassName(descriptor_), "ver",
761 GeneratedCodeVersionSuffix());
762 }
763
GenerateSerializeOneField(io::Printer * printer,const FieldDescriptor * field)764 void ImmutableMessageGenerator::GenerateSerializeOneField(
765 io::Printer* printer, const FieldDescriptor* field) {
766 field_generators_.get(field).GenerateSerializationCode(printer);
767 }
768
GenerateSerializeOneExtensionRange(io::Printer * printer,const Descriptor::ExtensionRange * range)769 void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange(
770 io::Printer* printer, const Descriptor::ExtensionRange* range) {
771 printer->Print("extensionWriter.writeUntil($end$, output);\n", "end",
772 StrCat(range->end));
773 }
774
775 // ===================================================================
776
GenerateBuilder(io::Printer * printer)777 void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
778 // LITE_RUNTIME implements this at the GeneratedMessageLite level.
779 printer->Print(
780 "@java.lang.Override\n"
781 "public Builder newBuilderForType() { return newBuilder(); }\n");
782
783 printer->Print(
784 "public static Builder newBuilder() {\n"
785 " return DEFAULT_INSTANCE.toBuilder();\n"
786 "}\n"
787 "public static Builder newBuilder($classname$ prototype) {\n"
788 " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
789 "}\n"
790 "@java.lang.Override\n"
791 "public Builder toBuilder() {\n"
792 " return this == DEFAULT_INSTANCE\n"
793 " ? new Builder() : new Builder().mergeFrom(this);\n"
794 "}\n"
795 "\n",
796 "classname", name_resolver_->GetImmutableClassName(descriptor_));
797
798 printer->Print(
799 "@java.lang.Override\n"
800 "protected Builder newBuilderForType(\n"
801 " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
802 " Builder builder = new Builder(parent);\n"
803 " return builder;\n"
804 "}\n",
805 "ver", GeneratedCodeVersionSuffix());
806
807 MessageBuilderGenerator builderGenerator(descriptor_, context_);
808 builderGenerator.Generate(printer);
809 }
810
GenerateDescriptorMethods(io::Printer * printer)811 void ImmutableMessageGenerator::GenerateDescriptorMethods(
812 io::Printer* printer) {
813 if (!descriptor_->options().no_standard_descriptor_accessor()) {
814 printer->Print(
815 "public static final com.google.protobuf.Descriptors.Descriptor\n"
816 " getDescriptor() {\n"
817 " return $fileclass$.internal_$identifier$_descriptor;\n"
818 "}\n"
819 "\n",
820 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
821 "identifier", UniqueFileScopeIdentifier(descriptor_));
822 }
823 std::vector<const FieldDescriptor*> map_fields;
824 for (int i = 0; i < descriptor_->field_count(); i++) {
825 const FieldDescriptor* field = descriptor_->field(i);
826 if (GetJavaType(field) == JAVATYPE_MESSAGE &&
827 IsMapEntry(field->message_type())) {
828 map_fields.push_back(field);
829 }
830 }
831 if (!map_fields.empty()) {
832 printer->Print(
833 "@SuppressWarnings({\"rawtypes\"})\n"
834 "@java.lang.Override\n"
835 "protected com.google.protobuf.MapField internalGetMapField(\n"
836 " int number) {\n"
837 " switch (number) {\n");
838 printer->Indent();
839 printer->Indent();
840 for (int i = 0; i < map_fields.size(); ++i) {
841 const FieldDescriptor* field = map_fields[i];
842 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
843 printer->Print(
844 "case $number$:\n"
845 " return internalGet$capitalized_name$();\n",
846 "number", StrCat(field->number()), "capitalized_name",
847 info->capitalized_name);
848 }
849 printer->Print(
850 "default:\n"
851 " throw new RuntimeException(\n"
852 " \"Invalid map field number: \" + number);\n");
853 printer->Outdent();
854 printer->Outdent();
855 printer->Print(
856 " }\n"
857 "}\n");
858 }
859 printer->Print(
860 "@java.lang.Override\n"
861 "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
862 " internalGetFieldAccessorTable() {\n"
863 " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
864 " .ensureFieldAccessorsInitialized(\n"
865 " $classname$.class, $classname$.Builder.class);\n"
866 "}\n"
867 "\n",
868 "classname", name_resolver_->GetImmutableClassName(descriptor_),
869 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
870 "identifier", UniqueFileScopeIdentifier(descriptor_), "ver",
871 GeneratedCodeVersionSuffix());
872 }
873
874 // ===================================================================
875
GenerateIsInitialized(io::Printer * printer)876 void ImmutableMessageGenerator::GenerateIsInitialized(io::Printer* printer) {
877 // Memoizes whether the protocol buffer is fully initialized (has all
878 // required fields). -1 means not yet computed. 0 means false and 1 means
879 // true.
880 printer->Print("private byte memoizedIsInitialized = -1;\n");
881 printer->Print(
882 "@java.lang.Override\n"
883 "public final boolean isInitialized() {\n");
884 printer->Indent();
885
886 // Don't directly compare to -1 to avoid an Android x86 JIT bug.
887 printer->Print(
888 "byte isInitialized = memoizedIsInitialized;\n"
889 "if (isInitialized == 1) return true;\n"
890 "if (isInitialized == 0) return false;\n"
891 "\n");
892
893 // Check that all required fields in this message are set.
894 // TODO(kenton): We can optimize this when we switch to putting all the
895 // "has" fields into a single bitfield.
896 for (int i = 0; i < descriptor_->field_count(); i++) {
897 const FieldDescriptor* field = descriptor_->field(i);
898 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
899
900 if (field->is_required()) {
901 printer->Print(
902 "if (!has$name$()) {\n"
903 " memoizedIsInitialized = 0;\n"
904 " return false;\n"
905 "}\n",
906 "name", info->capitalized_name);
907 }
908 }
909
910 // Now check that all embedded messages are initialized.
911 for (int i = 0; i < descriptor_->field_count(); i++) {
912 const FieldDescriptor* field = descriptor_->field(i);
913 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
914 if (GetJavaType(field) == JAVATYPE_MESSAGE &&
915 HasRequiredFields(field->message_type())) {
916 switch (field->label()) {
917 case FieldDescriptor::LABEL_REQUIRED:
918 printer->Print(
919 "if (!get$name$().isInitialized()) {\n"
920 " memoizedIsInitialized = 0;\n"
921 " return false;\n"
922 "}\n",
923 "type",
924 name_resolver_->GetImmutableClassName(field->message_type()),
925 "name", info->capitalized_name);
926 break;
927 case FieldDescriptor::LABEL_OPTIONAL:
928 printer->Print(
929 "if (has$name$()) {\n"
930 " if (!get$name$().isInitialized()) {\n"
931 " memoizedIsInitialized = 0;\n"
932 " return false;\n"
933 " }\n"
934 "}\n",
935 "name", info->capitalized_name);
936 break;
937 case FieldDescriptor::LABEL_REPEATED:
938 if (IsMapEntry(field->message_type())) {
939 printer->Print(
940 "for ($type$ item : get$name$Map().values()) {\n"
941 " if (!item.isInitialized()) {\n"
942 " memoizedIsInitialized = 0;\n"
943 " return false;\n"
944 " }\n"
945 "}\n",
946 "type",
947 MapValueImmutableClassdName(field->message_type(),
948 name_resolver_),
949 "name", info->capitalized_name);
950 } else {
951 printer->Print(
952 "for (int i = 0; i < get$name$Count(); i++) {\n"
953 " if (!get$name$(i).isInitialized()) {\n"
954 " memoizedIsInitialized = 0;\n"
955 " return false;\n"
956 " }\n"
957 "}\n",
958 "type",
959 name_resolver_->GetImmutableClassName(field->message_type()),
960 "name", info->capitalized_name);
961 }
962 break;
963 }
964 }
965 }
966
967 if (descriptor_->extension_range_count() > 0) {
968 printer->Print(
969 "if (!extensionsAreInitialized()) {\n"
970 " memoizedIsInitialized = 0;\n"
971 " return false;\n"
972 "}\n");
973 }
974
975 printer->Outdent();
976
977 printer->Print(" memoizedIsInitialized = 1;\n");
978
979 printer->Print(
980 " return true;\n"
981 "}\n"
982 "\n");
983 }
984
985 // ===================================================================
986
987 namespace {
CheckHasBitsForEqualsAndHashCode(const FieldDescriptor * field)988 bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) {
989 if (field->is_repeated()) {
990 return false;
991 }
992 if (HasHasbit(field)) {
993 return true;
994 }
995 return GetJavaType(field) == JAVATYPE_MESSAGE && !IsRealOneof(field);
996 }
997 } // namespace
998
GenerateEqualsAndHashCode(io::Printer * printer)999 void ImmutableMessageGenerator::GenerateEqualsAndHashCode(
1000 io::Printer* printer) {
1001 printer->Print(
1002 "@java.lang.Override\n"
1003 "public boolean equals(");
1004 printer->Print("final java.lang.Object obj) {\n");
1005 printer->Indent();
1006 printer->Print(
1007 "if (obj == this) {\n"
1008 " return true;\n"
1009 "}\n"
1010 "if (!(obj instanceof $classname$)) {\n"
1011 " return super.equals(obj);\n"
1012 "}\n"
1013 "$classname$ other = ($classname$) obj;\n"
1014 "\n",
1015 "classname", name_resolver_->GetImmutableClassName(descriptor_));
1016
1017 for (int i = 0; i < descriptor_->field_count(); i++) {
1018 const FieldDescriptor* field = descriptor_->field(i);
1019 if (!IsRealOneof(field)) {
1020 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
1021 bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
1022 if (check_has_bits) {
1023 printer->Print(
1024 "if (has$name$() != other.has$name$()) return false;\n"
1025 "if (has$name$()) {\n",
1026 "name", info->capitalized_name);
1027 printer->Indent();
1028 }
1029 field_generators_.get(field).GenerateEqualsCode(printer);
1030 if (check_has_bits) {
1031 printer->Outdent();
1032 printer->Print("}\n");
1033 }
1034 }
1035 }
1036
1037 // Compare oneofs.
1038 for (auto oneof : oneofs_) {
1039 printer->Print(
1040 "if (!get$oneof_capitalized_name$Case().equals("
1041 "other.get$oneof_capitalized_name$Case())) return false;\n",
1042 "oneof_capitalized_name",
1043 context_->GetOneofGeneratorInfo(oneof)->capitalized_name);
1044 printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name",
1045 context_->GetOneofGeneratorInfo(oneof)->name);
1046 printer->Indent();
1047 for (int j = 0; j < (oneof)->field_count(); j++) {
1048 const FieldDescriptor* field = (oneof)->field(j);
1049 printer->Print("case $field_number$:\n", "field_number",
1050 StrCat(field->number()));
1051 printer->Indent();
1052 field_generators_.get(field).GenerateEqualsCode(printer);
1053 printer->Print("break;\n");
1054 printer->Outdent();
1055 }
1056 printer->Print(
1057 "case 0:\n"
1058 "default:\n");
1059 printer->Outdent();
1060 printer->Print("}\n");
1061 }
1062
1063 // Always consider unknown fields for equality. This will sometimes return
1064 // false for non-canonical ordering when running in LITE_RUNTIME but it's
1065 // the best we can do.
1066 printer->Print(
1067 "if (!getUnknownFields().equals(other.getUnknownFields())) return "
1068 "false;\n");
1069 if (descriptor_->extension_range_count() > 0) {
1070 printer->Print(
1071 "if (!getExtensionFields().equals(other.getExtensionFields()))\n"
1072 " return false;\n");
1073 }
1074 printer->Print("return true;\n");
1075 printer->Outdent();
1076 printer->Print(
1077 "}\n"
1078 "\n");
1079
1080 printer->Print(
1081 "@java.lang.Override\n"
1082 "public int hashCode() {\n");
1083 printer->Indent();
1084 printer->Print("if (memoizedHashCode != 0) {\n");
1085 printer->Indent();
1086 printer->Print("return memoizedHashCode;\n");
1087 printer->Outdent();
1088 printer->Print(
1089 "}\n"
1090 "int hash = 41;\n");
1091
1092 // If we output a getDescriptor() method, use that as it is more efficient.
1093 if (descriptor_->options().no_standard_descriptor_accessor()) {
1094 printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
1095 } else {
1096 printer->Print("hash = (19 * hash) + getDescriptor().hashCode();\n");
1097 }
1098
1099 // hashCode non-oneofs.
1100 for (int i = 0; i < descriptor_->field_count(); i++) {
1101 const FieldDescriptor* field = descriptor_->field(i);
1102 if (!IsRealOneof(field)) {
1103 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
1104 bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
1105 if (check_has_bits) {
1106 printer->Print("if (has$name$()) {\n", "name", info->capitalized_name);
1107 printer->Indent();
1108 }
1109 field_generators_.get(field).GenerateHashCode(printer);
1110 if (check_has_bits) {
1111 printer->Outdent();
1112 printer->Print("}\n");
1113 }
1114 }
1115 }
1116
1117 // hashCode oneofs.
1118 for (auto oneof : oneofs_) {
1119 printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name",
1120 context_->GetOneofGeneratorInfo(oneof)->name);
1121 printer->Indent();
1122 for (int j = 0; j < (oneof)->field_count(); j++) {
1123 const FieldDescriptor* field = (oneof)->field(j);
1124 printer->Print("case $field_number$:\n", "field_number",
1125 StrCat(field->number()));
1126 printer->Indent();
1127 field_generators_.get(field).GenerateHashCode(printer);
1128 printer->Print("break;\n");
1129 printer->Outdent();
1130 }
1131 printer->Print(
1132 "case 0:\n"
1133 "default:\n");
1134 printer->Outdent();
1135 printer->Print("}\n");
1136 }
1137
1138 if (descriptor_->extension_range_count() > 0) {
1139 printer->Print("hash = hashFields(hash, getExtensionFields());\n");
1140 }
1141
1142 printer->Print("hash = (29 * hash) + getUnknownFields().hashCode();\n");
1143 printer->Print(
1144 "memoizedHashCode = hash;\n"
1145 "return hash;\n");
1146 printer->Outdent();
1147 printer->Print(
1148 "}\n"
1149 "\n");
1150 }
1151
1152 // ===================================================================
1153
GenerateExtensionRegistrationCode(io::Printer * printer)1154 void ImmutableMessageGenerator::GenerateExtensionRegistrationCode(
1155 io::Printer* printer) {
1156 for (int i = 0; i < descriptor_->extension_count(); i++) {
1157 ImmutableExtensionGenerator(descriptor_->extension(i), context_)
1158 .GenerateRegistrationCode(printer);
1159 }
1160
1161 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1162 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
1163 .GenerateExtensionRegistrationCode(printer);
1164 }
1165 }
1166
1167 // ===================================================================
GenerateParser(io::Printer * printer)1168 void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
1169 printer->Print(
1170 "$visibility$ static final com.google.protobuf.Parser<$classname$>\n"
1171 " PARSER = new com.google.protobuf.AbstractParser<$classname$>() {\n"
1172 " @java.lang.Override\n"
1173 " public $classname$ parsePartialFrom(\n"
1174 " com.google.protobuf.CodedInputStream input,\n"
1175 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
1176 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
1177 " Builder builder = newBuilder();\n"
1178 " try {\n"
1179 " builder.mergeFrom(input, extensionRegistry);\n"
1180 " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
1181 " throw e.setUnfinishedMessage(builder.buildPartial());\n"
1182 " } catch (com.google.protobuf.UninitializedMessageException e) {\n"
1183 " throw "
1184 "e.asInvalidProtocolBufferException().setUnfinishedMessage(builder."
1185 "buildPartial());\n"
1186 " } catch (java.io.IOException e) {\n"
1187 " throw new com.google.protobuf.InvalidProtocolBufferException(e)\n"
1188 " .setUnfinishedMessage(builder.buildPartial());\n"
1189 " }\n"
1190 " return builder.buildPartial();\n"
1191 " }\n"
1192 "};\n"
1193 "\n"
1194 "public static com.google.protobuf.Parser<$classname$> parser() {\n"
1195 " return PARSER;\n"
1196 "}\n"
1197 "\n"
1198 "@java.lang.Override\n"
1199 "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
1200 " return PARSER;\n"
1201 "}\n"
1202 "\n",
1203 "visibility",
1204 ExposePublicParser(descriptor_->file()) ? "@java.lang.Deprecated public"
1205 : "private",
1206 "classname", descriptor_->name());
1207 }
1208
1209 // ===================================================================
GenerateInitializers(io::Printer * printer)1210 void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) {
1211 for (int i = 0; i < descriptor_->field_count(); i++) {
1212 if (!IsRealOneof(descriptor_->field(i))) {
1213 field_generators_.get(descriptor_->field(i))
1214 .GenerateInitializationCode(printer);
1215 }
1216 }
1217 }
1218
1219 // ===================================================================
GenerateMutableCopy(io::Printer * printer)1220 void ImmutableMessageGenerator::GenerateMutableCopy(io::Printer* printer) {
1221 printer->Print(
1222 "protected com.google.protobuf.MutableMessage\n"
1223 " internalMutableDefault() {\n"
1224 " return MutableDefaultLoader.get();\n"
1225 "}\n"
1226 "\n"
1227 "private static final class MutableDefaultLoader {\n"
1228 " private static final java.lang.Object defaultOrRuntimeException;\n"
1229 " static {\n"
1230 " java.lang.Object local;\n"
1231 " try {\n"
1232 " local = internalMutableDefault(\"$mutable_name$\");\n"
1233 " } catch (java.lang.RuntimeException e) {\n"
1234 " local = e;\n"
1235 " }\n"
1236 " defaultOrRuntimeException = local;\n"
1237 " }\n"
1238 "\n"
1239 " private MutableDefaultLoader() {}\n"
1240 "\n"
1241 " public static com.google.protobuf.MutableMessage get() {\n"
1242 " if (defaultOrRuntimeException\n"
1243 " instanceof java.lang.RuntimeException) {\n"
1244 " throw (java.lang.RuntimeException) defaultOrRuntimeException;\n"
1245 " }\n"
1246 " return\n"
1247 " (com.google.protobuf.MutableMessage) "
1248 "defaultOrRuntimeException;\n"
1249 " }\n"
1250 "}\n",
1251 "mutable_name", name_resolver_->GetJavaMutableClassName(descriptor_));
1252 }
1253
GenerateKotlinDsl(io::Printer * printer) const1254 void ImmutableMessageGenerator::GenerateKotlinDsl(io::Printer* printer) const {
1255 printer->Print(
1256 "@kotlin.OptIn"
1257 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
1258 "@com.google.protobuf.kotlin.ProtoDslMarker\n");
1259 printer->Print(
1260 "public class Dsl private constructor(\n"
1261 " private val _builder: $message$.Builder\n"
1262 ") {\n"
1263 " public companion object {\n"
1264 " @kotlin.jvm.JvmSynthetic\n"
1265 " @kotlin.PublishedApi\n"
1266 " internal fun _create(builder: $message$.Builder): Dsl = "
1267 "Dsl(builder)\n"
1268 " }\n"
1269 "\n"
1270 " @kotlin.jvm.JvmSynthetic\n"
1271 " @kotlin.PublishedApi\n"
1272 " internal fun _build(): $message$ = _builder.build()\n",
1273 "message", name_resolver_->GetClassName(descriptor_, true));
1274
1275 printer->Indent();
1276
1277 for (int i = 0; i < descriptor_->field_count(); i++) {
1278 printer->Print("\n");
1279 field_generators_.get(descriptor_->field(i))
1280 .GenerateKotlinDslMembers(printer);
1281 }
1282
1283 for (auto oneof : oneofs_) {
1284 printer->Print(
1285 "public val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n"
1286 " @JvmName(\"get$oneof_capitalized_name$Case\")\n"
1287 " get() = _builder.get$oneof_capitalized_name$Case()\n\n"
1288 "public fun clear$oneof_capitalized_name$() {\n"
1289 " _builder.clear$oneof_capitalized_name$()\n"
1290 "}\n",
1291 "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name,
1292 "oneof_capitalized_name",
1293 context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message",
1294 name_resolver_->GetClassName(descriptor_, true));
1295 }
1296
1297 if (descriptor_->extension_range_count() > 0) {
1298 GenerateKotlinExtensions(printer);
1299 }
1300
1301 printer->Outdent();
1302 printer->Print("}\n");
1303 }
1304
GenerateKotlinMembers(io::Printer * printer) const1305 void ImmutableMessageGenerator::GenerateKotlinMembers(
1306 io::Printer* printer) const {
1307 printer->Print(
1308 "@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n"
1309 "public inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> "
1310 "kotlin.Unit): "
1311 "$message$ "
1312 "=\n"
1313 " $message_kt$.Dsl._create($message$.newBuilder()).apply { block() "
1314 "}._build()\n",
1315 "camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_),
1316 "message_kt", name_resolver_->GetKotlinExtensionsClassName(descriptor_),
1317 "message", name_resolver_->GetClassName(descriptor_, true));
1318
1319 printer->Print("public object $name$Kt {\n", "name", descriptor_->name());
1320 printer->Indent();
1321 GenerateKotlinDsl(printer);
1322 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1323 if (IsMapEntry(descriptor_->nested_type(i))) continue;
1324 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
1325 .GenerateKotlinMembers(printer);
1326 }
1327 printer->Outdent();
1328 printer->Print("}\n");
1329 }
1330
GenerateTopLevelKotlinMembers(io::Printer * printer) const1331 void ImmutableMessageGenerator::GenerateTopLevelKotlinMembers(
1332 io::Printer* printer) const {
1333 printer->Print(
1334 "@kotlin.jvm.JvmSynthetic\n"
1335 "public inline fun $message$.copy(block: $message_kt$.Dsl.() -> "
1336 "kotlin.Unit): "
1337 "$message$ =\n"
1338 " $message_kt$.Dsl._create(this.toBuilder()).apply { block() "
1339 "}._build()\n\n",
1340 "message", name_resolver_->GetClassName(descriptor_, true), "message_kt",
1341 name_resolver_->GetKotlinExtensionsClassName(descriptor_));
1342
1343 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1344 if (IsMapEntry(descriptor_->nested_type(i))) continue;
1345 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
1346 .GenerateTopLevelKotlinMembers(printer);
1347 }
1348
1349 GenerateKotlinOrNull(printer);
1350 }
1351
GenerateKotlinOrNull(io::Printer * printer) const1352 void ImmutableMessageGenerator::GenerateKotlinOrNull(io::Printer* printer) const {
1353 for (int i = 0; i < descriptor_->field_count(); i++) {
1354 const FieldDescriptor* field = descriptor_->field(i);
1355 if (field->has_presence() && GetJavaType(field) == JAVATYPE_MESSAGE) {
1356 printer->Print(
1357 "val $full_classname$OrBuilder.$camelcase_name$OrNull: $full_name$?\n"
1358 " get() = if (has$name$()) get$name$() else null\n\n",
1359 "full_classname", name_resolver_->GetClassName(descriptor_, true),
1360 "camelcase_name", context_->GetFieldGeneratorInfo(field)->name,
1361 "full_name",
1362 name_resolver_->GetImmutableClassName(field->message_type()), "name",
1363 context_->GetFieldGeneratorInfo(field)->capitalized_name);
1364 }
1365 }
1366 }
1367
GenerateKotlinExtensions(io::Printer * printer) const1368 void ImmutableMessageGenerator::GenerateKotlinExtensions(
1369 io::Printer* printer) const {
1370 std::string message_name = name_resolver_->GetClassName(descriptor_, true);
1371
1372 printer->Print(
1373 "@Suppress(\"UNCHECKED_CAST\")\n"
1374 "@kotlin.jvm.JvmSynthetic\n"
1375 "public operator fun <T : kotlin.Any> get(extension: "
1376 "com.google.protobuf.ExtensionLite<$message$, T>): T {\n"
1377 " return if (extension.isRepeated) {\n"
1378 " get(extension as com.google.protobuf.ExtensionLite<$message$, "
1379 "List<*>>) as T\n"
1380 " } else {\n"
1381 " _builder.getExtension(extension)\n"
1382 " }\n"
1383 "}\n\n",
1384 "message", message_name);
1385
1386 printer->Print(
1387 "@kotlin.jvm.JvmSynthetic\n"
1388 "@kotlin.OptIn"
1389 "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
1390 "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n"
1391 "public operator fun <E : kotlin.Any> get(\n"
1392 " extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n"
1393 "): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n"
1394 " return com.google.protobuf.kotlin.ExtensionList(extension, "
1395 "_builder.getExtension(extension))\n"
1396 "}\n\n",
1397 "message", message_name);
1398
1399 printer->Print(
1400 "@kotlin.jvm.JvmSynthetic\n"
1401 "public operator fun contains(extension: "
1402 "com.google.protobuf.ExtensionLite<$message$, *>): "
1403 "Boolean {\n"
1404 " return _builder.hasExtension(extension)\n"
1405 "}\n\n",
1406 "message", message_name);
1407
1408 printer->Print(
1409 "@kotlin.jvm.JvmSynthetic\n"
1410 "public fun clear(extension: "
1411 "com.google.protobuf.ExtensionLite<$message$, *>) "
1412 "{\n"
1413 " _builder.clearExtension(extension)\n"
1414 "}\n\n",
1415 "message", message_name);
1416
1417 printer->Print(
1418 "@kotlin.jvm.JvmSynthetic\n"
1419 "@kotlin.PublishedApi\n"
1420 "internal fun <T : kotlin.Any> setExtension(extension: "
1421 "com.google.protobuf.ExtensionLite<$message$, T>, "
1422 "value: T) {\n"
1423 " _builder.setExtension(extension, value)\n"
1424 "}\n\n",
1425 "message", message_name);
1426
1427 printer->Print(
1428 "@kotlin.jvm.JvmSynthetic\n"
1429 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1430 "public inline operator fun <T : Comparable<T>> set(\n"
1431 " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
1432 " value: T\n"
1433 ") {\n"
1434 " setExtension(extension, value)\n"
1435 "}\n\n",
1436 "message", message_name);
1437
1438 printer->Print(
1439 "@kotlin.jvm.JvmSynthetic\n"
1440 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1441 "public inline operator fun set(\n"
1442 " extension: com.google.protobuf.ExtensionLite<$message$, "
1443 "com.google.protobuf.ByteString>,\n"
1444 " value: com.google.protobuf.ByteString\n"
1445 ") {\n"
1446 " setExtension(extension, value)\n"
1447 "}\n\n",
1448 "message", message_name);
1449
1450 printer->Print(
1451 "@kotlin.jvm.JvmSynthetic\n"
1452 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1453 "public inline operator fun <T : com.google.protobuf.MessageLite> set(\n"
1454 " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
1455 " value: T\n"
1456 ") {\n"
1457 " setExtension(extension, value)\n"
1458 "}\n\n",
1459 "message", message_name);
1460
1461 printer->Print(
1462 "@kotlin.jvm.JvmSynthetic\n"
1463 "public fun <E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, "
1464 "$message$>.add(value: E) {\n"
1465 " _builder.addExtension(this.extension, value)\n"
1466 "}\n\n",
1467 "message", message_name);
1468
1469 printer->Print(
1470 "@kotlin.jvm.JvmSynthetic\n"
1471 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1472 "public inline operator fun <E : kotlin.Any> "
1473 "com.google.protobuf.kotlin.ExtensionList<E, "
1474 "$message$>.plusAssign"
1475 "(value: E) {\n"
1476 " add(value)\n"
1477 "}\n\n",
1478 "message", message_name);
1479
1480 printer->Print(
1481 "@kotlin.jvm.JvmSynthetic\n"
1482 "public fun <E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, "
1483 "$message$>.addAll(values: Iterable<E>) {\n"
1484 " for (value in values) {\n"
1485 " add(value)\n"
1486 " }\n"
1487 "}\n\n",
1488 "message", message_name);
1489
1490 printer->Print(
1491 "@kotlin.jvm.JvmSynthetic\n"
1492 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1493 "public inline operator fun <E : kotlin.Any> "
1494 "com.google.protobuf.kotlin.ExtensionList<E, "
1495 "$message$>.plusAssign(values: "
1496 "Iterable<E>) {\n"
1497 " addAll(values)\n"
1498 "}\n\n",
1499 "message", message_name);
1500
1501 printer->Print(
1502 "@kotlin.jvm.JvmSynthetic\n"
1503 "public operator fun <E : kotlin.Any> "
1504 "com.google.protobuf.kotlin.ExtensionList<E, "
1505 "$message$>.set(index: Int, value: "
1506 "E) {\n"
1507 " _builder.setExtension(this.extension, index, value)\n"
1508 "}\n\n",
1509 "message", message_name);
1510
1511 printer->Print(
1512 "@kotlin.jvm.JvmSynthetic\n"
1513 "@Suppress(\"NOTHING_TO_INLINE\")\n"
1514 "public inline fun com.google.protobuf.kotlin.ExtensionList<*, "
1515 "$message$>.clear() {\n"
1516 " clear(extension)\n"
1517 "}\n\n",
1518 "message", message_name);
1519 }
1520
GenerateAnyMethods(io::Printer * printer)1521 void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
1522 printer->Print(
1523 "private static String getTypeUrl(\n"
1524 " java.lang.String typeUrlPrefix,\n"
1525 " com.google.protobuf.Descriptors.Descriptor descriptor) {\n"
1526 " return typeUrlPrefix.endsWith(\"/\")\n"
1527 " ? typeUrlPrefix + descriptor.getFullName()\n"
1528 " : typeUrlPrefix + \"/\" + descriptor.getFullName();\n"
1529 "}\n"
1530 "\n"
1531 "private static String getTypeNameFromTypeUrl(\n"
1532 " java.lang.String typeUrl) {\n"
1533 " int pos = typeUrl.lastIndexOf('/');\n"
1534 " return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n"
1535 "}\n"
1536 "\n"
1537 "public static <T extends com.google.protobuf.Message> Any pack(\n"
1538 " T message) {\n"
1539 " return Any.newBuilder()\n"
1540 " .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n"
1541 " message.getDescriptorForType()))\n"
1542 " .setValue(message.toByteString())\n"
1543 " .build();\n"
1544 "}\n"
1545 "\n"
1546 "/**\n"
1547 " * Packs a message using the given type URL prefix. The type URL will\n"
1548 " * be constructed by concatenating the message type's full name to the\n"
1549 " * prefix with an optional \"/\" separator if the prefix doesn't end\n"
1550 " * with \"/\" already.\n"
1551 " */\n"
1552 "public static <T extends com.google.protobuf.Message> Any pack(\n"
1553 " T message, java.lang.String typeUrlPrefix) {\n"
1554 " return Any.newBuilder()\n"
1555 " .setTypeUrl(getTypeUrl(typeUrlPrefix,\n"
1556 " message.getDescriptorForType()))\n"
1557 " .setValue(message.toByteString())\n"
1558 " .build();\n"
1559 "}\n"
1560 "\n"
1561 "public <T extends com.google.protobuf.Message> boolean is(\n"
1562 " java.lang.Class<T> clazz) {\n"
1563 " T defaultInstance =\n"
1564 " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
1565 " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n"
1566 " defaultInstance.getDescriptorForType().getFullName());\n"
1567 "}\n"
1568 "\n"
1569 "private volatile com.google.protobuf.Message cachedUnpackValue;\n"
1570 "\n"
1571 "@java.lang.SuppressWarnings(\"unchecked\")\n"
1572 "public <T extends com.google.protobuf.Message> T unpack(\n"
1573 " java.lang.Class<T> clazz)\n"
1574 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
1575 " boolean invalidClazz = false;\n"
1576 " if (cachedUnpackValue != null) {\n"
1577 " if (cachedUnpackValue.getClass() == clazz) {\n"
1578 " return (T) cachedUnpackValue;\n"
1579 " }\n"
1580 " invalidClazz = true;\n"
1581 " }\n"
1582 " if (invalidClazz || !is(clazz)) {\n"
1583 " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
1584 " \"Type of the Any message does not match the given class.\");\n"
1585 " }\n"
1586 " T defaultInstance =\n"
1587 " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
1588 " T result = (T) defaultInstance.getParserForType()\n"
1589 " .parseFrom(getValue());\n"
1590 " cachedUnpackValue = result;\n"
1591 " return result;\n"
1592 "}\n");
1593 }
1594
1595 } // namespace java
1596 } // namespace compiler
1597 } // namespace protobuf
1598 } // namespace google
1599