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