temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1 | // Protocol Buffers - Google's data interchange format |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 2 | // Copyright 2008 Google Inc. All rights reserved. |
Feng Xiao | e428862 | 2014-10-01 16:26:23 -0700 | [diff] [blame] | 3 | // https://developers.google.com/protocol-buffers/ |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 4 | // |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 5 | // Redistribution and use in source and binary forms, with or without |
| 6 | // modification, are permitted provided that the following conditions are |
| 7 | // met: |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 8 | // |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 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. |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 18 | // |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 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. |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 30 | |
| 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.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 35 | #include <google/protobuf/compiler/java/java_message.h> |
| 36 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 37 | #include <algorithm> |
| 38 | #include <google/protobuf/stubs/hash.h> |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 39 | #include <map> |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 40 | #include <memory> |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 41 | #ifndef _SHARED_PTR_H |
| 42 | #include <google/protobuf/stubs/shared_ptr.h> |
| 43 | #endif |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 44 | #include <vector> |
| 45 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 46 | #include <google/protobuf/compiler/java/java_context.h> |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 47 | #include <google/protobuf/compiler/java/java_doc_comment.h> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 48 | #include <google/protobuf/compiler/java/java_enum.h> |
| 49 | #include <google/protobuf/compiler/java/java_extension.h> |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 50 | #include <google/protobuf/compiler/java/java_generator_factory.h> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 51 | #include <google/protobuf/compiler/java/java_helpers.h> |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 52 | #include <google/protobuf/compiler/java/java_name_resolver.h> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 53 | #include <google/protobuf/io/coded_stream.h> |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 54 | #include <google/protobuf/io/printer.h> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 55 | #include <google/protobuf/descriptor.pb.h> |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 56 | #include <google/protobuf/wire_format.h> |
| 57 | #include <google/protobuf/stubs/strutil.h> |
| 58 | #include <google/protobuf/stubs/substitute.h> |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 59 | |
| 60 | namespace google { |
| 61 | namespace protobuf { |
| 62 | namespace compiler { |
| 63 | namespace java { |
| 64 | |
| 65 | using internal::WireFormat; |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 66 | using internal::WireFormatLite; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 67 | |
| 68 | namespace { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 69 | bool GenerateHasBits(const Descriptor* descriptor) { |
| 70 | return SupportFieldPresence(descriptor->file()) || |
| 71 | HasRepeatedFields(descriptor); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 72 | } |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 73 | |
| 74 | string 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 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 80 | } // namespace |
| 81 | |
| 82 | // =================================================================== |
| 83 | |
| 84 | MessageGenerator::MessageGenerator(const Descriptor* descriptor) |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 85 | : descriptor_(descriptor) {} |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 86 | |
| 87 | MessageGenerator::~MessageGenerator() {} |
| 88 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 89 | // =================================================================== |
| 90 | // TODO(api): Move this class to a separate immutable_message.cc file. |
| 91 | ImmutableMessageGenerator::ImmutableMessageGenerator( |
| 92 | const Descriptor* descriptor, Context* context) |
| 93 | : MessageGenerator(descriptor), context_(context), |
| 94 | name_resolver_(context->GetNameResolver()), |
| 95 | field_generators_(descriptor, context_) { |
| 96 | } |
| 97 | |
| 98 | ImmutableMessageGenerator::~ImmutableMessageGenerator() {} |
| 99 | |
| 100 | void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 101 | 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. |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 108 | |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 109 | map<string, string> vars; |
| 110 | vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); |
| 111 | vars["index"] = SimpleItoa(descriptor_->index()); |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 112 | vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 113 | if (descriptor_->containing_type() != NULL) { |
| 114 | vars["parent"] = UniqueFileScopeIdentifier( |
| 115 | descriptor_->containing_type()); |
| 116 | } |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 117 | if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 118 | // 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 127 | "$private$static final com.google.protobuf.Descriptors.Descriptor\n" |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 128 | " internal_$identifier$_descriptor;\n"); |
| 129 | |
| 130 | // And the FieldAccessorTable. |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 131 | GenerateFieldAccessorTable(printer); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 132 | } |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 133 | |
| 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 137 | ImmutableMessageGenerator(descriptor_->nested_type(i), context_) |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 138 | .GenerateStaticVariables(printer); |
| 139 | } |
| 140 | } |
| 141 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 142 | void ImmutableMessageGenerator::GenerateStaticVariableInitializers( |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 143 | io::Printer* printer) { |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 144 | if (HasDescriptorMethods(descriptor_)) { |
| 145 | map<string, string> vars; |
| 146 | vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); |
| 147 | vars["index"] = SimpleItoa(descriptor_->index()); |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 148 | vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 149 | if (descriptor_->containing_type() != NULL) { |
| 150 | vars["parent"] = UniqueFileScopeIdentifier( |
| 151 | descriptor_->containing_type()); |
| 152 | } |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 153 | |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 154 | // 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.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 164 | |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 165 | // And the FieldAccessorTable. |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 166 | GenerateFieldAccessorTableInitializer(printer); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 167 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 168 | |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 169 | // Generate static member initializers for all nested types. |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 170 | for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
| 171 | // TODO(kenton): Reuse MessageGenerator objects? |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 172 | ImmutableMessageGenerator(descriptor_->nested_type(i), context_) |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 173 | .GenerateStaticVariableInitializers(printer); |
| 174 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 175 | } |
| 176 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 177 | void ImmutableMessageGenerator:: |
| 178 | GenerateFieldAccessorTable(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 | |
| 194 | void ImmutableMessageGenerator:: |
| 195 | GenerateFieldAccessorTableInitializer(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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 220 | // =================================================================== |
| 221 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 222 | void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 223 | if (descriptor_->extension_range_count() > 0) { |
| 224 | if (HasDescriptorMethods(descriptor_)) { |
| 225 | printer->Print( |
| 226 | "public interface $classname$OrBuilder extends\n" |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 227 | " $extra_interfaces$\n" |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 228 | " com.google.protobuf.GeneratedMessage.\n" |
| 229 | " ExtendableMessageOrBuilder<$classname$> {\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 230 | "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 231 | "classname", descriptor_->name()); |
| 232 | } else { |
| 233 | printer->Print( |
| 234 | "public interface $classname$OrBuilder extends \n" |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 235 | " $extra_interfaces$\n" |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 236 | " com.google.protobuf.GeneratedMessageLite.\n" |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 237 | " ExtendableMessageOrBuilder<\n" |
| 238 | " $classname$, $classname$.Builder> {\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 239 | "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 240 | "classname", descriptor_->name()); |
| 241 | } |
| 242 | } else { |
| 243 | if (HasDescriptorMethods(descriptor_)) { |
| 244 | printer->Print( |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 245 | "public interface $classname$OrBuilder extends\n" |
| 246 | " $extra_interfaces$\n" |
| 247 | " com.google.protobuf.MessageOrBuilder {\n", |
| 248 | "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 249 | "classname", descriptor_->name()); |
| 250 | } else { |
| 251 | printer->Print( |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 252 | "public interface $classname$OrBuilder extends\n" |
| 253 | " $extra_interfaces$\n" |
| 254 | " com.google.protobuf.MessageLiteOrBuilder {\n", |
| 255 | "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 256 | "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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 263 | field_generators_.get(descriptor_->field(i)) |
| 264 | .GenerateInterfaceMembers(printer); |
| 265 | } |
| 266 | printer->Outdent(); |
| 267 | |
| 268 | printer->Print("}\n"); |
| 269 | } |
| 270 | |
| 271 | // =================================================================== |
| 272 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 273 | void ImmutableMessageGenerator::Generate(io::Printer* printer) { |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 274 | bool is_own_file = |
| 275 | descriptor_->containing_type() == NULL && |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 276 | MultipleJavaFiles(descriptor_->file(), /* immutable = */ true); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 277 | |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 278 | 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.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 284 | WriteMessageDocComment(printer, descriptor_); |
| 285 | |
| 286 | // The builder_type stores the super type name of the nested Builder class. |
| 287 | string builder_type; |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 288 | if (descriptor_->extension_range_count() > 0) { |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 289 | 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 Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 304 | builder_type = strings::Substitute( |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 305 | "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>", |
| 306 | name_resolver_->GetImmutableClassName(descriptor_), |
| 307 | variables["lite"]); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 308 | } else { |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 309 | 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 Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 324 | builder_type = strings::Substitute( |
| 325 | "com.google.protobuf.GeneratedMessage$0.Builder", |
| 326 | variables["lite"]); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 327 | } |
| 328 | printer->Indent(); |
Feng Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 329 | 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 Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 350 | } |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 351 | |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 352 | if (HasDescriptorMethods(descriptor_)) { |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 353 | printer->Print( |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 354 | "@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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 364 | printer->Print( |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 365 | "}\n"); |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 366 | } |
| 367 | |
| 368 | if (HasGeneratedMethods(descriptor_)) { |
| 369 | GenerateParsingConstructor(printer); |
| 370 | } |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 371 | |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 372 | GenerateDescriptorMethods(printer, false); |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 373 | GenerateParser(printer); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 374 | |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 375 | // Nested types |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 376 | for (int i = 0; i < descriptor_->enum_type_count(); i++) { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 377 | EnumGenerator(descriptor_->enum_type(i), true, context_) |
| 378 | .Generate(printer); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 379 | } |
| 380 | |
| 381 | for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 382 | // Don't generate Java classes for map entry messages. |
| 383 | if (IsMapEntry(descriptor_->nested_type(i))) continue; |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 384 | ImmutableMessageGenerator messageGenerator( |
| 385 | descriptor_->nested_type(i), context_); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 386 | messageGenerator.GenerateInterface(printer); |
| 387 | messageGenerator.Generate(printer); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 388 | } |
| 389 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 390 | 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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 402 | } |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 403 | |
| 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"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 471 | } |
| 472 | |
| 473 | // Fields |
| 474 | for (int i = 0; i < descriptor_->field_count(); i++) { |
kenton@google.com | cfa2d8a | 2009-04-18 00:02:12 +0000 | [diff] [blame] | 475 | printer->Print("public static final int $constant_name$ = $number$;\n", |
| 476 | "constant_name", FieldConstantName(descriptor_->field(i)), |
| 477 | "number", SimpleItoa(descriptor_->field(i)->number())); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 478 | field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); |
| 479 | printer->Print("\n"); |
| 480 | } |
| 481 | |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 482 | if (HasGeneratedMethods(descriptor_)) { |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 483 | GenerateIsInitialized(printer, MEMOIZE); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 484 | GenerateMessageSerializationMethods(printer); |
| 485 | } |
| 486 | |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 487 | if (HasEqualsAndHashCode(descriptor_)) { |
| 488 | GenerateEqualsAndHashCode(printer); |
| 489 | } |
| 490 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 491 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 492 | GenerateParseFromMethods(printer); |
| 493 | GenerateBuilder(printer); |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 494 | |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 495 | printer->Print( |
| 496 | "\n" |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 497 | "// @@protoc_insertion_point(class_scope:$full_name$)\n", |
| 498 | "full_name", descriptor_->full_name()); |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 499 | |
Feng Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 500 | |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 501 | // Carefully initialize the default instance in such a way that it doesn't |
| 502 | // conflict with other initialization. |
Feng Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 503 | printer->Print( |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 504 | "private static final $classname$ defaultInstance;\n", |
Feng Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 505 | "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 Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 517 | " 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 Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 522 | "}\n" |
| 523 | "\n", |
| 524 | "classname", descriptor_->name()); |
| 525 | } |
| 526 | printer->Print( |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 527 | "public static $classname$ getDefaultInstance() {\n" |
| 528 | " return defaultInstance;\n" |
| 529 | "}\n" |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 530 | "\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 Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 536 | "public $classname$ getDefaultInstanceForType() {\n" |
| 537 | " return defaultInstance;\n" |
| 538 | "}\n" |
| 539 | "\n", |
Feng Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 540 | "classname", name_resolver_->GetImmutableClassName(descriptor_)); |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 541 | } 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 Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 554 | |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 555 | // 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 559 | ImmutableExtensionGenerator(descriptor_->extension(i), context_) |
| 560 | .Generate(printer); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 561 | } |
| 562 | |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 563 | // 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.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 576 | printer->Outdent(); |
| 577 | printer->Print("}\n\n"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 578 | } |
| 579 | |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 580 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 581 | // =================================================================== |
| 582 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 583 | void ImmutableMessageGenerator:: |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 584 | GenerateMessageSerializationMethods(io::Printer* printer) { |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 585 | google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields( |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 586 | SortFieldsByNumber(descriptor_)); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 587 | |
| 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 Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 592 | std::sort(sorted_extensions.begin(), sorted_extensions.end(), |
| 593 | ExtensionRangeOrdering()); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 594 | |
| 595 | printer->Print( |
| 596 | "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" |
| 597 | " throws java.io.IOException {\n"); |
| 598 | printer->Indent(); |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 599 | 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 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 609 | |
| 610 | if (descriptor_->extension_range_count() > 0) { |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 611 | if (descriptor_->options().message_set_wire_format()) { |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 612 | 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.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 626 | } else { |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 627 | 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.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 641 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 642 | } |
| 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 Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 659 | if (PreserveUnknownFields(descriptor_)) { |
| 660 | if (descriptor_->options().message_set_wire_format() |
| 661 | && HasDescriptorMethods(descriptor_)) { |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 662 | printer->Print( |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 663 | "unknownFields.writeAsMessageSetTo(output);\n"); |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 664 | } else { |
| 665 | printer->Print( |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 666 | "unknownFields.writeTo(output);\n"); |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 667 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 668 | } |
| 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.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 687 | if (descriptor_->options().message_set_wire_format()) { |
| 688 | printer->Print( |
| 689 | "size += extensionsSerializedSizeAsMessageSet();\n"); |
| 690 | } else { |
| 691 | printer->Print( |
| 692 | "size += extensionsSerializedSize();\n"); |
| 693 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 694 | } |
| 695 | |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 696 | if (PreserveUnknownFields(descriptor_)) { |
| 697 | if (descriptor_->options().message_set_wire_format() |
| 698 | && HasDescriptorMethods(descriptor_)) { |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 699 | printer->Print( |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 700 | "size += unknownFields.getSerializedSizeAsMessageSet();\n"); |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 701 | } else { |
| 702 | printer->Print( |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 703 | "size += unknownFields.getSerializedSize();\n"); |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 704 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 705 | } |
| 706 | |
| 707 | printer->Outdent(); |
| 708 | printer->Print( |
| 709 | " memoizedSerializedSize = size;\n" |
| 710 | " return size;\n" |
| 711 | "}\n" |
| 712 | "\n"); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 713 | |
| 714 | printer->Print( |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 715 | "private static final long serialVersionUID = 0L;\n"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 716 | } |
| 717 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 718 | void ImmutableMessageGenerator:: |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 719 | GenerateParseFromMethods(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.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 727 | " return PARSER.parseFrom(data);\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 728 | "}\n" |
| 729 | "public static $classname$ parseFrom(\n" |
| 730 | " com.google.protobuf.ByteString data,\n" |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 731 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 732 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 733 | " return PARSER.parseFrom(data, extensionRegistry);\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 734 | "}\n" |
| 735 | "public static $classname$ parseFrom(byte[] data)\n" |
| 736 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 737 | " return PARSER.parseFrom(data);\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 738 | "}\n" |
| 739 | "public static $classname$ parseFrom(\n" |
| 740 | " byte[] data,\n" |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 741 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 742 | " throws com.google.protobuf.InvalidProtocolBufferException {\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 743 | " return PARSER.parseFrom(data, extensionRegistry);\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 744 | "}\n" |
| 745 | "public static $classname$ parseFrom(java.io.InputStream input)\n" |
| 746 | " throws java.io.IOException {\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 747 | " return PARSER.parseFrom(input);\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 748 | "}\n" |
| 749 | "public static $classname$ parseFrom(\n" |
| 750 | " java.io.InputStream input,\n" |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 751 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 752 | " throws java.io.IOException {\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 753 | " return PARSER.parseFrom(input, extensionRegistry);\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 754 | "}\n" |
kenton@google.com | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 755 | "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n" |
| 756 | " throws java.io.IOException {\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 757 | " return PARSER.parseDelimitedFrom(input);\n" |
kenton@google.com | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 758 | "}\n" |
| 759 | "public static $classname$ parseDelimitedFrom(\n" |
| 760 | " java.io.InputStream input,\n" |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 761 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
kenton@google.com | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 762 | " throws java.io.IOException {\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 763 | " return PARSER.parseDelimitedFrom(input, extensionRegistry);\n" |
kenton@google.com | d37d46d | 2009-04-25 02:53:47 +0000 | [diff] [blame] | 764 | "}\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 765 | "public static $classname$ parseFrom(\n" |
| 766 | " com.google.protobuf.CodedInputStream input)\n" |
| 767 | " throws java.io.IOException {\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 768 | " return PARSER.parseFrom(input);\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 769 | "}\n" |
| 770 | "public static $classname$ parseFrom(\n" |
| 771 | " com.google.protobuf.CodedInputStream input,\n" |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 772 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 773 | " throws java.io.IOException {\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 774 | " return PARSER.parseFrom(input, extensionRegistry);\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 775 | "}\n" |
| 776 | "\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 777 | "classname", name_resolver_->GetImmutableClassName(descriptor_)); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 778 | } |
| 779 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 780 | void ImmutableMessageGenerator::GenerateSerializeOneField( |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 781 | io::Printer* printer, const FieldDescriptor* field) { |
| 782 | field_generators_.get(field).GenerateSerializationCode(printer); |
| 783 | } |
| 784 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 785 | void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 786 | 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 794 | void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 795 | if (HasDescriptorMethods(descriptor_)) { |
| 796 | // LITE_RUNTIME implements this at the GeneratedMessageLite level. |
| 797 | printer->Print( |
| 798 | "public Builder newBuilderForType() { return newBuilder(); }\n"); |
| 799 | } |
| 800 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 801 | printer->Print( |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 802 | "public static Builder newBuilder() {\n" |
| 803 | " return defaultInstance.toBuilder();\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 804 | "}\n" |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 805 | "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" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 812 | "\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 813 | "classname", name_resolver_->GetImmutableClassName(descriptor_)); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 814 | |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 815 | 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.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 825 | WriteMessageDocComment(printer, descriptor_); |
| 826 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 827 | if (descriptor_->extension_range_count() > 0) { |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 828 | if (HasDescriptorMethods(descriptor_)) { |
| 829 | printer->Print( |
| 830 | "public static final class Builder extends\n" |
| 831 | " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 832 | " $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.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 837 | } else { |
| 838 | printer->Print( |
| 839 | "public static final class Builder extends\n" |
| 840 | " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n" |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 841 | " $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.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 846 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 847 | } else { |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 848 | if (HasDescriptorMethods(descriptor_)) { |
| 849 | printer->Print( |
| 850 | "public static final class Builder extends\n" |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 851 | " 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.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 856 | } else { |
| 857 | printer->Print( |
| 858 | "public static final class Builder extends\n" |
| 859 | " com.google.protobuf.GeneratedMessageLite.Builder<\n" |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 860 | " $classname$, Builder>\n" |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 861 | " implements\n" |
| 862 | " $extra_interfaces$\n" |
| 863 | " $classname$OrBuilder {\n", |
| 864 | "classname", name_resolver_->GetImmutableClassName(descriptor_), |
| 865 | "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 866 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 867 | } |
| 868 | printer->Indent(); |
| 869 | |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 870 | GenerateDescriptorMethods(printer, true); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 871 | GenerateCommonBuilderMethods(printer); |
| 872 | |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 873 | if (HasGeneratedMethods(descriptor_)) { |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 874 | GenerateIsInitialized(printer, DONT_MEMOIZE); |
Feng Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 875 | GenerateBuilderParsingMethods(printer); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 876 | } |
| 877 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 878 | // 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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 908 | } |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 909 | |
| 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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 922 | } |
| 923 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 924 | for (int i = 0; i < descriptor_->field_count(); i++) { |
| 925 | printer->Print("\n"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 926 | field_generators_.get(descriptor_->field(i)) |
| 927 | .GenerateBuilderMembers(printer); |
| 928 | } |
| 929 | |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 930 | 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 | |
temporal | 8ee1474 | 2009-12-20 00:09:50 +0000 | [diff] [blame] | 944 | printer->Print( |
| 945 | "\n" |
| 946 | "// @@protoc_insertion_point(builder_scope:$full_name$)\n", |
| 947 | "full_name", descriptor_->full_name()); |
| 948 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 949 | printer->Outdent(); |
| 950 | printer->Print("}\n"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 951 | } |
| 952 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 953 | void ImmutableMessageGenerator:: |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 954 | GenerateDescriptorMethods(io::Printer* printer, bool is_builder) { |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 955 | if (HasDescriptorMethods(descriptor_)) { |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 956 | 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 963 | "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 964 | "identifier", UniqueFileScopeIdentifier(descriptor_)); |
| 965 | } |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 966 | 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 Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 987 | " return internalGet$capitalized_name$();\n", |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 988 | "number", SimpleItoa(field->number()), |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 989 | "capitalized_name", info->capitalized_name); |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 990 | } |
| 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 Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 1000 | 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 Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1028 | } |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1029 | printer->Print( |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1030 | "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" |
| 1031 | " internalGetFieldAccessorTable() {\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1032 | " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" |
| 1033 | " .ensureFieldAccessorsInitialized(\n" |
| 1034 | " $classname$.class, $classname$.Builder.class);\n" |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1035 | "}\n" |
| 1036 | "\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1037 | "classname", name_resolver_->GetImmutableClassName(descriptor_), |
| 1038 | "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1039 | "identifier", UniqueFileScopeIdentifier(descriptor_)); |
| 1040 | } |
| 1041 | } |
| 1042 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1043 | // =================================================================== |
| 1044 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1045 | void ImmutableMessageGenerator:: |
| 1046 | GenerateCommonBuilderMethods(io::Printer* printer) { |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1047 | if (HasDescriptorMethods(descriptor_)) { |
| 1048 | printer->Print( |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 1049 | "// 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.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1057 | "private Builder(\n" |
| 1058 | " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1059 | " super(parent);\n" |
| 1060 | " maybeForceBuilderInitialization();\n" |
| 1061 | "}\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1062 | "classname", name_resolver_->GetImmutableClassName(descriptor_)); |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 1063 | } else { |
| 1064 | // LITE runtime passes along the default instance to implement |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 1065 | // getDefaultInstanceForType() at the GeneratedMessageLite level. |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 1066 | 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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1074 | } |
| 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1085 | if (!descriptor_->field(i)->containing_oneof()) { |
| 1086 | field_generators_.get(descriptor_->field(i)) |
| 1087 | .GenerateFieldBuilderInitializationCode(printer); |
| 1088 | } |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1089 | } |
| 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( |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1103 | "public Builder clear() {\n" |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1104 | " super.clear();\n"); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1105 | |
| 1106 | printer->Indent(); |
| 1107 | |
| 1108 | for (int i = 0; i < descriptor_->field_count(); i++) { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1109 | 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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1121 | } |
| 1122 | |
| 1123 | printer->Outdent(); |
| 1124 | |
| 1125 | printer->Print( |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1126 | " return this;\n" |
| 1127 | "}\n" |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1128 | "\n"); |
| 1129 | |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1130 | if (HasDescriptorMethods(descriptor_)) { |
| 1131 | printer->Print( |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1132 | "public com.google.protobuf.Descriptors.Descriptor\n" |
| 1133 | " getDescriptorForType() {\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1134 | " return $fileclass$.internal_$identifier$_descriptor;\n" |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1135 | "}\n" |
| 1136 | "\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1137 | "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1138 | "identifier", UniqueFileScopeIdentifier(descriptor_)); |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 1139 | |
| 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.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1147 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1148 | |
| 1149 | // ----------------------------------------------------------------- |
| 1150 | |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 1151 | 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 Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 1165 | if (HasDescriptorMethods(descriptor_)) { |
| 1166 | printer->Print( |
| 1167 | "public $classname$ buildPartial() {\n" |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 1168 | " $classname$ result = new $classname$(this);\n", |
| 1169 | "classname", name_resolver_->GetImmutableClassName(descriptor_)); |
Feng Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 1170 | } else { |
| 1171 | // LITE_RUNTIME only provides a single message constructor. |
| 1172 | printer->Print( |
| 1173 | "public $classname$ buildPartial() {\n" |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 1174 | " $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 Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 1179 | " 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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1187 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1188 | printer->Indent(); |
| 1189 | |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1190 | int totalBuilderBits = 0; |
| 1191 | int totalMessageBits = 0; |
| 1192 | for (int i = 0; i < descriptor_->field_count(); i++) { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1193 | const ImmutableFieldGenerator& field = |
| 1194 | field_generators_.get(descriptor_->field(i)); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1195 | totalBuilderBits += field.GetNumBitsForBuilder(); |
| 1196 | totalMessageBits += field.GetNumBitsForMessage(); |
| 1197 | } |
| 1198 | int totalBuilderInts = (totalBuilderBits + 31) / 32; |
| 1199 | int totalMessageInts = (totalMessageBits + 31) / 32; |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1200 | |
| 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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1214 | } |
| 1215 | |
| 1216 | // Output generation code for each field. |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1217 | for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1218 | field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer); |
| 1219 | } |
| 1220 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1221 | 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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1233 | } |
| 1234 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1235 | printer->Outdent(); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1236 | |
| 1237 | if (HasDescriptorMethods(descriptor_)) { |
| 1238 | printer->Print( |
| 1239 | " onBuilt();\n"); |
| 1240 | } |
| 1241 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1242 | printer->Print( |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1243 | " return result;\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1244 | "}\n" |
| 1245 | "\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1246 | "classname", name_resolver_->GetImmutableClassName(descriptor_)); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1247 | |
| 1248 | // ----------------------------------------------------------------- |
| 1249 | |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1250 | 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.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1255 | "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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1264 | "classname", name_resolver_->GetImmutableClassName(descriptor_)); |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1265 | } |
| 1266 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1267 | printer->Print( |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1268 | "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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1272 | "classname", name_resolver_->GetImmutableClassName(descriptor_)); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1273 | printer->Indent(); |
| 1274 | |
| 1275 | for (int i = 0; i < descriptor_->field_count(); i++) { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1276 | 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"); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1314 | } |
| 1315 | |
| 1316 | printer->Outdent(); |
kenton@google.com | 2d6daa7 | 2009-01-22 01:27:00 +0000 | [diff] [blame] | 1317 | |
| 1318 | // if message type has extensions |
| 1319 | if (descriptor_->extension_range_count() > 0) { |
| 1320 | printer->Print( |
| 1321 | " this.mergeExtensionFields(other);\n"); |
| 1322 | } |
| 1323 | |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1324 | if (PreserveUnknownFields(descriptor_)) { |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1325 | printer->Print( |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1326 | " this.mergeUnknownFields(other.unknownFields);\n"); |
| 1327 | } |
| 1328 | |
| 1329 | if (HasDescriptorMethods(descriptor_)) { |
| 1330 | printer->Print(" onChanged();\n"); |
kenton@google.com | 80b1d62 | 2009-07-29 01:13:20 +0000 | [diff] [blame] | 1331 | } |
| 1332 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1333 | printer->Print( |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1334 | " return this;\n" |
| 1335 | "}\n" |
| 1336 | "\n"); |
| 1337 | } |
| 1338 | } |
| 1339 | |
| 1340 | // =================================================================== |
| 1341 | |
Feng Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 1342 | void ImmutableMessageGenerator:: |
| 1343 | GenerateBuilderParsingMethods(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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1370 | void ImmutableMessageGenerator::GenerateIsInitialized( |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1371 | io::Printer* printer, UseMemoization useMemoization) { |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 1372 | // LITE_RUNTIME avoids generating isInitialized if it's not needed. |
| 1373 | if (!HasDescriptorMethods(descriptor_) |
| 1374 | && !HasRequiredFields(descriptor_)) { |
| 1375 | return; |
| 1376 | } |
| 1377 | |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1378 | 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 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1386 | printer->Print( |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1387 | "public final boolean isInitialized() {\n"); |
| 1388 | printer->Indent(); |
| 1389 | |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1390 | if (memoization) { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1391 | // Don't directly compare to -1 to avoid an Android x86 JIT bug. |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1392 | printer->Print( |
| 1393 | "byte isInitialized = memoizedIsInitialized;\n" |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1394 | "if (isInitialized == 1) return true;\n" |
| 1395 | "if (isInitialized == 0) return false;\n" |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1396 | "\n"); |
| 1397 | } |
| 1398 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1399 | // 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1404 | const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1405 | |
| 1406 | if (field->is_required()) { |
| 1407 | printer->Print( |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1408 | "if (!has$name$()) {\n" |
| 1409 | " $memoize$\n" |
| 1410 | " return false;\n" |
| 1411 | "}\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1412 | "name", info->capitalized_name, |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1413 | "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1414 | } |
| 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1420 | const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); |
kenton@google.com | fccb146 | 2009-12-18 02:11:36 +0000 | [diff] [blame] | 1421 | if (GetJavaType(field) == JAVATYPE_MESSAGE && |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1422 | HasRequiredFields(field->message_type())) { |
| 1423 | switch (field->label()) { |
| 1424 | case FieldDescriptor::LABEL_REQUIRED: |
| 1425 | printer->Print( |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1426 | "if (!get$name$().isInitialized()) {\n" |
| 1427 | " $memoize$\n" |
| 1428 | " return false;\n" |
| 1429 | "}\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1430 | "type", name_resolver_->GetImmutableClassName( |
| 1431 | field->message_type()), |
| 1432 | "name", info->capitalized_name, |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1433 | "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1434 | break; |
| 1435 | case FieldDescriptor::LABEL_OPTIONAL: |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1436 | 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 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1450 | printer->Print( |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1451 | " if (!get$name$().isInitialized()) {\n" |
| 1452 | " $memoize$\n" |
| 1453 | " return false;\n" |
| 1454 | " }\n" |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1455 | "}\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1456 | "name", info->capitalized_name, |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1457 | "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1458 | break; |
| 1459 | case FieldDescriptor::LABEL_REPEATED: |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 1460 | 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 | } |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1485 | break; |
| 1486 | } |
| 1487 | } |
| 1488 | } |
| 1489 | |
| 1490 | if (descriptor_->extension_range_count() > 0) { |
| 1491 | printer->Print( |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1492 | "if (!extensionsAreInitialized()) {\n" |
| 1493 | " $memoize$\n" |
| 1494 | " return false;\n" |
| 1495 | "}\n", |
| 1496 | "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1497 | } |
| 1498 | |
| 1499 | printer->Outdent(); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1500 | |
| 1501 | if (memoization) { |
| 1502 | printer->Print( |
| 1503 | " memoizedIsInitialized = 1;\n"); |
| 1504 | } |
| 1505 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1506 | printer->Print( |
| 1507 | " return true;\n" |
| 1508 | "}\n" |
| 1509 | "\n"); |
| 1510 | } |
| 1511 | |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 1512 | // =================================================================== |
| 1513 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1514 | namespace { |
| 1515 | bool 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 | |
| 1527 | void ImmutableMessageGenerator:: |
| 1528 | GenerateEqualsAndHashCode(io::Printer* printer) { |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1529 | printer->Print( |
| 1530 | "@java.lang.Override\n" |
liujisi@google.com | 9cf65b7 | 2011-04-08 03:40:29 +0000 | [diff] [blame] | 1531 | "public boolean equals(final java.lang.Object obj) {\n"); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1532 | 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1542 | "classname", name_resolver_->GetImmutableClassName(descriptor_)); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1543 | |
| 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1547 | const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); |
| 1548 | bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); |
| 1549 | if (check_has_bits) { |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1550 | printer->Print( |
| 1551 | "result = result && (has$name$() == other.has$name$());\n" |
| 1552 | "if (has$name$()) {\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1553 | "name", info->capitalized_name); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1554 | printer->Indent(); |
| 1555 | } |
| 1556 | field_generators_.get(field).GenerateEqualsCode(printer); |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1557 | if (check_has_bits) { |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1558 | printer->Outdent(); |
| 1559 | printer->Print( |
| 1560 | "}\n"); |
| 1561 | } |
| 1562 | } |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1563 | 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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1567 | printer->Print( |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1568 | "result = result && unknownFields.equals(other.unknownFields);\n"); |
| 1569 | } |
| 1570 | if (HasDescriptorMethods(descriptor_)) { |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1571 | 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.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1589 | "if (memoizedHashCode != 0) {\n"); |
| 1590 | printer->Indent(); |
| 1591 | printer->Print( |
| 1592 | "return memoizedHashCode;\n"); |
| 1593 | printer->Outdent(); |
| 1594 | printer->Print( |
| 1595 | "}\n" |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1596 | "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.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1607 | for (int i = 0; i < descriptor_->field_count(); i++) { |
| 1608 | const FieldDescriptor* field = descriptor_->field(i); |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1609 | const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); |
| 1610 | bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); |
| 1611 | if (check_has_bits) { |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1612 | printer->Print( |
| 1613 | "if (has$name$()) {\n", |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1614 | "name", info->capitalized_name); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1615 | printer->Indent(); |
| 1616 | } |
| 1617 | field_generators_.get(field).GenerateHashCode(printer); |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1618 | if (check_has_bits) { |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1619 | 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1629 | |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1630 | printer->Print( |
| 1631 | "hash = (29 * hash) + unknownFields.hashCode();\n"); |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1632 | printer->Print( |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1633 | "memoizedHashCode = hash;\n" |
liujisi@google.com | 33165fe | 2010-11-02 13:14:58 +0000 | [diff] [blame] | 1634 | "return hash;\n"); |
| 1635 | printer->Outdent(); |
| 1636 | printer->Print( |
| 1637 | "}\n" |
| 1638 | "\n"); |
| 1639 | } |
| 1640 | |
| 1641 | // =================================================================== |
| 1642 | |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1643 | void ImmutableMessageGenerator:: |
| 1644 | GenerateExtensionRegistrationCode(io::Printer* printer) { |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 1645 | for (int i = 0; i < descriptor_->extension_count(); i++) { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1646 | ImmutableExtensionGenerator(descriptor_->extension(i), context_) |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 1647 | .GenerateRegistrationCode(printer); |
| 1648 | } |
| 1649 | |
| 1650 | for (int i = 0; i < descriptor_->nested_type_count(); i++) { |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1651 | ImmutableMessageGenerator(descriptor_->nested_type(i), context_) |
kenton@google.com | 24bf56f | 2008-09-24 20:31:01 +0000 | [diff] [blame] | 1652 | .GenerateExtensionRegistrationCode(printer); |
| 1653 | } |
| 1654 | } |
| 1655 | |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1656 | // =================================================================== |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1657 | void ImmutableMessageGenerator:: |
| 1658 | GenerateParsingConstructor(io::Printer* printer) { |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 1659 | google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields( |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1660 | SortFieldsByNumber(descriptor_)); |
| 1661 | |
| 1662 | printer->Print( |
| 1663 | "private $classname$(\n" |
| 1664 | " com.google.protobuf.CodedInputStream input,\n" |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 1665 | " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n", |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1666 | "classname", descriptor_->name()); |
| 1667 | printer->Indent(); |
| 1668 | |
| 1669 | // Initialize all fields to default. |
Feng Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 1670 | if (HasDescriptorMethods(descriptor_)) { |
| 1671 | printer->Print( |
| 1672 | "this();\n"); |
| 1673 | } else { |
| 1674 | // LITE_RUNTIME only has one constructor. |
| 1675 | GenerateInitializers(printer); |
| 1676 | } |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1677 | |
| 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1681 | const ImmutableFieldGenerator& field = |
| 1682 | field_generators_.get(descriptor_->field(i)); |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1683 | 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 Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1691 | 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.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1701 | } |
| 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 Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1720 | " 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.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1755 | |
| 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 Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 1801 | " throw new RuntimeException(e.setUnfinishedMessage(this));\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1802 | "} catch (java.io.IOException e) {\n" |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 1803 | " throw new RuntimeException(\n" |
| 1804 | " new com.google.protobuf.InvalidProtocolBufferException(\n" |
| 1805 | " e.getMessage()).setUnfinishedMessage(this));\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1806 | "} 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 Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1815 | if (PreserveUnknownFields(descriptor_)) { |
| 1816 | // Make unknown fields immutable. |
| 1817 | printer->Print("this.unknownFields = unknownFields.build();\n"); |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1818 | } |
| 1819 | |
Feng Xiao | f157a56 | 2014-11-14 11:50:31 -0800 | [diff] [blame] | 1820 | 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.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1832 | |
| 1833 | printer->Outdent(); |
| 1834 | printer->Outdent(); |
| 1835 | printer->Print( |
| 1836 | " }\n" // finally |
| 1837 | "}\n"); |
| 1838 | } |
| 1839 | |
| 1840 | // =================================================================== |
jieluo@google.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1841 | void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1842 | printer->Print( |
Feng Xiao | 6ef984a | 2014-11-10 17:34:54 -0800 | [diff] [blame] | 1843 | "public static final com.google.protobuf.Parser<$classname$> PARSER =\n" |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1844 | " 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 Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 1854 | // The parsing constructor throws an InvalidProtocolBufferException via a |
| 1855 | // RuntimeException to aid in method pruning. We unwrap it here. |
xiaofeng@google.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1856 | printer->Print( |
Jisi Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 1857 | " 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.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1867 | "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 Liu | 885b612 | 2015-02-28 14:51:22 -0800 | [diff] [blame^] | 1893 | 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.com | b55a20f | 2012-09-22 02:40:50 +0000 | [diff] [blame] | 1903 | } |
| 1904 | |
Feng Xiao | 99aa0f9 | 2014-11-20 16:18:53 -0800 | [diff] [blame] | 1905 | // =================================================================== |
| 1906 | void 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.com | 4de8f55 | 2014-07-18 00:47:59 +0000 | [diff] [blame] | 1915 | |
temporal | 40ee551 | 2008-07-10 02:12:20 +0000 | [diff] [blame] | 1916 | } // namespace java |
| 1917 | } // namespace compiler |
| 1918 | } // namespace protobuf |
| 1919 | } // namespace google |