blob: e982a17bb942046e55e91daf5840d9f80482a16c [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000035#include <google/protobuf/compiler/java/java_message.h>
36
temporal40ee5512008-07-10 02:12:20 +000037#include <algorithm>
38#include <google/protobuf/stubs/hash.h>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000039#include <map>
jieluo@google.com4de8f552014-07-18 00:47:59 +000040#include <memory>
Feng Xiao6ef984a2014-11-10 17:34:54 -080041#ifndef _SHARED_PTR_H
42#include <google/protobuf/stubs/shared_ptr.h>
43#endif
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000044#include <vector>
45
jieluo@google.com4de8f552014-07-18 00:47:59 +000046#include <google/protobuf/compiler/java/java_context.h>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000047#include <google/protobuf/compiler/java/java_doc_comment.h>
temporal40ee5512008-07-10 02:12:20 +000048#include <google/protobuf/compiler/java/java_enum.h>
49#include <google/protobuf/compiler/java/java_extension.h>
jieluo@google.com4de8f552014-07-18 00:47:59 +000050#include <google/protobuf/compiler/java/java_generator_factory.h>
temporal40ee5512008-07-10 02:12:20 +000051#include <google/protobuf/compiler/java/java_helpers.h>
jieluo@google.com4de8f552014-07-18 00:47:59 +000052#include <google/protobuf/compiler/java/java_name_resolver.h>
temporal40ee5512008-07-10 02:12:20 +000053#include <google/protobuf/io/coded_stream.h>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000054#include <google/protobuf/io/printer.h>
temporal40ee5512008-07-10 02:12:20 +000055#include <google/protobuf/descriptor.pb.h>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000056#include <google/protobuf/wire_format.h>
57#include <google/protobuf/stubs/strutil.h>
58#include <google/protobuf/stubs/substitute.h>
temporal40ee5512008-07-10 02:12:20 +000059
60namespace google {
61namespace protobuf {
62namespace compiler {
63namespace java {
64
65using internal::WireFormat;
kenton@google.com80b1d622009-07-29 01:13:20 +000066using internal::WireFormatLite;
temporal40ee5512008-07-10 02:12:20 +000067
68namespace {
jieluo@google.com4de8f552014-07-18 00:47:59 +000069bool GenerateHasBits(const Descriptor* descriptor) {
70 return SupportFieldPresence(descriptor->file()) ||
71 HasRepeatedFields(descriptor);
temporal40ee5512008-07-10 02:12:20 +000072}
Feng Xiaof157a562014-11-14 11:50:31 -080073
74string MapValueImmutableClassdName(const Descriptor* descriptor,
75 ClassNameResolver* name_resolver) {
76 const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
77 GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
78 return name_resolver->GetImmutableClassName(value_field->message_type());
79}
temporal40ee5512008-07-10 02:12:20 +000080} // namespace
81
82// ===================================================================
83
84MessageGenerator::MessageGenerator(const Descriptor* descriptor)
jieluo@google.com4de8f552014-07-18 00:47:59 +000085 : descriptor_(descriptor) {}
temporal40ee5512008-07-10 02:12:20 +000086
87MessageGenerator::~MessageGenerator() {}
88
jieluo@google.com4de8f552014-07-18 00:47:59 +000089// ===================================================================
90// TODO(api): Move this class to a separate immutable_message.cc file.
91ImmutableMessageGenerator::ImmutableMessageGenerator(
92 const Descriptor* descriptor, Context* context)
93 : MessageGenerator(descriptor), context_(context),
94 name_resolver_(context->GetNameResolver()),
95 field_generators_(descriptor, context_) {
96}
97
98ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
99
100void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000101 if (HasDescriptorMethods(descriptor_)) {
102 // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
103 // used in the construction of descriptors, we have a tricky bootstrapping
104 // problem. To help control static initialization order, we make sure all
105 // descriptors and other static data that depends on them are members of
106 // the outermost class in the file. This way, they will be initialized in
107 // a deterministic order.
temporal40ee5512008-07-10 02:12:20 +0000108
kenton@google.com80b1d622009-07-29 01:13:20 +0000109 map<string, string> vars;
110 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
111 vars["index"] = SimpleItoa(descriptor_->index());
jieluo@google.com4de8f552014-07-18 00:47:59 +0000112 vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
kenton@google.com80b1d622009-07-29 01:13:20 +0000113 if (descriptor_->containing_type() != NULL) {
114 vars["parent"] = UniqueFileScopeIdentifier(
115 descriptor_->containing_type());
116 }
jieluo@google.com4de8f552014-07-18 00:47:59 +0000117 if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000118 // We can only make these package-private since the classes that use them
119 // are in separate files.
120 vars["private"] = "";
121 } else {
122 vars["private"] = "private ";
123 }
124
125 // The descriptor for this type.
126 printer->Print(vars,
jieluo@google.com4de8f552014-07-18 00:47:59 +0000127 "$private$static final com.google.protobuf.Descriptors.Descriptor\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000128 " internal_$identifier$_descriptor;\n");
129
130 // And the FieldAccessorTable.
jieluo@google.com4de8f552014-07-18 00:47:59 +0000131 GenerateFieldAccessorTable(printer);
temporal40ee5512008-07-10 02:12:20 +0000132 }
kenton@google.com24bf56f2008-09-24 20:31:01 +0000133
134 // Generate static members for all nested types.
135 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
136 // TODO(kenton): Reuse MessageGenerator objects?
jieluo@google.com4de8f552014-07-18 00:47:59 +0000137 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
kenton@google.com24bf56f2008-09-24 20:31:01 +0000138 .GenerateStaticVariables(printer);
139 }
140}
141
jieluo@google.com4de8f552014-07-18 00:47:59 +0000142void ImmutableMessageGenerator::GenerateStaticVariableInitializers(
kenton@google.com24bf56f2008-09-24 20:31:01 +0000143 io::Printer* printer) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000144 if (HasDescriptorMethods(descriptor_)) {
145 map<string, string> vars;
146 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
147 vars["index"] = SimpleItoa(descriptor_->index());
jieluo@google.com4de8f552014-07-18 00:47:59 +0000148 vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
kenton@google.com80b1d622009-07-29 01:13:20 +0000149 if (descriptor_->containing_type() != NULL) {
150 vars["parent"] = UniqueFileScopeIdentifier(
151 descriptor_->containing_type());
152 }
kenton@google.com24bf56f2008-09-24 20:31:01 +0000153
kenton@google.com80b1d622009-07-29 01:13:20 +0000154 // The descriptor for this type.
155 if (descriptor_->containing_type() == NULL) {
156 printer->Print(vars,
157 "internal_$identifier$_descriptor =\n"
158 " getDescriptor().getMessageTypes().get($index$);\n");
159 } else {
160 printer->Print(vars,
161 "internal_$identifier$_descriptor =\n"
162 " internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
163 }
kenton@google.com24bf56f2008-09-24 20:31:01 +0000164
kenton@google.com80b1d622009-07-29 01:13:20 +0000165 // And the FieldAccessorTable.
jieluo@google.com4de8f552014-07-18 00:47:59 +0000166 GenerateFieldAccessorTableInitializer(printer);
temporal40ee5512008-07-10 02:12:20 +0000167 }
temporal40ee5512008-07-10 02:12:20 +0000168
kenton@google.com24bf56f2008-09-24 20:31:01 +0000169 // Generate static member initializers for all nested types.
temporal40ee5512008-07-10 02:12:20 +0000170 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
171 // TODO(kenton): Reuse MessageGenerator objects?
jieluo@google.com4de8f552014-07-18 00:47:59 +0000172 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
kenton@google.com24bf56f2008-09-24 20:31:01 +0000173 .GenerateStaticVariableInitializers(printer);
174 }
temporal40ee5512008-07-10 02:12:20 +0000175}
176
jieluo@google.com4de8f552014-07-18 00:47:59 +0000177void ImmutableMessageGenerator::
178GenerateFieldAccessorTable(io::Printer* printer) {
179 map<string, string> vars;
180 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
181 if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
182 // We can only make these package-private since the classes that use them
183 // are in separate files.
184 vars["private"] = "";
185 } else {
186 vars["private"] = "private ";
187 }
188 printer->Print(vars,
189 "$private$static\n"
190 " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
191 " internal_$identifier$_fieldAccessorTable;\n");
192}
193
194void ImmutableMessageGenerator::
195GenerateFieldAccessorTableInitializer(io::Printer* printer) {
196 printer->Print(
197 "internal_$identifier$_fieldAccessorTable = new\n"
198 " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
199 " internal_$identifier$_descriptor,\n"
200 " new java.lang.String[] { ",
201 "identifier",
202 UniqueFileScopeIdentifier(descriptor_));
203 for (int i = 0; i < descriptor_->field_count(); i++) {
204 const FieldDescriptor* field = descriptor_->field(i);
205 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
206 printer->Print(
207 "\"$field_name$\", ",
208 "field_name", info->capitalized_name);
209 }
210 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
211 const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
212 const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof);
213 printer->Print(
214 "\"$oneof_name$\", ",
215 "oneof_name", info->capitalized_name);
216 }
217 printer->Print("});\n");
218}
219
liujisi@google.com33165fe2010-11-02 13:14:58 +0000220// ===================================================================
221
jieluo@google.com4de8f552014-07-18 00:47:59 +0000222void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000223 if (descriptor_->extension_range_count() > 0) {
224 if (HasDescriptorMethods(descriptor_)) {
225 printer->Print(
226 "public interface $classname$OrBuilder extends\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000227 " $extra_interfaces$\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000228 " com.google.protobuf.GeneratedMessage.\n"
229 " ExtendableMessageOrBuilder<$classname$> {\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +0000230 "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
liujisi@google.com33165fe2010-11-02 13:14:58 +0000231 "classname", descriptor_->name());
232 } else {
233 printer->Print(
234 "public interface $classname$OrBuilder extends \n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000235 " $extra_interfaces$\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000236 " com.google.protobuf.GeneratedMessageLite.\n"
Jisi Liu885b6122015-02-28 14:51:22 -0800237 " ExtendableMessageOrBuilder<\n"
238 " $classname$, $classname$.Builder> {\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +0000239 "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
liujisi@google.com33165fe2010-11-02 13:14:58 +0000240 "classname", descriptor_->name());
241 }
242 } else {
243 if (HasDescriptorMethods(descriptor_)) {
244 printer->Print(
jieluo@google.com4de8f552014-07-18 00:47:59 +0000245 "public interface $classname$OrBuilder extends\n"
246 " $extra_interfaces$\n"
247 " com.google.protobuf.MessageOrBuilder {\n",
248 "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
liujisi@google.com33165fe2010-11-02 13:14:58 +0000249 "classname", descriptor_->name());
250 } else {
251 printer->Print(
jieluo@google.com4de8f552014-07-18 00:47:59 +0000252 "public interface $classname$OrBuilder extends\n"
253 " $extra_interfaces$\n"
254 " com.google.protobuf.MessageLiteOrBuilder {\n",
255 "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
liujisi@google.com33165fe2010-11-02 13:14:58 +0000256 "classname", descriptor_->name());
257 }
258 }
259
260 printer->Indent();
261 for (int i = 0; i < descriptor_->field_count(); i++) {
262 printer->Print("\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000263 field_generators_.get(descriptor_->field(i))
264 .GenerateInterfaceMembers(printer);
265 }
266 printer->Outdent();
267
268 printer->Print("}\n");
269}
270
271// ===================================================================
272
jieluo@google.com4de8f552014-07-18 00:47:59 +0000273void ImmutableMessageGenerator::Generate(io::Printer* printer) {
temporal40ee5512008-07-10 02:12:20 +0000274 bool is_own_file =
275 descriptor_->containing_type() == NULL &&
jieluo@google.com4de8f552014-07-18 00:47:59 +0000276 MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
temporal40ee5512008-07-10 02:12:20 +0000277
Feng Xiao6ef984a2014-11-10 17:34:54 -0800278 map<string, string> variables;
279 variables["static"] = is_own_file ? " " : " static ";
280 variables["classname"] = descriptor_->name();
281 variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
282 variables["lite"] = HasDescriptorMethods(descriptor_) ? "" : "Lite";
283
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000284 WriteMessageDocComment(printer, descriptor_);
285
286 // The builder_type stores the super type name of the nested Builder class.
287 string builder_type;
temporal40ee5512008-07-10 02:12:20 +0000288 if (descriptor_->extension_range_count() > 0) {
Jisi Liu885b6122015-02-28 14:51:22 -0800289 if (HasDescriptorMethods(descriptor_)) {
290 printer->Print(variables,
291 "public $static$final class $classname$ extends\n"
292 " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
293 " $classname$> implements\n"
294 " $extra_interfaces$\n"
295 " $classname$OrBuilder {\n");
296 } else {
297 printer->Print(variables,
298 "public $static$final class $classname$ extends\n"
299 " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
300 " $classname$, $classname$.Builder> implements\n"
301 " $extra_interfaces$\n"
302 " $classname$OrBuilder {\n");
303 }
Feng Xiao6ef984a2014-11-10 17:34:54 -0800304 builder_type = strings::Substitute(
Jisi Liu885b6122015-02-28 14:51:22 -0800305 "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
306 name_resolver_->GetImmutableClassName(descriptor_),
307 variables["lite"]);
temporal40ee5512008-07-10 02:12:20 +0000308 } else {
Jisi Liu885b6122015-02-28 14:51:22 -0800309 if (HasDescriptorMethods(descriptor_)) {
310 printer->Print(variables,
311 "public $static$final class $classname$ extends\n"
312 " com.google.protobuf.GeneratedMessage implements\n"
313 " $extra_interfaces$\n"
314 " $classname$OrBuilder {\n");
315 } else {
316 printer->Print(variables,
317 "public $static$final class $classname$ extends\n"
318 " com.google.protobuf.GeneratedMessageLite<\n"
319 " $classname$, $classname$.Builder> implements\n"
320 " $extra_interfaces$\n"
321 " $classname$OrBuilder {\n");
322 }
323
Feng Xiao6ef984a2014-11-10 17:34:54 -0800324 builder_type = strings::Substitute(
325 "com.google.protobuf.GeneratedMessage$0.Builder",
326 variables["lite"]);
temporal40ee5512008-07-10 02:12:20 +0000327 }
328 printer->Indent();
Feng Xiao99aa0f92014-11-20 16:18:53 -0800329 if (HasDescriptorMethods(descriptor_)) {
330 // Using builder_type, instead of Builder, prevents the Builder class from
331 // being loaded into PermGen space when the default instance is created.
332 // This optimizes the PermGen space usage for clients that do not modify
333 // messages.
334 printer->Print(
335 "// Use $classname$.newBuilder() to construct.\n"
336 "private $classname$($buildertype$ builder) {\n"
337 " super(builder);\n"
338 "}\n",
339 "classname", descriptor_->name(),
340 "buildertype", builder_type);
341 printer->Print(
342 "private $classname$() {\n",
343 "classname", descriptor_->name());
344 printer->Indent();
345 GenerateInitializers(printer);
346 printer->Outdent();
347 printer->Print(
348 "}\n"
349 "\n");
Feng Xiao6ef984a2014-11-10 17:34:54 -0800350 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000351
Feng Xiao6ef984a2014-11-10 17:34:54 -0800352 if (HasDescriptorMethods(descriptor_)) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000353 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -0800354 "@java.lang.Override\n"
355 "public final com.google.protobuf.UnknownFieldSet\n"
356 "getUnknownFields() {\n");
357 if (PreserveUnknownFields(descriptor_)) {
358 printer->Print(
359 " return this.unknownFields;\n");
360 } else {
361 printer->Print(
362 " return com.google.protobuf.UnknownFieldSet.getDefaultInstance();\n");
363 }
jieluo@google.com4de8f552014-07-18 00:47:59 +0000364 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -0800365 "}\n");
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000366 }
367
368 if (HasGeneratedMethods(descriptor_)) {
369 GenerateParsingConstructor(printer);
370 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000371
Jisi Liu885b6122015-02-28 14:51:22 -0800372 GenerateDescriptorMethods(printer, false);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000373 GenerateParser(printer);
temporal40ee5512008-07-10 02:12:20 +0000374
liujisi@google.com33165fe2010-11-02 13:14:58 +0000375 // Nested types
temporal40ee5512008-07-10 02:12:20 +0000376 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000377 EnumGenerator(descriptor_->enum_type(i), true, context_)
378 .Generate(printer);
temporal40ee5512008-07-10 02:12:20 +0000379 }
380
381 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800382 // Don't generate Java classes for map entry messages.
383 if (IsMapEntry(descriptor_->nested_type(i))) continue;
jieluo@google.com4de8f552014-07-18 00:47:59 +0000384 ImmutableMessageGenerator messageGenerator(
385 descriptor_->nested_type(i), context_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000386 messageGenerator.GenerateInterface(printer);
387 messageGenerator.Generate(printer);
temporal40ee5512008-07-10 02:12:20 +0000388 }
389
jieluo@google.com4de8f552014-07-18 00:47:59 +0000390 if (GenerateHasBits(descriptor_)) {
391 // Integers for bit fields.
392 int totalBits = 0;
393 for (int i = 0; i < descriptor_->field_count(); i++) {
394 totalBits += field_generators_.get(descriptor_->field(i))
395 .GetNumBitsForMessage();
396 }
397 int totalInts = (totalBits + 31) / 32;
398 for (int i = 0; i < totalInts; i++) {
399 printer->Print("private int $bit_field_name$;\n",
400 "bit_field_name", GetBitFieldName(i));
401 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000402 }
jieluo@google.com4de8f552014-07-18 00:47:59 +0000403
404 // oneof
405 map<string, string> vars;
406 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
407 vars["oneof_name"] = context_->GetOneofGeneratorInfo(
408 descriptor_->oneof_decl(i))->name;
409 vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
410 descriptor_->oneof_decl(i))->capitalized_name;
411 vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
412 // oneofCase_ and oneof_
413 printer->Print(vars,
414 "private int $oneof_name$Case_ = 0;\n"
415 "private java.lang.Object $oneof_name$_;\n");
416 // OneofCase enum
417 printer->Print(vars,
418 "public enum $oneof_capitalized_name$Case\n"
419 " implements com.google.protobuf.Internal.EnumLite {\n");
420 printer->Indent();
421 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
422 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
423 printer->Print(
424 "$field_name$($field_number$),\n",
425 "field_name",
426 ToUpper(field->name()),
427 "field_number",
428 SimpleItoa(field->number()));
429 }
430 printer->Print(
431 "$cap_oneof_name$_NOT_SET(0);\n",
432 "cap_oneof_name",
433 ToUpper(vars["oneof_name"]));
434 printer->Print(vars,
435 "private int value = 0;\n"
436 "private $oneof_capitalized_name$Case(int value) {\n"
437 " this.value = value;\n"
438 "}\n");
439 printer->Print(vars,
440 "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
441 " switch (value) {\n");
442 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
443 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
444 printer->Print(
445 " case $field_number$: return $field_name$;\n",
446 "field_number",
447 SimpleItoa(field->number()),
448 "field_name",
449 ToUpper(field->name()));
450 }
451 printer->Print(
452 " case 0: return $cap_oneof_name$_NOT_SET;\n"
453 " default: throw new java.lang.IllegalArgumentException(\n"
454 " \"Value is undefined for this oneof enum.\");\n"
455 " }\n"
456 "}\n"
457 "public int getNumber() {\n"
458 " return this.value;\n"
459 "}\n",
460 "cap_oneof_name", ToUpper(vars["oneof_name"]));
461 printer->Outdent();
462 printer->Print("};\n\n");
463 // oneofCase()
464 printer->Print(vars,
465 "public $oneof_capitalized_name$Case\n"
466 "get$oneof_capitalized_name$Case() {\n"
467 " return $oneof_capitalized_name$Case.valueOf(\n"
468 " $oneof_name$Case_);\n"
469 "}\n"
470 "\n");
temporal40ee5512008-07-10 02:12:20 +0000471 }
472
473 // Fields
474 for (int i = 0; i < descriptor_->field_count(); i++) {
kenton@google.comcfa2d8a2009-04-18 00:02:12 +0000475 printer->Print("public static final int $constant_name$ = $number$;\n",
476 "constant_name", FieldConstantName(descriptor_->field(i)),
477 "number", SimpleItoa(descriptor_->field(i)->number()));
temporal40ee5512008-07-10 02:12:20 +0000478 field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
479 printer->Print("\n");
480 }
481
kenton@google.com80b1d622009-07-29 01:13:20 +0000482 if (HasGeneratedMethods(descriptor_)) {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000483 GenerateIsInitialized(printer, MEMOIZE);
temporal40ee5512008-07-10 02:12:20 +0000484 GenerateMessageSerializationMethods(printer);
485 }
486
liujisi@google.com33165fe2010-11-02 13:14:58 +0000487 if (HasEqualsAndHashCode(descriptor_)) {
488 GenerateEqualsAndHashCode(printer);
489 }
490
jieluo@google.com4de8f552014-07-18 00:47:59 +0000491
temporal40ee5512008-07-10 02:12:20 +0000492 GenerateParseFromMethods(printer);
493 GenerateBuilder(printer);
kenton@google.com24bf56f2008-09-24 20:31:01 +0000494
kenton@google.com24bf56f2008-09-24 20:31:01 +0000495 printer->Print(
496 "\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000497 "// @@protoc_insertion_point(class_scope:$full_name$)\n",
498 "full_name", descriptor_->full_name());
kenton@google.com24bf56f2008-09-24 20:31:01 +0000499
Feng Xiao99aa0f92014-11-20 16:18:53 -0800500
Feng Xiaof157a562014-11-14 11:50:31 -0800501 // Carefully initialize the default instance in such a way that it doesn't
502 // conflict with other initialization.
Feng Xiao99aa0f92014-11-20 16:18:53 -0800503 printer->Print(
Jisi Liu885b6122015-02-28 14:51:22 -0800504 "private static final $classname$ defaultInstance;\n",
Feng Xiao99aa0f92014-11-20 16:18:53 -0800505 "classname", name_resolver_->GetImmutableClassName(descriptor_));
506 if (HasDescriptorMethods(descriptor_)) {
507 printer->Print(
508 "static {\n"
509 " defaultInstance = new $classname$();\n"
510 "}\n"
511 "\n",
512 "classname", name_resolver_->GetImmutableClassName(descriptor_));
513 } else {
514 // LITE_RUNTIME only has one constructor.
515 printer->Print(
516 "static {\n"
Jisi Liu885b6122015-02-28 14:51:22 -0800517 " defaultInstance = new $classname$(\n"
518 " com.google.protobuf.Internal\n"
519 " .EMPTY_CODED_INPUT_STREAM,\n"
520 " com.google.protobuf.ExtensionRegistryLite\n"
521 " .getEmptyRegistry());\n"
Feng Xiao99aa0f92014-11-20 16:18:53 -0800522 "}\n"
523 "\n",
524 "classname", descriptor_->name());
525 }
526 printer->Print(
Feng Xiaof157a562014-11-14 11:50:31 -0800527 "public static $classname$ getDefaultInstance() {\n"
528 " return defaultInstance;\n"
529 "}\n"
Jisi Liu885b6122015-02-28 14:51:22 -0800530 "\n",
531 "classname", name_resolver_->GetImmutableClassName(descriptor_));
532
533 if (HasDescriptorMethods(descriptor_)) {
534 // LITE_RUNTIME implements this at the GeneratedMessageLite level.
535 printer->Print(
Feng Xiaof157a562014-11-14 11:50:31 -0800536 "public $classname$ getDefaultInstanceForType() {\n"
537 " return defaultInstance;\n"
538 "}\n"
539 "\n",
Feng Xiao99aa0f92014-11-20 16:18:53 -0800540 "classname", name_resolver_->GetImmutableClassName(descriptor_));
Jisi Liu885b6122015-02-28 14:51:22 -0800541 } else {
542 // LITE_RUNTIME uses this to implement the *ForType methods at the
543 // GeneratedMessageLite level.
544 printer->Print(
545 "static {"
546 " com.google.protobuf.GeneratedMessageLite.onLoad(\n"
547 " $classname$.class, new com.google.protobuf.GeneratedMessageLite\n"
548 " .PrototypeHolder<$classname$, Builder>(\n"
549 " defaultInstance, PARSER));"
550 "}\n"
551 "\n",
552 "classname", name_resolver_->GetImmutableClassName(descriptor_));
553 }
Feng Xiaof157a562014-11-14 11:50:31 -0800554
liujisi@google.com33165fe2010-11-02 13:14:58 +0000555 // Extensions must be declared after the defaultInstance is initialized
556 // because the defaultInstance is used by the extension to lazily retrieve
557 // the outer class's FileDescriptor.
558 for (int i = 0; i < descriptor_->extension_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000559 ImmutableExtensionGenerator(descriptor_->extension(i), context_)
560 .Generate(printer);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000561 }
562
Jisi Liu885b6122015-02-28 14:51:22 -0800563 // Some fields also have static members that must be initialized after we
564 // have the default instance available.
565 printer->Print(
566 "static {\n");
567 printer->Indent();
568 for (int i = 0; i < descriptor_->field_count(); i++) {
569 field_generators_.get(descriptor_->field(i))
570 .GenerateStaticInitializationCode(printer);
571 }
572 printer->Outdent();
573 printer->Print(
574 "}\n");
575
kenton@google.com24bf56f2008-09-24 20:31:01 +0000576 printer->Outdent();
577 printer->Print("}\n\n");
temporal40ee5512008-07-10 02:12:20 +0000578}
579
liujisi@google.com33165fe2010-11-02 13:14:58 +0000580
temporal40ee5512008-07-10 02:12:20 +0000581// ===================================================================
582
jieluo@google.com4de8f552014-07-18 00:47:59 +0000583void ImmutableMessageGenerator::
temporal40ee5512008-07-10 02:12:20 +0000584GenerateMessageSerializationMethods(io::Printer* printer) {
Feng Xiaof157a562014-11-14 11:50:31 -0800585 google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
jieluo@google.com4de8f552014-07-18 00:47:59 +0000586 SortFieldsByNumber(descriptor_));
temporal40ee5512008-07-10 02:12:20 +0000587
588 vector<const Descriptor::ExtensionRange*> sorted_extensions;
589 for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
590 sorted_extensions.push_back(descriptor_->extension_range(i));
591 }
Jisi Liu885b6122015-02-28 14:51:22 -0800592 std::sort(sorted_extensions.begin(), sorted_extensions.end(),
593 ExtensionRangeOrdering());
temporal40ee5512008-07-10 02:12:20 +0000594
595 printer->Print(
596 "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
597 " throws java.io.IOException {\n");
598 printer->Indent();
Jisi Liu885b6122015-02-28 14:51:22 -0800599 if (HasPackedFields(descriptor_)) {
600 // writeTo(CodedOutputStream output) might be invoked without
601 // getSerializedSize() ever being called, but we need the memoized
602 // sizes in case this message has packed fields. Rather than emit checks for
603 // each packed field, just call getSerializedSize() up front.
604 // In most cases, getSerializedSize() will have already been called anyway
605 // by one of the wrapper writeTo() methods, making this call cheap.
606 printer->Print(
607 "getSerializedSize();\n");
608 }
temporal40ee5512008-07-10 02:12:20 +0000609
610 if (descriptor_->extension_range_count() > 0) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000611 if (descriptor_->options().message_set_wire_format()) {
Jisi Liu885b6122015-02-28 14:51:22 -0800612 if (HasDescriptorMethods(descriptor_)) {
613 printer->Print(
614 "com.google.protobuf.GeneratedMessage\n"
615 " .ExtendableMessage<$classname$>.ExtensionWriter\n"
616 " extensionWriter = newMessageSetExtensionWriter();\n",
617 "classname", name_resolver_->GetImmutableClassName(descriptor_));
618 } else {
619 printer->Print(
620 "com.google.protobuf.GeneratedMessageLite\n"
621 " .ExtendableMessage<$classname$, $classname$.Builder>\n"
622 " .ExtensionWriter extensionWriter =\n"
623 " newMessageSetExtensionWriter();\n",
624 "classname", name_resolver_->GetImmutableClassName(descriptor_));
625 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000626 } else {
Jisi Liu885b6122015-02-28 14:51:22 -0800627 if (HasDescriptorMethods(descriptor_)) {
628 printer->Print(
629 "com.google.protobuf.GeneratedMessage\n"
630 " .ExtendableMessage<$classname$>.ExtensionWriter\n"
631 " extensionWriter = newExtensionWriter();\n",
632 "classname", name_resolver_->GetImmutableClassName(descriptor_));
633 } else {
634 printer->Print(
635 "com.google.protobuf.GeneratedMessageLite\n"
636 " .ExtendableMessage<$classname$, $classname$.Builder>\n"
637 " .ExtensionWriter extensionWriter =\n"
638 " newExtensionWriter();\n",
639 "classname", name_resolver_->GetImmutableClassName(descriptor_));
640 }
kenton@google.com80b1d622009-07-29 01:13:20 +0000641 }
temporal40ee5512008-07-10 02:12:20 +0000642 }
643
644 // Merge the fields and the extension ranges, both sorted by field number.
645 for (int i = 0, j = 0;
646 i < descriptor_->field_count() || j < sorted_extensions.size();
647 ) {
648 if (i == descriptor_->field_count()) {
649 GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
650 } else if (j == sorted_extensions.size()) {
651 GenerateSerializeOneField(printer, sorted_fields[i++]);
652 } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
653 GenerateSerializeOneField(printer, sorted_fields[i++]);
654 } else {
655 GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
656 }
657 }
658
Feng Xiao6ef984a2014-11-10 17:34:54 -0800659 if (PreserveUnknownFields(descriptor_)) {
660 if (descriptor_->options().message_set_wire_format()
661 && HasDescriptorMethods(descriptor_)) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000662 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -0800663 "unknownFields.writeAsMessageSetTo(output);\n");
kenton@google.com80b1d622009-07-29 01:13:20 +0000664 } else {
665 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -0800666 "unknownFields.writeTo(output);\n");
kenton@google.com80b1d622009-07-29 01:13:20 +0000667 }
temporal40ee5512008-07-10 02:12:20 +0000668 }
669
670 printer->Outdent();
671 printer->Print(
672 "}\n"
673 "\n"
674 "private int memoizedSerializedSize = -1;\n"
675 "public int getSerializedSize() {\n"
676 " int size = memoizedSerializedSize;\n"
677 " if (size != -1) return size;\n"
678 "\n"
679 " size = 0;\n");
680 printer->Indent();
681
682 for (int i = 0; i < descriptor_->field_count(); i++) {
683 field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
684 }
685
686 if (descriptor_->extension_range_count() > 0) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000687 if (descriptor_->options().message_set_wire_format()) {
688 printer->Print(
689 "size += extensionsSerializedSizeAsMessageSet();\n");
690 } else {
691 printer->Print(
692 "size += extensionsSerializedSize();\n");
693 }
temporal40ee5512008-07-10 02:12:20 +0000694 }
695
Feng Xiao6ef984a2014-11-10 17:34:54 -0800696 if (PreserveUnknownFields(descriptor_)) {
697 if (descriptor_->options().message_set_wire_format()
698 && HasDescriptorMethods(descriptor_)) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000699 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -0800700 "size += unknownFields.getSerializedSizeAsMessageSet();\n");
kenton@google.com80b1d622009-07-29 01:13:20 +0000701 } else {
702 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -0800703 "size += unknownFields.getSerializedSize();\n");
kenton@google.com80b1d622009-07-29 01:13:20 +0000704 }
temporal40ee5512008-07-10 02:12:20 +0000705 }
706
707 printer->Outdent();
708 printer->Print(
709 " memoizedSerializedSize = size;\n"
710 " return size;\n"
711 "}\n"
712 "\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000713
714 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -0800715 "private static final long serialVersionUID = 0L;\n");
temporal40ee5512008-07-10 02:12:20 +0000716}
717
jieluo@google.com4de8f552014-07-18 00:47:59 +0000718void ImmutableMessageGenerator::
temporal40ee5512008-07-10 02:12:20 +0000719GenerateParseFromMethods(io::Printer* printer) {
720 // Note: These are separate from GenerateMessageSerializationMethods()
721 // because they need to be generated even for messages that are optimized
722 // for code size.
723 printer->Print(
724 "public static $classname$ parseFrom(\n"
725 " com.google.protobuf.ByteString data)\n"
726 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000727 " return PARSER.parseFrom(data);\n"
temporal40ee5512008-07-10 02:12:20 +0000728 "}\n"
729 "public static $classname$ parseFrom(\n"
730 " com.google.protobuf.ByteString data,\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000731 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
temporal40ee5512008-07-10 02:12:20 +0000732 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000733 " return PARSER.parseFrom(data, extensionRegistry);\n"
temporal40ee5512008-07-10 02:12:20 +0000734 "}\n"
735 "public static $classname$ parseFrom(byte[] data)\n"
736 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000737 " return PARSER.parseFrom(data);\n"
temporal40ee5512008-07-10 02:12:20 +0000738 "}\n"
739 "public static $classname$ parseFrom(\n"
740 " byte[] data,\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000741 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
temporal40ee5512008-07-10 02:12:20 +0000742 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000743 " return PARSER.parseFrom(data, extensionRegistry);\n"
temporal40ee5512008-07-10 02:12:20 +0000744 "}\n"
745 "public static $classname$ parseFrom(java.io.InputStream input)\n"
746 " throws java.io.IOException {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000747 " return PARSER.parseFrom(input);\n"
temporal40ee5512008-07-10 02:12:20 +0000748 "}\n"
749 "public static $classname$ parseFrom(\n"
750 " java.io.InputStream input,\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000751 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
temporal40ee5512008-07-10 02:12:20 +0000752 " throws java.io.IOException {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000753 " return PARSER.parseFrom(input, extensionRegistry);\n"
temporal40ee5512008-07-10 02:12:20 +0000754 "}\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000755 "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
756 " throws java.io.IOException {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000757 " return PARSER.parseDelimitedFrom(input);\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000758 "}\n"
759 "public static $classname$ parseDelimitedFrom(\n"
760 " java.io.InputStream input,\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000761 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000762 " throws java.io.IOException {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000763 " return PARSER.parseDelimitedFrom(input, extensionRegistry);\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000764 "}\n"
temporal40ee5512008-07-10 02:12:20 +0000765 "public static $classname$ parseFrom(\n"
766 " com.google.protobuf.CodedInputStream input)\n"
767 " throws java.io.IOException {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000768 " return PARSER.parseFrom(input);\n"
temporal40ee5512008-07-10 02:12:20 +0000769 "}\n"
770 "public static $classname$ parseFrom(\n"
771 " com.google.protobuf.CodedInputStream input,\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000772 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
temporal40ee5512008-07-10 02:12:20 +0000773 " throws java.io.IOException {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000774 " return PARSER.parseFrom(input, extensionRegistry);\n"
temporal40ee5512008-07-10 02:12:20 +0000775 "}\n"
776 "\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +0000777 "classname", name_resolver_->GetImmutableClassName(descriptor_));
temporal40ee5512008-07-10 02:12:20 +0000778}
779
jieluo@google.com4de8f552014-07-18 00:47:59 +0000780void ImmutableMessageGenerator::GenerateSerializeOneField(
temporal40ee5512008-07-10 02:12:20 +0000781 io::Printer* printer, const FieldDescriptor* field) {
782 field_generators_.get(field).GenerateSerializationCode(printer);
783}
784
jieluo@google.com4de8f552014-07-18 00:47:59 +0000785void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange(
temporal40ee5512008-07-10 02:12:20 +0000786 io::Printer* printer, const Descriptor::ExtensionRange* range) {
787 printer->Print(
788 "extensionWriter.writeUntil($end$, output);\n",
789 "end", SimpleItoa(range->end));
790}
791
792// ===================================================================
793
jieluo@google.com4de8f552014-07-18 00:47:59 +0000794void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
Jisi Liu885b6122015-02-28 14:51:22 -0800795 if (HasDescriptorMethods(descriptor_)) {
796 // LITE_RUNTIME implements this at the GeneratedMessageLite level.
797 printer->Print(
798 "public Builder newBuilderForType() { return newBuilder(); }\n");
799 }
800
temporal40ee5512008-07-10 02:12:20 +0000801 printer->Print(
Jisi Liu885b6122015-02-28 14:51:22 -0800802 "public static Builder newBuilder() {\n"
803 " return defaultInstance.toBuilder();\n"
temporal40ee5512008-07-10 02:12:20 +0000804 "}\n"
Jisi Liu885b6122015-02-28 14:51:22 -0800805 "public static Builder newBuilder($classname$ prototype) {\n"
806 " return defaultInstance.toBuilder().mergeFrom(prototype);\n"
807 "}\n"
808 "public Builder toBuilder() {\n"
809 " return this == defaultInstance\n"
810 " ? new Builder() : new Builder().mergeFrom(this);\n"
811 "}\n"
temporal40ee5512008-07-10 02:12:20 +0000812 "\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +0000813 "classname", name_resolver_->GetImmutableClassName(descriptor_));
temporal40ee5512008-07-10 02:12:20 +0000814
liujisi@google.com33165fe2010-11-02 13:14:58 +0000815 if (HasNestedBuilders(descriptor_)) {
816 printer->Print(
817 "@java.lang.Override\n"
818 "protected Builder newBuilderForType(\n"
819 " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
820 " Builder builder = new Builder(parent);\n"
821 " return builder;\n"
822 "}\n");
823 }
824
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000825 WriteMessageDocComment(printer, descriptor_);
826
temporal40ee5512008-07-10 02:12:20 +0000827 if (descriptor_->extension_range_count() > 0) {
kenton@google.com80b1d622009-07-29 01:13:20 +0000828 if (HasDescriptorMethods(descriptor_)) {
829 printer->Print(
830 "public static final class Builder extends\n"
831 " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000832 " $classname$, Builder> implements\n"
833 " $extra_interfaces$\n"
834 " $classname$OrBuilder {\n",
835 "classname", name_resolver_->GetImmutableClassName(descriptor_),
836 "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
kenton@google.com80b1d622009-07-29 01:13:20 +0000837 } else {
838 printer->Print(
839 "public static final class Builder extends\n"
840 " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000841 " $classname$, Builder> implements\n"
842 " $extra_interfaces$\n"
843 " $classname$OrBuilder {\n",
844 "classname", name_resolver_->GetImmutableClassName(descriptor_),
845 "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
kenton@google.com80b1d622009-07-29 01:13:20 +0000846 }
temporal40ee5512008-07-10 02:12:20 +0000847 } else {
kenton@google.com80b1d622009-07-29 01:13:20 +0000848 if (HasDescriptorMethods(descriptor_)) {
849 printer->Print(
850 "public static final class Builder extends\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000851 " com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n"
852 " $extra_interfaces$\n"
853 " $classname$OrBuilder {\n",
854 "classname", name_resolver_->GetImmutableClassName(descriptor_),
855 "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
kenton@google.com80b1d622009-07-29 01:13:20 +0000856 } else {
857 printer->Print(
858 "public static final class Builder extends\n"
859 " com.google.protobuf.GeneratedMessageLite.Builder<\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000860 " $classname$, Builder>\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000861 " implements\n"
862 " $extra_interfaces$\n"
863 " $classname$OrBuilder {\n",
864 "classname", name_resolver_->GetImmutableClassName(descriptor_),
865 "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
kenton@google.com80b1d622009-07-29 01:13:20 +0000866 }
temporal40ee5512008-07-10 02:12:20 +0000867 }
868 printer->Indent();
869
Jisi Liu885b6122015-02-28 14:51:22 -0800870 GenerateDescriptorMethods(printer, true);
temporal40ee5512008-07-10 02:12:20 +0000871 GenerateCommonBuilderMethods(printer);
872
kenton@google.com80b1d622009-07-29 01:13:20 +0000873 if (HasGeneratedMethods(descriptor_)) {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000874 GenerateIsInitialized(printer, DONT_MEMOIZE);
Feng Xiao99aa0f92014-11-20 16:18:53 -0800875 GenerateBuilderParsingMethods(printer);
temporal40ee5512008-07-10 02:12:20 +0000876 }
877
jieluo@google.com4de8f552014-07-18 00:47:59 +0000878 // oneof
879 map<string, string> vars;
880 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
881 vars["oneof_name"] = context_->GetOneofGeneratorInfo(
882 descriptor_->oneof_decl(i))->name;
883 vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
884 descriptor_->oneof_decl(i))->capitalized_name;
885 vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
886 // oneofCase_ and oneof_
887 printer->Print(vars,
888 "private int $oneof_name$Case_ = 0;\n"
889 "private java.lang.Object $oneof_name$_;\n");
890 // oneofCase() and clearOneof()
891 printer->Print(vars,
892 "public $oneof_capitalized_name$Case\n"
893 " get$oneof_capitalized_name$Case() {\n"
894 " return $oneof_capitalized_name$Case.valueOf(\n"
895 " $oneof_name$Case_);\n"
896 "}\n"
897 "\n"
898 "public Builder clear$oneof_capitalized_name$() {\n"
899 " $oneof_name$Case_ = 0;\n"
900 " $oneof_name$_ = null;\n");
901 if (HasDescriptorMethods(descriptor_)) {
902 printer->Print(" onChanged();\n");
903 }
904 printer->Print(
905 " return this;\n"
906 "}\n"
907 "\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000908 }
jieluo@google.com4de8f552014-07-18 00:47:59 +0000909
910 if (GenerateHasBits(descriptor_)) {
911 // Integers for bit fields.
912 int totalBits = 0;
913 for (int i = 0; i < descriptor_->field_count(); i++) {
914 totalBits += field_generators_.get(descriptor_->field(i))
915 .GetNumBitsForBuilder();
916 }
917 int totalInts = (totalBits + 31) / 32;
918 for (int i = 0; i < totalInts; i++) {
919 printer->Print("private int $bit_field_name$;\n",
920 "bit_field_name", GetBitFieldName(i));
921 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000922 }
923
temporal40ee5512008-07-10 02:12:20 +0000924 for (int i = 0; i < descriptor_->field_count(); i++) {
925 printer->Print("\n");
temporal40ee5512008-07-10 02:12:20 +0000926 field_generators_.get(descriptor_->field(i))
927 .GenerateBuilderMembers(printer);
928 }
929
Feng Xiao6ef984a2014-11-10 17:34:54 -0800930 if (!PreserveUnknownFields(descriptor_)) {
931 printer->Print(
932 "public final Builder setUnknownFields(\n"
933 " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
934 " return this;\n"
935 "}\n"
936 "\n"
937 "public final Builder mergeUnknownFields(\n"
938 " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
939 " return this;\n"
940 "}\n"
941 "\n");
942 }
943
temporal8ee14742009-12-20 00:09:50 +0000944 printer->Print(
945 "\n"
946 "// @@protoc_insertion_point(builder_scope:$full_name$)\n",
947 "full_name", descriptor_->full_name());
948
temporal40ee5512008-07-10 02:12:20 +0000949 printer->Outdent();
950 printer->Print("}\n");
temporal40ee5512008-07-10 02:12:20 +0000951}
952
jieluo@google.com4de8f552014-07-18 00:47:59 +0000953void ImmutableMessageGenerator::
Jisi Liu885b6122015-02-28 14:51:22 -0800954GenerateDescriptorMethods(io::Printer* printer, bool is_builder) {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000955 if (HasDescriptorMethods(descriptor_)) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000956 if (!descriptor_->options().no_standard_descriptor_accessor()) {
957 printer->Print(
958 "public static final com.google.protobuf.Descriptors.Descriptor\n"
959 " getDescriptor() {\n"
960 " return $fileclass$.internal_$identifier$_descriptor;\n"
961 "}\n"
962 "\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +0000963 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000964 "identifier", UniqueFileScopeIdentifier(descriptor_));
965 }
Feng Xiao6ef984a2014-11-10 17:34:54 -0800966 vector<const FieldDescriptor*> map_fields;
967 for (int i = 0; i < descriptor_->field_count(); i++) {
968 const FieldDescriptor* field = descriptor_->field(i);
969 if (GetJavaType(field) == JAVATYPE_MESSAGE &&
970 IsMapEntry(field->message_type())) {
971 map_fields.push_back(field);
972 }
973 }
974 if (!map_fields.empty()) {
975 printer->Print(
976 "@SuppressWarnings({\"rawtypes\"})\n"
977 "protected com.google.protobuf.MapField internalGetMapField(\n"
978 " int number) {\n"
979 " switch (number) {\n");
980 printer->Indent();
981 printer->Indent();
982 for (int i = 0; i < map_fields.size(); ++i) {
983 const FieldDescriptor* field = map_fields[i];
984 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
985 printer->Print(
986 "case $number$:\n"
Jisi Liu885b6122015-02-28 14:51:22 -0800987 " return internalGet$capitalized_name$();\n",
Feng Xiao6ef984a2014-11-10 17:34:54 -0800988 "number", SimpleItoa(field->number()),
Jisi Liu885b6122015-02-28 14:51:22 -0800989 "capitalized_name", info->capitalized_name);
Feng Xiao6ef984a2014-11-10 17:34:54 -0800990 }
991 printer->Print(
992 "default:\n"
993 " throw new RuntimeException(\n"
994 " \"Invalid map field number: \" + number);\n");
995 printer->Outdent();
996 printer->Outdent();
997 printer->Print(
998 " }\n"
999 "}\n");
Jisi Liu885b6122015-02-28 14:51:22 -08001000 if (is_builder) {
1001 printer->Print(
1002 "@SuppressWarnings({\"rawtypes\"})\n"
1003 "protected com.google.protobuf.MapField internalGetMutableMapField(\n"
1004 " int number) {\n"
1005 " switch (number) {\n");
1006 printer->Indent();
1007 printer->Indent();
1008 for (int i = 0; i < map_fields.size(); ++i) {
1009 const FieldDescriptor* field = map_fields[i];
1010 const FieldGeneratorInfo* info =
1011 context_->GetFieldGeneratorInfo(field);
1012 printer->Print(
1013 "case $number$:\n"
1014 " return internalGetMutable$capitalized_name$();\n",
1015 "number", SimpleItoa(field->number()),
1016 "capitalized_name", info->capitalized_name);
1017 }
1018 printer->Print(
1019 "default:\n"
1020 " throw new RuntimeException(\n"
1021 " \"Invalid map field number: \" + number);\n");
1022 printer->Outdent();
1023 printer->Outdent();
1024 printer->Print(
1025 " }\n"
1026 "}\n");
1027 }
Feng Xiao6ef984a2014-11-10 17:34:54 -08001028 }
liujisi@google.com33165fe2010-11-02 13:14:58 +00001029 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001030 "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
1031 " internalGetFieldAccessorTable() {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001032 " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
1033 " .ensureFieldAccessorsInitialized(\n"
1034 " $classname$.class, $classname$.Builder.class);\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001035 "}\n"
1036 "\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001037 "classname", name_resolver_->GetImmutableClassName(descriptor_),
1038 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
liujisi@google.com33165fe2010-11-02 13:14:58 +00001039 "identifier", UniqueFileScopeIdentifier(descriptor_));
1040 }
1041}
1042
temporal40ee5512008-07-10 02:12:20 +00001043// ===================================================================
1044
jieluo@google.com4de8f552014-07-18 00:47:59 +00001045void ImmutableMessageGenerator::
1046GenerateCommonBuilderMethods(io::Printer* printer) {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001047 if (HasDescriptorMethods(descriptor_)) {
1048 printer->Print(
Feng Xiaof157a562014-11-14 11:50:31 -08001049 "// Construct using $classname$.newBuilder()\n"
1050 "private Builder() {\n"
1051 " maybeForceBuilderInitialization();\n"
1052 "}\n"
1053 "\n",
1054 "classname", name_resolver_->GetImmutableClassName(descriptor_));
1055
1056 printer->Print(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001057 "private Builder(\n"
1058 " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001059 " super(parent);\n"
1060 " maybeForceBuilderInitialization();\n"
1061 "}\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001062 "classname", name_resolver_->GetImmutableClassName(descriptor_));
Feng Xiaof157a562014-11-14 11:50:31 -08001063 } else {
1064 // LITE runtime passes along the default instance to implement
Jisi Liu885b6122015-02-28 14:51:22 -08001065 // getDefaultInstanceForType() at the GeneratedMessageLite level.
Feng Xiaof157a562014-11-14 11:50:31 -08001066 printer->Print(
1067 "// Construct using $classname$.newBuilder()\n"
1068 "private Builder() {\n"
1069 " super(defaultInstance);\n"
1070 " maybeForceBuilderInitialization();\n"
1071 "}\n"
1072 "\n",
1073 "classname", name_resolver_->GetImmutableClassName(descriptor_));
liujisi@google.com33165fe2010-11-02 13:14:58 +00001074 }
1075
1076
1077 if (HasNestedBuilders(descriptor_)) {
1078 printer->Print(
1079 "private void maybeForceBuilderInitialization() {\n"
1080 " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
1081
1082 printer->Indent();
1083 printer->Indent();
1084 for (int i = 0; i < descriptor_->field_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001085 if (!descriptor_->field(i)->containing_oneof()) {
1086 field_generators_.get(descriptor_->field(i))
1087 .GenerateFieldBuilderInitializationCode(printer);
1088 }
liujisi@google.com33165fe2010-11-02 13:14:58 +00001089 }
1090 printer->Outdent();
1091 printer->Outdent();
1092
1093 printer->Print(
1094 " }\n"
1095 "}\n");
1096 } else {
1097 printer->Print(
1098 "private void maybeForceBuilderInitialization() {\n"
1099 "}\n");
1100 }
1101
1102 printer->Print(
temporal40ee5512008-07-10 02:12:20 +00001103 "public Builder clear() {\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -08001104 " super.clear();\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +00001105
1106 printer->Indent();
1107
1108 for (int i = 0; i < descriptor_->field_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001109 if (!descriptor_->field(i)->containing_oneof()) {
1110 field_generators_.get(descriptor_->field(i))
1111 .GenerateBuilderClearCode(printer);
1112 }
1113 }
1114
1115 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
1116 printer->Print(
1117 "$oneof_name$Case_ = 0;\n"
1118 "$oneof_name$_ = null;\n",
1119 "oneof_name", context_->GetOneofGeneratorInfo(
1120 descriptor_->oneof_decl(i))->name);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001121 }
1122
1123 printer->Outdent();
1124
1125 printer->Print(
temporal40ee5512008-07-10 02:12:20 +00001126 " return this;\n"
1127 "}\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -08001128 "\n");
1129
kenton@google.com80b1d622009-07-29 01:13:20 +00001130 if (HasDescriptorMethods(descriptor_)) {
1131 printer->Print(
kenton@google.com80b1d622009-07-29 01:13:20 +00001132 "public com.google.protobuf.Descriptors.Descriptor\n"
1133 " getDescriptorForType() {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001134 " return $fileclass$.internal_$identifier$_descriptor;\n"
kenton@google.com80b1d622009-07-29 01:13:20 +00001135 "}\n"
1136 "\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001137 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001138 "identifier", UniqueFileScopeIdentifier(descriptor_));
Feng Xiaof157a562014-11-14 11:50:31 -08001139
1140 // LITE runtime implements this in GeneratedMessageLite.
1141 printer->Print(
1142 "public $classname$ getDefaultInstanceForType() {\n"
1143 " return $classname$.getDefaultInstance();\n"
1144 "}\n"
1145 "\n",
1146 "classname", name_resolver_->GetImmutableClassName(descriptor_));
kenton@google.com80b1d622009-07-29 01:13:20 +00001147 }
temporal40ee5512008-07-10 02:12:20 +00001148
1149 // -----------------------------------------------------------------
1150
Feng Xiaof157a562014-11-14 11:50:31 -08001151 if (HasDescriptorMethods(descriptor_)) {
1152 // LITE implements build in GeneratedMessageLite to save methods.
1153 printer->Print(
1154 "public $classname$ build() {\n"
1155 " $classname$ result = buildPartial();\n"
1156 " if (!result.isInitialized()) {\n"
1157 " throw newUninitializedMessageException(result);\n"
1158 " }\n"
1159 " return result;\n"
1160 "}\n"
1161 "\n",
1162 "classname", name_resolver_->GetImmutableClassName(descriptor_));
1163 }
1164
Feng Xiao99aa0f92014-11-20 16:18:53 -08001165 if (HasDescriptorMethods(descriptor_)) {
1166 printer->Print(
1167 "public $classname$ buildPartial() {\n"
Jisi Liu885b6122015-02-28 14:51:22 -08001168 " $classname$ result = new $classname$(this);\n",
1169 "classname", name_resolver_->GetImmutableClassName(descriptor_));
Feng Xiao99aa0f92014-11-20 16:18:53 -08001170 } else {
1171 // LITE_RUNTIME only provides a single message constructor.
1172 printer->Print(
1173 "public $classname$ buildPartial() {\n"
Jisi Liu885b6122015-02-28 14:51:22 -08001174 " $classname$ result = new $classname$(\n"
1175 " com.google.protobuf.Internal\n"
1176 " .EMPTY_CODED_INPUT_STREAM,\n"
1177 " com.google.protobuf.ExtensionRegistryLite\n"
1178 " .getEmptyRegistry());\n"
Feng Xiao99aa0f92014-11-20 16:18:53 -08001179 " result.unknownFields = this.unknownFields;\n",
1180 "classname", name_resolver_->GetImmutableClassName(descriptor_));
1181
1182 if (descriptor_->extension_range_count() > 0) {
1183 printer->Print(
1184 " result.extensions = this.buildExtensions();\n");
1185 }
1186 }
liujisi@google.com33165fe2010-11-02 13:14:58 +00001187
temporal40ee5512008-07-10 02:12:20 +00001188 printer->Indent();
1189
liujisi@google.com33165fe2010-11-02 13:14:58 +00001190 int totalBuilderBits = 0;
1191 int totalMessageBits = 0;
1192 for (int i = 0; i < descriptor_->field_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001193 const ImmutableFieldGenerator& field =
1194 field_generators_.get(descriptor_->field(i));
liujisi@google.com33165fe2010-11-02 13:14:58 +00001195 totalBuilderBits += field.GetNumBitsForBuilder();
1196 totalMessageBits += field.GetNumBitsForMessage();
1197 }
1198 int totalBuilderInts = (totalBuilderBits + 31) / 32;
1199 int totalMessageInts = (totalMessageBits + 31) / 32;
jieluo@google.com4de8f552014-07-18 00:47:59 +00001200
1201 if (GenerateHasBits(descriptor_)) {
1202 // Local vars for from and to bit fields to avoid accessing the builder and
1203 // message over and over for these fields. Seems to provide a slight
1204 // perforamance improvement in micro benchmark and this is also what proto1
1205 // code does.
1206 for (int i = 0; i < totalBuilderInts; i++) {
1207 printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
1208 "bit_field_name", GetBitFieldName(i));
1209 }
1210 for (int i = 0; i < totalMessageInts; i++) {
1211 printer->Print("int to_$bit_field_name$ = 0;\n",
1212 "bit_field_name", GetBitFieldName(i));
1213 }
liujisi@google.com33165fe2010-11-02 13:14:58 +00001214 }
1215
1216 // Output generation code for each field.
temporal40ee5512008-07-10 02:12:20 +00001217 for (int i = 0; i < descriptor_->field_count(); i++) {
1218 field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
1219 }
1220
jieluo@google.com4de8f552014-07-18 00:47:59 +00001221 if (GenerateHasBits(descriptor_)) {
1222 // Copy the bit field results to the generated message
1223 for (int i = 0; i < totalMessageInts; i++) {
1224 printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
1225 "bit_field_name", GetBitFieldName(i));
1226 }
1227 }
1228
1229 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
1230 printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n",
1231 "oneof_name", context_->GetOneofGeneratorInfo(
1232 descriptor_->oneof_decl(i))->name);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001233 }
1234
temporal40ee5512008-07-10 02:12:20 +00001235 printer->Outdent();
liujisi@google.com33165fe2010-11-02 13:14:58 +00001236
1237 if (HasDescriptorMethods(descriptor_)) {
1238 printer->Print(
1239 " onBuilt();\n");
1240 }
1241
temporal40ee5512008-07-10 02:12:20 +00001242 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001243 " return result;\n"
temporal40ee5512008-07-10 02:12:20 +00001244 "}\n"
1245 "\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001246 "classname", name_resolver_->GetImmutableClassName(descriptor_));
temporal40ee5512008-07-10 02:12:20 +00001247
1248 // -----------------------------------------------------------------
1249
kenton@google.com80b1d622009-07-29 01:13:20 +00001250 if (HasGeneratedMethods(descriptor_)) {
1251 // MergeFrom(Message other) requires the ability to distinguish the other
1252 // messages type by its descriptor.
1253 if (HasDescriptorMethods(descriptor_)) {
1254 printer->Print(
kenton@google.com80b1d622009-07-29 01:13:20 +00001255 "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
1256 " if (other instanceof $classname$) {\n"
1257 " return mergeFrom(($classname$)other);\n"
1258 " } else {\n"
1259 " super.mergeFrom(other);\n"
1260 " return this;\n"
1261 " }\n"
1262 "}\n"
1263 "\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001264 "classname", name_resolver_->GetImmutableClassName(descriptor_));
kenton@google.com80b1d622009-07-29 01:13:20 +00001265 }
1266
temporal40ee5512008-07-10 02:12:20 +00001267 printer->Print(
temporal40ee5512008-07-10 02:12:20 +00001268 "public Builder mergeFrom($classname$ other) {\n"
1269 // Optimization: If other is the default instance, we know none of its
1270 // fields are set so we can skip the merge.
1271 " if (other == $classname$.getDefaultInstance()) return this;\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001272 "classname", name_resolver_->GetImmutableClassName(descriptor_));
temporal40ee5512008-07-10 02:12:20 +00001273 printer->Indent();
1274
1275 for (int i = 0; i < descriptor_->field_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001276 if (!descriptor_->field(i)->containing_oneof()) {
1277 field_generators_.get(
1278 descriptor_->field(i)).GenerateMergingCode(printer);
1279 }
1280 }
1281
1282 // Merge oneof fields.
1283 for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
1284 printer->Print(
1285 "switch (other.get$oneof_capitalized_name$Case()) {\n",
1286 "oneof_capitalized_name",
1287 context_->GetOneofGeneratorInfo(
1288 descriptor_->oneof_decl(i))->capitalized_name);
1289 printer->Indent();
1290 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
1291 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
1292 printer->Print(
1293 "case $field_name$: {\n",
1294 "field_name",
1295 ToUpper(field->name()));
1296 printer->Indent();
1297 field_generators_.get(field).GenerateMergingCode(printer);
1298 printer->Print(
1299 "break;\n");
1300 printer->Outdent();
1301 printer->Print(
1302 "}\n");
1303 }
1304 printer->Print(
1305 "case $cap_oneof_name$_NOT_SET: {\n"
1306 " break;\n"
1307 "}\n",
1308 "cap_oneof_name",
1309 ToUpper(context_->GetOneofGeneratorInfo(
1310 descriptor_->oneof_decl(i))->name));
1311 printer->Outdent();
1312 printer->Print(
1313 "}\n");
temporal40ee5512008-07-10 02:12:20 +00001314 }
1315
1316 printer->Outdent();
kenton@google.com2d6daa72009-01-22 01:27:00 +00001317
1318 // if message type has extensions
1319 if (descriptor_->extension_range_count() > 0) {
1320 printer->Print(
1321 " this.mergeExtensionFields(other);\n");
1322 }
1323
Feng Xiao6ef984a2014-11-10 17:34:54 -08001324 if (PreserveUnknownFields(descriptor_)) {
kenton@google.com80b1d622009-07-29 01:13:20 +00001325 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -08001326 " this.mergeUnknownFields(other.unknownFields);\n");
1327 }
1328
1329 if (HasDescriptorMethods(descriptor_)) {
1330 printer->Print(" onChanged();\n");
kenton@google.com80b1d622009-07-29 01:13:20 +00001331 }
1332
temporal40ee5512008-07-10 02:12:20 +00001333 printer->Print(
temporal40ee5512008-07-10 02:12:20 +00001334 " return this;\n"
1335 "}\n"
1336 "\n");
1337 }
1338}
1339
1340// ===================================================================
1341
Feng Xiao99aa0f92014-11-20 16:18:53 -08001342void ImmutableMessageGenerator::
1343GenerateBuilderParsingMethods(io::Printer* printer) {
1344 if (HasDescriptorMethods(descriptor_)) {
1345 // LITE_RUNTIME implements this at the GeneratedMessageLite level.
1346 printer->Print(
1347 "public Builder mergeFrom(\n"
1348 " com.google.protobuf.CodedInputStream input,\n"
1349 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
1350 " throws java.io.IOException {\n"
1351 " $classname$ parsedMessage = null;\n"
1352 " try {\n"
1353 " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n"
1354 " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
1355 " parsedMessage = ($classname$) e.getUnfinishedMessage();\n"
1356 " throw e;\n"
1357 " } finally {\n"
1358 " if (parsedMessage != null) {\n"
1359 " mergeFrom(parsedMessage);\n"
1360 " }\n"
1361 " }\n"
1362 " return this;\n"
1363 "}\n",
1364 "classname", name_resolver_->GetImmutableClassName(descriptor_));
1365 }
1366}
1367
1368// ===================================================================
1369
jieluo@google.com4de8f552014-07-18 00:47:59 +00001370void ImmutableMessageGenerator::GenerateIsInitialized(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001371 io::Printer* printer, UseMemoization useMemoization) {
Jisi Liu885b6122015-02-28 14:51:22 -08001372 // LITE_RUNTIME avoids generating isInitialized if it's not needed.
1373 if (!HasDescriptorMethods(descriptor_)
1374 && !HasRequiredFields(descriptor_)) {
1375 return;
1376 }
1377
liujisi@google.com33165fe2010-11-02 13:14:58 +00001378 bool memoization = useMemoization == MEMOIZE;
1379 if (memoization) {
1380 // Memoizes whether the protocol buffer is fully initialized (has all
1381 // required fields). -1 means not yet computed. 0 means false and 1 means
1382 // true.
1383 printer->Print(
1384 "private byte memoizedIsInitialized = -1;\n");
1385 }
temporal40ee5512008-07-10 02:12:20 +00001386 printer->Print(
temporal40ee5512008-07-10 02:12:20 +00001387 "public final boolean isInitialized() {\n");
1388 printer->Indent();
1389
liujisi@google.com33165fe2010-11-02 13:14:58 +00001390 if (memoization) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001391 // Don't directly compare to -1 to avoid an Android x86 JIT bug.
liujisi@google.com33165fe2010-11-02 13:14:58 +00001392 printer->Print(
1393 "byte isInitialized = memoizedIsInitialized;\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00001394 "if (isInitialized == 1) return true;\n"
1395 "if (isInitialized == 0) return false;\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001396 "\n");
1397 }
1398
temporal40ee5512008-07-10 02:12:20 +00001399 // Check that all required fields in this message are set.
1400 // TODO(kenton): We can optimize this when we switch to putting all the
1401 // "has" fields into a single bitfield.
1402 for (int i = 0; i < descriptor_->field_count(); i++) {
1403 const FieldDescriptor* field = descriptor_->field(i);
jieluo@google.com4de8f552014-07-18 00:47:59 +00001404 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
temporal40ee5512008-07-10 02:12:20 +00001405
1406 if (field->is_required()) {
1407 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001408 "if (!has$name$()) {\n"
1409 " $memoize$\n"
1410 " return false;\n"
1411 "}\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001412 "name", info->capitalized_name,
liujisi@google.com33165fe2010-11-02 13:14:58 +00001413 "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
temporal40ee5512008-07-10 02:12:20 +00001414 }
1415 }
1416
1417 // Now check that all embedded messages are initialized.
1418 for (int i = 0; i < descriptor_->field_count(); i++) {
1419 const FieldDescriptor* field = descriptor_->field(i);
jieluo@google.com4de8f552014-07-18 00:47:59 +00001420 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
kenton@google.comfccb1462009-12-18 02:11:36 +00001421 if (GetJavaType(field) == JAVATYPE_MESSAGE &&
temporal40ee5512008-07-10 02:12:20 +00001422 HasRequiredFields(field->message_type())) {
1423 switch (field->label()) {
1424 case FieldDescriptor::LABEL_REQUIRED:
1425 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001426 "if (!get$name$().isInitialized()) {\n"
1427 " $memoize$\n"
1428 " return false;\n"
1429 "}\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001430 "type", name_resolver_->GetImmutableClassName(
1431 field->message_type()),
1432 "name", info->capitalized_name,
liujisi@google.com33165fe2010-11-02 13:14:58 +00001433 "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
temporal40ee5512008-07-10 02:12:20 +00001434 break;
1435 case FieldDescriptor::LABEL_OPTIONAL:
Feng Xiao6ef984a2014-11-10 17:34:54 -08001436 if (!SupportFieldPresence(descriptor_->file()) &&
1437 field->containing_oneof() != NULL) {
1438 const OneofDescriptor* oneof = field->containing_oneof();
1439 const OneofGeneratorInfo* oneof_info =
1440 context_->GetOneofGeneratorInfo(oneof);
1441 printer->Print(
1442 "if ($oneof_name$Case_ == $field_number$) {\n",
1443 "oneof_name", oneof_info->name,
1444 "field_number", SimpleItoa(field->number()));
1445 } else {
1446 printer->Print(
1447 "if (has$name$()) {\n",
1448 "name", info->capitalized_name);
1449 }
temporal40ee5512008-07-10 02:12:20 +00001450 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001451 " if (!get$name$().isInitialized()) {\n"
1452 " $memoize$\n"
1453 " return false;\n"
1454 " }\n"
temporal40ee5512008-07-10 02:12:20 +00001455 "}\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001456 "name", info->capitalized_name,
liujisi@google.com33165fe2010-11-02 13:14:58 +00001457 "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
temporal40ee5512008-07-10 02:12:20 +00001458 break;
1459 case FieldDescriptor::LABEL_REPEATED:
Feng Xiaof157a562014-11-14 11:50:31 -08001460 if (IsMapEntry(field->message_type())) {
1461 printer->Print(
1462 "for ($type$ item : get$name$().values()) {\n"
1463 " if (!item.isInitialized()) {\n"
1464 " $memoize$\n"
1465 " return false;\n"
1466 " }\n"
1467 "}\n",
1468 "type", MapValueImmutableClassdName(field->message_type(),
1469 name_resolver_),
1470 "name", info->capitalized_name,
1471 "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
1472 } else {
1473 printer->Print(
1474 "for (int i = 0; i < get$name$Count(); i++) {\n"
1475 " if (!get$name$(i).isInitialized()) {\n"
1476 " $memoize$\n"
1477 " return false;\n"
1478 " }\n"
1479 "}\n",
1480 "type", name_resolver_->GetImmutableClassName(
1481 field->message_type()),
1482 "name", info->capitalized_name,
1483 "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
1484 }
temporal40ee5512008-07-10 02:12:20 +00001485 break;
1486 }
1487 }
1488 }
1489
1490 if (descriptor_->extension_range_count() > 0) {
1491 printer->Print(
liujisi@google.com33165fe2010-11-02 13:14:58 +00001492 "if (!extensionsAreInitialized()) {\n"
1493 " $memoize$\n"
1494 " return false;\n"
1495 "}\n",
1496 "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
temporal40ee5512008-07-10 02:12:20 +00001497 }
1498
1499 printer->Outdent();
liujisi@google.com33165fe2010-11-02 13:14:58 +00001500
1501 if (memoization) {
1502 printer->Print(
1503 " memoizedIsInitialized = 1;\n");
1504 }
1505
temporal40ee5512008-07-10 02:12:20 +00001506 printer->Print(
1507 " return true;\n"
1508 "}\n"
1509 "\n");
1510}
1511
kenton@google.com24bf56f2008-09-24 20:31:01 +00001512// ===================================================================
1513
jieluo@google.com4de8f552014-07-18 00:47:59 +00001514namespace {
1515bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) {
1516 if (field->is_repeated()) {
1517 return false;
1518 }
1519 if (SupportFieldPresence(field->file())) {
1520 return true;
1521 }
1522 return GetJavaType(field) == JAVATYPE_MESSAGE &&
1523 field->containing_oneof() == NULL;
1524}
1525} // namespace
1526
1527void ImmutableMessageGenerator::
1528GenerateEqualsAndHashCode(io::Printer* printer) {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001529 printer->Print(
1530 "@java.lang.Override\n"
liujisi@google.com9cf65b72011-04-08 03:40:29 +00001531 "public boolean equals(final java.lang.Object obj) {\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +00001532 printer->Indent();
1533 printer->Print(
1534 "if (obj == this) {\n"
1535 " return true;\n"
1536 "}\n"
1537 "if (!(obj instanceof $classname$)) {\n"
1538 " return super.equals(obj);\n"
1539 "}\n"
1540 "$classname$ other = ($classname$) obj;\n"
1541 "\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001542 "classname", name_resolver_->GetImmutableClassName(descriptor_));
liujisi@google.com33165fe2010-11-02 13:14:58 +00001543
1544 printer->Print("boolean result = true;\n");
1545 for (int i = 0; i < descriptor_->field_count(); i++) {
1546 const FieldDescriptor* field = descriptor_->field(i);
jieluo@google.com4de8f552014-07-18 00:47:59 +00001547 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
1548 bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
1549 if (check_has_bits) {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001550 printer->Print(
1551 "result = result && (has$name$() == other.has$name$());\n"
1552 "if (has$name$()) {\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001553 "name", info->capitalized_name);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001554 printer->Indent();
1555 }
1556 field_generators_.get(field).GenerateEqualsCode(printer);
jieluo@google.com4de8f552014-07-18 00:47:59 +00001557 if (check_has_bits) {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001558 printer->Outdent();
1559 printer->Print(
1560 "}\n");
1561 }
1562 }
Feng Xiao6ef984a2014-11-10 17:34:54 -08001563 if (PreserveUnknownFields(descriptor_)) {
1564 // Always consider unknown fields for equality. This will sometimes return
1565 // false for non-canonical ordering when running in LITE_RUNTIME but it's
1566 // the best we can do.
liujisi@google.com33165fe2010-11-02 13:14:58 +00001567 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -08001568 "result = result && unknownFields.equals(other.unknownFields);\n");
1569 }
1570 if (HasDescriptorMethods(descriptor_)) {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001571 if (descriptor_->extension_range_count() > 0) {
1572 printer->Print(
1573 "result = result &&\n"
1574 " getExtensionFields().equals(other.getExtensionFields());\n");
1575 }
1576 }
1577 printer->Print(
1578 "return result;\n");
1579 printer->Outdent();
1580 printer->Print(
1581 "}\n"
1582 "\n");
1583
1584 printer->Print(
1585 "@java.lang.Override\n"
1586 "public int hashCode() {\n");
1587 printer->Indent();
1588 printer->Print(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001589 "if (memoizedHashCode != 0) {\n");
1590 printer->Indent();
1591 printer->Print(
1592 "return memoizedHashCode;\n");
1593 printer->Outdent();
1594 printer->Print(
1595 "}\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00001596 "int hash = 41;\n");
1597
1598 if (HasDescriptorMethods(descriptor_)) {
1599 printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
1600 } else {
1601 // Include the hash of the class so that two objects with different types
1602 // but the same field values will probably have different hashes.
1603 printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n",
1604 "classname", name_resolver_->GetImmutableClassName(descriptor_));
1605 }
1606
liujisi@google.com33165fe2010-11-02 13:14:58 +00001607 for (int i = 0; i < descriptor_->field_count(); i++) {
1608 const FieldDescriptor* field = descriptor_->field(i);
jieluo@google.com4de8f552014-07-18 00:47:59 +00001609 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
1610 bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
1611 if (check_has_bits) {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001612 printer->Print(
1613 "if (has$name$()) {\n",
jieluo@google.com4de8f552014-07-18 00:47:59 +00001614 "name", info->capitalized_name);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001615 printer->Indent();
1616 }
1617 field_generators_.get(field).GenerateHashCode(printer);
jieluo@google.com4de8f552014-07-18 00:47:59 +00001618 if (check_has_bits) {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001619 printer->Outdent();
1620 printer->Print("}\n");
1621 }
1622 }
1623 if (HasDescriptorMethods(descriptor_)) {
1624 if (descriptor_->extension_range_count() > 0) {
1625 printer->Print(
1626 "hash = hashFields(hash, getExtensionFields());\n");
1627 }
1628 }
jieluo@google.com4de8f552014-07-18 00:47:59 +00001629
Feng Xiao6ef984a2014-11-10 17:34:54 -08001630 printer->Print(
1631 "hash = (29 * hash) + unknownFields.hashCode();\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +00001632 printer->Print(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001633 "memoizedHashCode = hash;\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001634 "return hash;\n");
1635 printer->Outdent();
1636 printer->Print(
1637 "}\n"
1638 "\n");
1639}
1640
1641// ===================================================================
1642
jieluo@google.com4de8f552014-07-18 00:47:59 +00001643void ImmutableMessageGenerator::
1644GenerateExtensionRegistrationCode(io::Printer* printer) {
kenton@google.com24bf56f2008-09-24 20:31:01 +00001645 for (int i = 0; i < descriptor_->extension_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001646 ImmutableExtensionGenerator(descriptor_->extension(i), context_)
kenton@google.com24bf56f2008-09-24 20:31:01 +00001647 .GenerateRegistrationCode(printer);
1648 }
1649
1650 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001651 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
kenton@google.com24bf56f2008-09-24 20:31:01 +00001652 .GenerateExtensionRegistrationCode(printer);
1653 }
1654}
1655
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001656// ===================================================================
jieluo@google.com4de8f552014-07-18 00:47:59 +00001657void ImmutableMessageGenerator::
1658GenerateParsingConstructor(io::Printer* printer) {
Feng Xiaof157a562014-11-14 11:50:31 -08001659 google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001660 SortFieldsByNumber(descriptor_));
1661
1662 printer->Print(
1663 "private $classname$(\n"
1664 " com.google.protobuf.CodedInputStream input,\n"
Jisi Liu885b6122015-02-28 14:51:22 -08001665 " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n",
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001666 "classname", descriptor_->name());
1667 printer->Indent();
1668
1669 // Initialize all fields to default.
Feng Xiao99aa0f92014-11-20 16:18:53 -08001670 if (HasDescriptorMethods(descriptor_)) {
1671 printer->Print(
1672 "this();\n");
1673 } else {
1674 // LITE_RUNTIME only has one constructor.
1675 GenerateInitializers(printer);
1676 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001677
1678 // Use builder bits to track mutable repeated fields.
1679 int totalBuilderBits = 0;
1680 for (int i = 0; i < descriptor_->field_count(); i++) {
jieluo@google.com4de8f552014-07-18 00:47:59 +00001681 const ImmutableFieldGenerator& field =
1682 field_generators_.get(descriptor_->field(i));
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001683 totalBuilderBits += field.GetNumBitsForBuilder();
1684 }
1685 int totalBuilderInts = (totalBuilderBits + 31) / 32;
1686 for (int i = 0; i < totalBuilderInts; i++) {
1687 printer->Print("int mutable_$bit_field_name$ = 0;\n",
1688 "bit_field_name", GetBitFieldName(i));
1689 }
1690
Feng Xiao6ef984a2014-11-10 17:34:54 -08001691 if (PreserveUnknownFields(descriptor_)) {
1692 if (HasDescriptorMethods(descriptor_)) {
1693 printer->Print(
1694 "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
1695 " com.google.protobuf.UnknownFieldSet.newBuilder();\n");
1696 } else {
1697 printer->Print(
1698 "com.google.protobuf.UnknownFieldSetLite.Builder unknownFields =\n"
1699 " com.google.protobuf.UnknownFieldSetLite.newBuilder();\n");
1700 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001701 }
1702
1703 printer->Print(
1704 "try {\n");
1705 printer->Indent();
1706
1707 printer->Print(
1708 "boolean done = false;\n"
1709 "while (!done) {\n");
1710 printer->Indent();
1711
1712 printer->Print(
1713 "int tag = input.readTag();\n"
1714 "switch (tag) {\n");
1715 printer->Indent();
1716
1717 printer->Print(
1718 "case 0:\n" // zero signals EOF / limit reached
1719 " done = true;\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -08001720 " break;\n");
1721
1722 if (PreserveUnknownFields(descriptor_)) {
1723 if (!HasDescriptorMethods(descriptor_)
1724 && descriptor_->extension_range_count() > 0) {
1725 // Lite runtime directly invokes parseUnknownField to reduce method
1726 // counts.
1727 printer->Print(
1728 "default: {\n"
1729 " if (!parseUnknownField(extensions, getDefaultInstanceForType(),\n"
1730 " input, unknownFields,\n"
1731 " extensionRegistry, tag)) {\n"
1732 " done = true;\n" // it's an endgroup tag
1733 " }\n"
1734 " break;\n"
1735 "}\n");
1736 } else {
1737 printer->Print(
1738 "default: {\n"
1739 " if (!parseUnknownField(input, unknownFields,\n"
1740 " extensionRegistry, tag)) {\n"
1741 " done = true;\n" // it's an endgroup tag
1742 " }\n"
1743 " break;\n"
1744 "}\n");
1745 }
1746 } else {
1747 printer->Print(
1748 "default: {\n"
1749 " if (!input.skipField(tag)) {\n"
1750 " done = true;\n" // it's an endgroup tag
1751 " }\n"
1752 " break;\n"
1753 "}\n");
1754 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001755
1756 for (int i = 0; i < descriptor_->field_count(); i++) {
1757 const FieldDescriptor* field = sorted_fields[i];
1758 uint32 tag = WireFormatLite::MakeTag(field->number(),
1759 WireFormat::WireTypeForFieldType(field->type()));
1760
1761 printer->Print(
1762 "case $tag$: {\n",
1763 "tag", SimpleItoa(tag));
1764 printer->Indent();
1765
1766 field_generators_.get(field).GenerateParsingCode(printer);
1767
1768 printer->Outdent();
1769 printer->Print(
1770 " break;\n"
1771 "}\n");
1772
1773 if (field->is_packable()) {
1774 // To make packed = true wire compatible, we generate parsing code from a
1775 // packed version of this field regardless of field->options().packed().
1776 uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
1777 WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
1778 printer->Print(
1779 "case $tag$: {\n",
1780 "tag", SimpleItoa(packed_tag));
1781 printer->Indent();
1782
1783 field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
1784
1785 printer->Outdent();
1786 printer->Print(
1787 " break;\n"
1788 "}\n");
1789 }
1790 }
1791
1792 printer->Outdent();
1793 printer->Outdent();
1794 printer->Print(
1795 " }\n" // switch (tag)
1796 "}\n"); // while (!done)
1797
1798 printer->Outdent();
1799 printer->Print(
1800 "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
Jisi Liu885b6122015-02-28 14:51:22 -08001801 " throw new RuntimeException(e.setUnfinishedMessage(this));\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001802 "} catch (java.io.IOException e) {\n"
Jisi Liu885b6122015-02-28 14:51:22 -08001803 " throw new RuntimeException(\n"
1804 " new com.google.protobuf.InvalidProtocolBufferException(\n"
1805 " e.getMessage()).setUnfinishedMessage(this));\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001806 "} finally {\n");
1807 printer->Indent();
1808
1809 // Make repeated field list immutable.
1810 for (int i = 0; i < descriptor_->field_count(); i++) {
1811 const FieldDescriptor* field = sorted_fields[i];
1812 field_generators_.get(field).GenerateParsingDoneCode(printer);
1813 }
1814
Feng Xiao6ef984a2014-11-10 17:34:54 -08001815 if (PreserveUnknownFields(descriptor_)) {
1816 // Make unknown fields immutable.
1817 printer->Print("this.unknownFields = unknownFields.build();\n");
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001818 }
1819
Feng Xiaof157a562014-11-14 11:50:31 -08001820 if (!HasDescriptorMethods(descriptor_)) {
1821 // LITE runtime uses a static method to reduce method count.
1822 if (descriptor_->extension_range_count() > 0) {
1823 // Make extensions immutable.
1824 printer->Print(
1825 "makeExtensionsImmutable(extensions);\n");
1826 }
1827 } else {
1828 // Make extensions immutable.
1829 printer->Print(
1830 "makeExtensionsImmutable();\n");
1831 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001832
1833 printer->Outdent();
1834 printer->Outdent();
1835 printer->Print(
1836 " }\n" // finally
1837 "}\n");
1838}
1839
1840// ===================================================================
jieluo@google.com4de8f552014-07-18 00:47:59 +00001841void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001842 printer->Print(
Feng Xiao6ef984a2014-11-10 17:34:54 -08001843 "public static final com.google.protobuf.Parser<$classname$> PARSER =\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001844 " new com.google.protobuf.AbstractParser<$classname$>() {\n",
1845 "classname", descriptor_->name());
1846 printer->Indent();
1847 printer->Print(
1848 "public $classname$ parsePartialFrom(\n"
1849 " com.google.protobuf.CodedInputStream input,\n"
1850 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
1851 " throws com.google.protobuf.InvalidProtocolBufferException {\n",
1852 "classname", descriptor_->name());
1853 if (HasGeneratedMethods(descriptor_)) {
Jisi Liu885b6122015-02-28 14:51:22 -08001854 // The parsing constructor throws an InvalidProtocolBufferException via a
1855 // RuntimeException to aid in method pruning. We unwrap it here.
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001856 printer->Print(
Jisi Liu885b6122015-02-28 14:51:22 -08001857 " try {\n"
1858 " return new $classname$(input, extensionRegistry);\n"
1859 " } catch (RuntimeException e) {\n"
1860 " if (e.getCause() instanceof\n"
1861 " com.google.protobuf.InvalidProtocolBufferException) {\n"
1862 " throw (com.google.protobuf.InvalidProtocolBufferException)\n"
1863 " e.getCause();\n"
1864 " }\n"
1865 " throw e;\n"
1866 " }\n",
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001867 "classname", descriptor_->name());
1868 } else {
1869 // When parsing constructor isn't generated, use builder to parse messages.
1870 // Note, will fallback to use reflection based mergeFieldFrom() in
1871 // AbstractMessage.Builder.
1872 printer->Indent();
1873 printer->Print(
1874 "Builder builder = newBuilder();\n"
1875 "try {\n"
1876 " builder.mergeFrom(input, extensionRegistry);\n"
1877 "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
1878 " throw e.setUnfinishedMessage(builder.buildPartial());\n"
1879 "} catch (java.io.IOException e) {\n"
1880 " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
1881 " e.getMessage()).setUnfinishedMessage(builder.buildPartial());\n"
1882 "}\n"
1883 "return builder.buildPartial();\n");
1884 printer->Outdent();
1885 }
1886 printer->Print(
1887 "}\n");
1888 printer->Outdent();
1889 printer->Print(
1890 "};\n"
1891 "\n");
1892
Jisi Liu885b6122015-02-28 14:51:22 -08001893 if (HasDescriptorMethods(descriptor_)) {
1894 // LITE_RUNTIME implements this at the GeneratedMessageLite level.
1895 printer->Print(
1896 "@java.lang.Override\n"
1897 "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
1898 " return PARSER;\n"
1899 "}\n"
1900 "\n",
1901 "classname", descriptor_->name());
1902 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001903}
1904
Feng Xiao99aa0f92014-11-20 16:18:53 -08001905// ===================================================================
1906void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) {
1907 for (int i = 0; i < descriptor_->field_count(); i++) {
1908 if (!descriptor_->field(i)->containing_oneof()) {
1909 field_generators_.get(descriptor_->field(i))
1910 .GenerateInitializationCode(printer);
1911 }
1912 }
1913}
1914
jieluo@google.com4de8f552014-07-18 00:47:59 +00001915
temporal40ee5512008-07-10 02:12:20 +00001916} // namespace java
1917} // namespace compiler
1918} // namespace protobuf
1919} // namespace google