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