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: dweis@google.com (Daniel Weis) 32// Based on original Protocol Buffers design by 33// Sanjay Ghemawat, Jeff Dean, and others. 34 35#include <google/protobuf/compiler/java/java_message_builder.h> 36 37#include <algorithm> 38#include <google/protobuf/stubs/hash.h> 39#include <map> 40#include <memory> 41#ifndef _SHARED_PTR_H 42#include <google/protobuf/stubs/shared_ptr.h> 43#endif 44#include <vector> 45 46#include <google/protobuf/compiler/java/java_context.h> 47#include <google/protobuf/compiler/java/java_doc_comment.h> 48#include <google/protobuf/compiler/java/java_enum.h> 49#include <google/protobuf/compiler/java/java_extension.h> 50#include <google/protobuf/compiler/java/java_generator_factory.h> 51#include <google/protobuf/compiler/java/java_helpers.h> 52#include <google/protobuf/compiler/java/java_name_resolver.h> 53#include <google/protobuf/io/coded_stream.h> 54#include <google/protobuf/io/printer.h> 55#include <google/protobuf/descriptor.pb.h> 56#include <google/protobuf/wire_format.h> 57#include <google/protobuf/stubs/strutil.h> 58#include <google/protobuf/stubs/substitute.h> 59 60namespace google { 61namespace protobuf { 62namespace compiler { 63namespace java { 64 65namespace { 66bool GenerateHasBits(const Descriptor* descriptor) { 67 return SupportFieldPresence(descriptor->file()) || 68 HasRepeatedFields(descriptor); 69} 70 71string MapValueImmutableClassdName(const Descriptor* descriptor, 72 ClassNameResolver* name_resolver) { 73 const FieldDescriptor* value_field = descriptor->FindFieldByName("value"); 74 GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); 75 return name_resolver->GetImmutableClassName(value_field->message_type()); 76} 77} // namespace 78 79MessageBuilderGenerator::MessageBuilderGenerator( 80 const Descriptor* descriptor, Context* context) 81 : descriptor_(descriptor), context_(context), 82 name_resolver_(context->GetNameResolver()), 83 field_generators_(descriptor, context_) { 84 GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite())) 85 << "Generator factory error: A non-lite message generator is used to " 86 "generate lite messages."; 87} 88 89MessageBuilderGenerator::~MessageBuilderGenerator() {} 90 91void MessageBuilderGenerator:: 92Generate(io::Printer* printer) { 93 WriteMessageDocComment(printer, descriptor_); 94 if (descriptor_->extension_range_count() > 0) { 95 printer->Print( 96 "public static final class Builder extends\n" 97 " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" 98 " $classname$, Builder> implements\n" 99 " $extra_interfaces$\n" 100 " $classname$OrBuilder {\n", 101 "classname", name_resolver_->GetImmutableClassName(descriptor_), 102 "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); 103 } else { 104 printer->Print( 105 "public static final class Builder extends\n" 106 " com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n" 107 " $extra_interfaces$\n" 108 " $classname$OrBuilder {\n", 109 "classname", name_resolver_->GetImmutableClassName(descriptor_), 110 "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); 111 } 112 printer->Indent(); 113 114 GenerateDescriptorMethods(printer); 115 GenerateCommonBuilderMethods(printer); 116 117 if (context_->HasGeneratedMethods(descriptor_)) { 118 GenerateIsInitialized(printer); 119 GenerateBuilderParsingMethods(printer); 120 } 121 122 // oneof 123 map<string, string> vars; 124 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { 125 vars["oneof_name"] = context_->GetOneofGeneratorInfo( 126 descriptor_->oneof_decl(i))->name; 127 vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( 128 descriptor_->oneof_decl(i))->capitalized_name; 129 vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); 130 // oneofCase_ and oneof_ 131 printer->Print(vars, 132 "private int $oneof_name$Case_ = 0;\n" 133 "private java.lang.Object $oneof_name$_;\n"); 134 // oneofCase() and clearOneof() 135 printer->Print(vars, 136 "public $oneof_capitalized_name$Case\n" 137 " get$oneof_capitalized_name$Case() {\n" 138 " return $oneof_capitalized_name$Case.forNumber(\n" 139 " $oneof_name$Case_);\n" 140 "}\n" 141 "\n" 142 "public Builder clear$oneof_capitalized_name$() {\n" 143 " $oneof_name$Case_ = 0;\n" 144 " $oneof_name$_ = null;\n"); 145 printer->Print(" onChanged();\n"); 146 printer->Print( 147 " return this;\n" 148 "}\n" 149 "\n"); 150 } 151 152 if (GenerateHasBits(descriptor_)) { 153 // Integers for bit fields. 154 int totalBits = 0; 155 for (int i = 0; i < descriptor_->field_count(); i++) { 156 totalBits += field_generators_.get(descriptor_->field(i)) 157 .GetNumBitsForBuilder(); 158 } 159 int totalInts = (totalBits + 31) / 32; 160 for (int i = 0; i < totalInts; i++) { 161 printer->Print("private int $bit_field_name$;\n", 162 "bit_field_name", GetBitFieldName(i)); 163 } 164 } 165 166 for (int i = 0; i < descriptor_->field_count(); i++) { 167 printer->Print("\n"); 168 field_generators_.get(descriptor_->field(i)) 169 .GenerateBuilderMembers(printer); 170 } 171 172 if (!PreserveUnknownFields(descriptor_)) { 173 printer->Print( 174 "public final Builder setUnknownFields(\n" 175 " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" 176 " return this;\n" 177 "}\n" 178 "\n" 179 "public final Builder mergeUnknownFields(\n" 180 " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" 181 " return this;\n" 182 "}\n" 183 "\n"); 184 } 185 186 printer->Print( 187 "\n" 188 "// @@protoc_insertion_point(builder_scope:$full_name$)\n", 189 "full_name", descriptor_->full_name()); 190 191 printer->Outdent(); 192 printer->Print("}\n"); 193} 194 195// =================================================================== 196 197void MessageBuilderGenerator:: 198GenerateDescriptorMethods(io::Printer* printer) { 199 if (!descriptor_->options().no_standard_descriptor_accessor()) { 200 printer->Print( 201 "public static final com.google.protobuf.Descriptors.Descriptor\n" 202 " getDescriptor() {\n" 203 " return $fileclass$.internal_$identifier$_descriptor;\n" 204 "}\n" 205 "\n", 206 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), 207 "identifier", UniqueFileScopeIdentifier(descriptor_)); 208 } 209 vector<const FieldDescriptor*> map_fields; 210 for (int i = 0; i < descriptor_->field_count(); i++) { 211 const FieldDescriptor* field = descriptor_->field(i); 212 if (GetJavaType(field) == JAVATYPE_MESSAGE && 213 IsMapEntry(field->message_type())) { 214 map_fields.push_back(field); 215 } 216 } 217 if (!map_fields.empty()) { 218 printer->Print( 219 "@SuppressWarnings({\"rawtypes\"})\n" 220 "protected com.google.protobuf.MapField internalGetMapField(\n" 221 " int number) {\n" 222 " switch (number) {\n"); 223 printer->Indent(); 224 printer->Indent(); 225 for (int i = 0; i < map_fields.size(); ++i) { 226 const FieldDescriptor* field = map_fields[i]; 227 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); 228 printer->Print( 229 "case $number$:\n" 230 " return internalGet$capitalized_name$();\n", 231 "number", SimpleItoa(field->number()), 232 "capitalized_name", info->capitalized_name); 233 } 234 printer->Print( 235 "default:\n" 236 " throw new RuntimeException(\n" 237 " \"Invalid map field number: \" + number);\n"); 238 printer->Outdent(); 239 printer->Outdent(); 240 printer->Print( 241 " }\n" 242 "}\n"); 243 printer->Print( 244 "@SuppressWarnings({\"rawtypes\"})\n" 245 "protected com.google.protobuf.MapField internalGetMutableMapField(\n" 246 " int number) {\n" 247 " switch (number) {\n"); 248 printer->Indent(); 249 printer->Indent(); 250 for (int i = 0; i < map_fields.size(); ++i) { 251 const FieldDescriptor* field = map_fields[i]; 252 const FieldGeneratorInfo* info = 253 context_->GetFieldGeneratorInfo(field); 254 printer->Print( 255 "case $number$:\n" 256 " return internalGetMutable$capitalized_name$();\n", 257 "number", SimpleItoa(field->number()), 258 "capitalized_name", info->capitalized_name); 259 } 260 printer->Print( 261 "default:\n" 262 " throw new RuntimeException(\n" 263 " \"Invalid map field number: \" + number);\n"); 264 printer->Outdent(); 265 printer->Outdent(); 266 printer->Print( 267 " }\n" 268 "}\n"); 269 } 270 printer->Print( 271 "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" 272 " internalGetFieldAccessorTable() {\n" 273 " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" 274 " .ensureFieldAccessorsInitialized(\n" 275 " $classname$.class, $classname$.Builder.class);\n" 276 "}\n" 277 "\n", 278 "classname", name_resolver_->GetImmutableClassName(descriptor_), 279 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), 280 "identifier", UniqueFileScopeIdentifier(descriptor_)); 281} 282 283// =================================================================== 284 285void MessageBuilderGenerator:: 286GenerateCommonBuilderMethods(io::Printer* printer) { 287 printer->Print( 288 "// Construct using $classname$.newBuilder()\n" 289 "private Builder() {\n" 290 " maybeForceBuilderInitialization();\n" 291 "}\n" 292 "\n", 293 "classname", name_resolver_->GetImmutableClassName(descriptor_)); 294 295 printer->Print( 296 "private Builder(\n" 297 " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" 298 " super(parent);\n" 299 " maybeForceBuilderInitialization();\n" 300 "}\n", 301 "classname", name_resolver_->GetImmutableClassName(descriptor_)); 302 303 printer->Print( 304 "private void maybeForceBuilderInitialization() {\n" 305 " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n"); 306 307 printer->Indent(); 308 printer->Indent(); 309 for (int i = 0; i < descriptor_->field_count(); i++) { 310 if (!descriptor_->field(i)->containing_oneof()) { 311 field_generators_.get(descriptor_->field(i)) 312 .GenerateFieldBuilderInitializationCode(printer); 313 } 314 } 315 printer->Outdent(); 316 printer->Outdent(); 317 318 printer->Print( 319 " }\n" 320 "}\n"); 321 322 printer->Print( 323 "public Builder clear() {\n" 324 " super.clear();\n"); 325 326 printer->Indent(); 327 328 for (int i = 0; i < descriptor_->field_count(); i++) { 329 if (!descriptor_->field(i)->containing_oneof()) { 330 field_generators_.get(descriptor_->field(i)) 331 .GenerateBuilderClearCode(printer); 332 } 333 } 334 335 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { 336 printer->Print( 337 "$oneof_name$Case_ = 0;\n" 338 "$oneof_name$_ = null;\n", 339 "oneof_name", context_->GetOneofGeneratorInfo( 340 descriptor_->oneof_decl(i))->name); 341 } 342 343 printer->Outdent(); 344 345 printer->Print( 346 " return this;\n" 347 "}\n" 348 "\n"); 349 350 printer->Print( 351 "public com.google.protobuf.Descriptors.Descriptor\n" 352 " getDescriptorForType() {\n" 353 " return $fileclass$.internal_$identifier$_descriptor;\n" 354 "}\n" 355 "\n", 356 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), 357 "identifier", UniqueFileScopeIdentifier(descriptor_)); 358 359 // LITE runtime implements this in GeneratedMessageLite. 360 printer->Print( 361 "public $classname$ getDefaultInstanceForType() {\n" 362 " return $classname$.getDefaultInstance();\n" 363 "}\n" 364 "\n", 365 "classname", name_resolver_->GetImmutableClassName(descriptor_)); 366 367 printer->Print( 368 "public $classname$ build() {\n" 369 " $classname$ result = buildPartial();\n" 370 " if (!result.isInitialized()) {\n" 371 " throw newUninitializedMessageException(result);\n" 372 " }\n" 373 " return result;\n" 374 "}\n" 375 "\n", 376 "classname", name_resolver_->GetImmutableClassName(descriptor_)); 377 378 printer->Print( 379 "public $classname$ buildPartial() {\n" 380 " $classname$ result = new $classname$(this);\n", 381 "classname", name_resolver_->GetImmutableClassName(descriptor_)); 382 383 printer->Indent(); 384 385 int totalBuilderBits = 0; 386 int totalMessageBits = 0; 387 for (int i = 0; i < descriptor_->field_count(); i++) { 388 const ImmutableFieldGenerator& field = 389 field_generators_.get(descriptor_->field(i)); 390 totalBuilderBits += field.GetNumBitsForBuilder(); 391 totalMessageBits += field.GetNumBitsForMessage(); 392 } 393 int totalBuilderInts = (totalBuilderBits + 31) / 32; 394 int totalMessageInts = (totalMessageBits + 31) / 32; 395 396 if (GenerateHasBits(descriptor_)) { 397 // Local vars for from and to bit fields to avoid accessing the builder and 398 // message over and over for these fields. Seems to provide a slight 399 // perforamance improvement in micro benchmark and this is also what proto1 400 // code does. 401 for (int i = 0; i < totalBuilderInts; i++) { 402 printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n", 403 "bit_field_name", GetBitFieldName(i)); 404 } 405 for (int i = 0; i < totalMessageInts; i++) { 406 printer->Print("int to_$bit_field_name$ = 0;\n", 407 "bit_field_name", GetBitFieldName(i)); 408 } 409 } 410 411 // Output generation code for each field. 412 for (int i = 0; i < descriptor_->field_count(); i++) { 413 field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer); 414 } 415 416 if (GenerateHasBits(descriptor_)) { 417 // Copy the bit field results to the generated message 418 for (int i = 0; i < totalMessageInts; i++) { 419 printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n", 420 "bit_field_name", GetBitFieldName(i)); 421 } 422 } 423 424 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { 425 printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n", 426 "oneof_name", context_->GetOneofGeneratorInfo( 427 descriptor_->oneof_decl(i))->name); 428 } 429 430 printer->Outdent(); 431 432 printer->Print( 433 " onBuilt();\n"); 434 435 printer->Print( 436 " return result;\n" 437 "}\n" 438 "\n", 439 "classname", name_resolver_->GetImmutableClassName(descriptor_)); 440 441 // ----------------------------------------------------------------- 442 443 if (context_->HasGeneratedMethods(descriptor_)) { 444 printer->Print( 445 "public Builder mergeFrom(com.google.protobuf.Message other) {\n" 446 " if (other instanceof $classname$) {\n" 447 " return mergeFrom(($classname$)other);\n" 448 " } else {\n" 449 " super.mergeFrom(other);\n" 450 " return this;\n" 451 " }\n" 452 "}\n" 453 "\n", 454 "classname", name_resolver_->GetImmutableClassName(descriptor_)); 455 456 printer->Print( 457 "public Builder mergeFrom($classname$ other) {\n" 458 // Optimization: If other is the default instance, we know none of its 459 // fields are set so we can skip the merge. 460 " if (other == $classname$.getDefaultInstance()) return this;\n", 461 "classname", name_resolver_->GetImmutableClassName(descriptor_)); 462 printer->Indent(); 463 464 for (int i = 0; i < descriptor_->field_count(); i++) { 465 if (!descriptor_->field(i)->containing_oneof()) { 466 field_generators_.get( 467 descriptor_->field(i)).GenerateMergingCode(printer); 468 } 469 } 470 471 // Merge oneof fields. 472 for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { 473 printer->Print( 474 "switch (other.get$oneof_capitalized_name$Case()) {\n", 475 "oneof_capitalized_name", 476 context_->GetOneofGeneratorInfo( 477 descriptor_->oneof_decl(i))->capitalized_name); 478 printer->Indent(); 479 for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { 480 const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); 481 printer->Print( 482 "case $field_name$: {\n", 483 "field_name", 484 ToUpper(field->name())); 485 printer->Indent(); 486 field_generators_.get(field).GenerateMergingCode(printer); 487 printer->Print( 488 "break;\n"); 489 printer->Outdent(); 490 printer->Print( 491 "}\n"); 492 } 493 printer->Print( 494 "case $cap_oneof_name$_NOT_SET: {\n" 495 " break;\n" 496 "}\n", 497 "cap_oneof_name", 498 ToUpper(context_->GetOneofGeneratorInfo( 499 descriptor_->oneof_decl(i))->name)); 500 printer->Outdent(); 501 printer->Print( 502 "}\n"); 503 } 504 505 printer->Outdent(); 506 507 // if message type has extensions 508 if (descriptor_->extension_range_count() > 0) { 509 printer->Print( 510 " this.mergeExtensionFields(other);\n"); 511 } 512 513 if (PreserveUnknownFields(descriptor_)) { 514 printer->Print( 515 " this.mergeUnknownFields(other.unknownFields);\n"); 516 } 517 518 printer->Print( 519 " onChanged();\n"); 520 521 printer->Print( 522 " return this;\n" 523 "}\n" 524 "\n"); 525 } 526} 527 528// =================================================================== 529 530void MessageBuilderGenerator:: 531GenerateBuilderParsingMethods(io::Printer* printer) { 532 printer->Print( 533 "public Builder mergeFrom(\n" 534 " com.google.protobuf.CodedInputStream input,\n" 535 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" 536 " throws java.io.IOException {\n" 537 " $classname$ parsedMessage = null;\n" 538 " try {\n" 539 " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n" 540 " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" 541 " parsedMessage = ($classname$) e.getUnfinishedMessage();\n" 542 " throw e.unwrapIOException();\n" 543 " } finally {\n" 544 " if (parsedMessage != null) {\n" 545 " mergeFrom(parsedMessage);\n" 546 " }\n" 547 " }\n" 548 " return this;\n" 549 "}\n", 550 "classname", name_resolver_->GetImmutableClassName(descriptor_)); 551} 552 553// =================================================================== 554 555void MessageBuilderGenerator::GenerateIsInitialized( 556 io::Printer* printer) { 557 printer->Print( 558 "public final boolean isInitialized() {\n"); 559 printer->Indent(); 560 561 // Check that all required fields in this message are set. 562 // TODO(kenton): We can optimize this when we switch to putting all the 563 // "has" fields into a single bitfield. 564 for (int i = 0; i < descriptor_->field_count(); i++) { 565 const FieldDescriptor* field = descriptor_->field(i); 566 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); 567 568 if (field->is_required()) { 569 printer->Print( 570 "if (!has$name$()) {\n" 571 " return false;\n" 572 "}\n", 573 "name", info->capitalized_name); 574 } 575 } 576 577 // Now check that all embedded messages are initialized. 578 for (int i = 0; i < descriptor_->field_count(); i++) { 579 const FieldDescriptor* field = descriptor_->field(i); 580 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); 581 if (GetJavaType(field) == JAVATYPE_MESSAGE && 582 HasRequiredFields(field->message_type())) { 583 switch (field->label()) { 584 case FieldDescriptor::LABEL_REQUIRED: 585 printer->Print( 586 "if (!get$name$().isInitialized()) {\n" 587 " return false;\n" 588 "}\n", 589 "type", name_resolver_->GetImmutableClassName( 590 field->message_type()), 591 "name", info->capitalized_name); 592 break; 593 case FieldDescriptor::LABEL_OPTIONAL: 594 if (!SupportFieldPresence(descriptor_->file()) && 595 field->containing_oneof() != NULL) { 596 const OneofDescriptor* oneof = field->containing_oneof(); 597 const OneofGeneratorInfo* oneof_info = 598 context_->GetOneofGeneratorInfo(oneof); 599 printer->Print( 600 "if ($oneof_name$Case_ == $field_number$) {\n", 601 "oneof_name", oneof_info->name, 602 "field_number", SimpleItoa(field->number())); 603 } else { 604 printer->Print( 605 "if (has$name$()) {\n", 606 "name", info->capitalized_name); 607 } 608 printer->Print( 609 " if (!get$name$().isInitialized()) {\n" 610 " return false;\n" 611 " }\n" 612 "}\n", 613 "name", info->capitalized_name); 614 break; 615 case FieldDescriptor::LABEL_REPEATED: 616 if (IsMapEntry(field->message_type())) { 617 printer->Print( 618 "for ($type$ item : get$name$().values()) {\n" 619 " if (!item.isInitialized()) {\n" 620 " return false;\n" 621 " }\n" 622 "}\n", 623 "type", MapValueImmutableClassdName(field->message_type(), 624 name_resolver_), 625 "name", info->capitalized_name); 626 } else { 627 printer->Print( 628 "for (int i = 0; i < get$name$Count(); i++) {\n" 629 " if (!get$name$(i).isInitialized()) {\n" 630 " return false;\n" 631 " }\n" 632 "}\n", 633 "type", name_resolver_->GetImmutableClassName( 634 field->message_type()), 635 "name", info->capitalized_name); 636 } 637 break; 638 } 639 } 640 } 641 642 if (descriptor_->extension_range_count() > 0) { 643 printer->Print( 644 "if (!extensionsAreInitialized()) {\n" 645 " return false;\n" 646 "}\n"); 647 } 648 649 printer->Outdent(); 650 651 printer->Print( 652 " return true;\n" 653 "}\n" 654 "\n"); 655} 656 657// =================================================================== 658 659} // namespace java 660} // namespace compiler 661} // namespace protobuf 662} // namespace google 663