diff options
author | Jisi Liu <jisi.liu@gmail.com> | 2016-04-28 14:34:59 -0700 |
---|---|---|
committer | Jisi Liu <jisi.liu@gmail.com> | 2016-04-28 14:34:59 -0700 |
commit | cf14183bcd5485b4a71541599ddce0b35eb71352 (patch) | |
tree | 12f6e5eb731d7a70cdac4cdafc8b3131629413e2 /src/google/protobuf/compiler/java | |
parent | f00300d7f04f1c38a7d70e271f9232b94dd0e326 (diff) |
Down integrate from Google internal.
Diffstat (limited to 'src/google/protobuf/compiler/java')
20 files changed, 331 insertions, 479 deletions
diff --git a/src/google/protobuf/compiler/java/java_doc_comment.cc b/src/google/protobuf/compiler/java/java_doc_comment.cc index 663f0c97..0b5caba4 100644 --- a/src/google/protobuf/compiler/java/java_doc_comment.cc +++ b/src/google/protobuf/compiler/java/java_doc_comment.cc @@ -120,9 +120,7 @@ static void WriteDocCommentBodyForLocation( lines.pop_back(); } - printer->Print( - " *\n" - " * <pre>\n"); + printer->Print(" * <pre>\n"); for (int i = 0; i < lines.size(); i++) { // Most lines should start with a space. Watch out for lines that start // with a /, since putting that right after the leading asterisk will @@ -133,7 +131,9 @@ static void WriteDocCommentBodyForLocation( printer->Print(" *$line$\n", "line", lines[i]); } } - printer->Print(" * </pre>\n"); + printer->Print( + " * </pre>\n" + " *\n"); } } @@ -163,12 +163,12 @@ static string FirstLineOf(const string& value) { } void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, message); printer->Print( - "/**\n" - " * Protobuf type {@code $fullname$}\n", + " * Protobuf type {@code $fullname$}\n" + " */\n", "fullname", EscapeJavadoc(message->full_name())); - WriteDocCommentBody(printer, message); - printer->Print(" */\n"); } void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) { @@ -176,55 +176,55 @@ void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) { // etc., but in practice everyone already knows the difference between these // so it's redundant information. - // We use the field declaration as the first line of the comment, e.g.: + // We start the comment with the main body based on the comments from the + // .proto file (if present). We then end with the field declaration, e.g.: // optional string foo = 5; - // This communicates a lot of information about the field in a small space. // If the field is a group, the debug string might end with {. + printer->Print("/**\n"); + WriteDocCommentBody(printer, field); printer->Print( - "/**\n" " * <code>$def$</code>\n", "def", EscapeJavadoc(FirstLineOf(field->DebugString()))); - WriteDocCommentBody(printer, field); printer->Print(" */\n"); } void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, enum_); printer->Print( - "/**\n" - " * Protobuf enum {@code $fullname$}\n", + " * Protobuf enum {@code $fullname$}\n" + " */\n", "fullname", EscapeJavadoc(enum_->full_name())); - WriteDocCommentBody(printer, enum_); - printer->Print(" */\n"); } void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, value); printer->Print( - "/**\n" - " * <code>$def$</code>\n", + " * <code>$def$</code>\n" + " */\n", "def", EscapeJavadoc(FirstLineOf(value->DebugString()))); - WriteDocCommentBody(printer, value); - printer->Print(" */\n"); } void WriteServiceDocComment(io::Printer* printer, const ServiceDescriptor* service) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, service); printer->Print( - "/**\n" - " * Protobuf service {@code $fullname$}\n", + " * Protobuf service {@code $fullname$}\n" + " */\n", "fullname", EscapeJavadoc(service->full_name())); - WriteDocCommentBody(printer, service); - printer->Print(" */\n"); } void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method) { + printer->Print("/**\n"); + WriteDocCommentBody(printer, method); printer->Print( - "/**\n" - " * <code>$def$</code>\n", + " * <code>$def$</code>\n" + " */\n", "def", EscapeJavadoc(FirstLineOf(method->DebugString()))); - WriteDocCommentBody(printer, method); - printer->Print(" */\n"); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index 9eea873a..947b80e4 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -92,6 +92,16 @@ void EnumGenerator::Generate(io::Printer* printer) { "classname", descriptor_->name()); printer->Indent(); + bool ordinal_is_index = true; + string index_text = "ordinal()"; + for (int i = 0; i < canonical_values_.size(); i++) { + if (canonical_values_[i]->index() != i) { + ordinal_is_index = false; + index_text = "index"; + break; + } + } + for (int i = 0; i < canonical_values_.size(); i++) { map<string, string> vars; vars["name"] = canonical_values_[i]->name(); @@ -101,12 +111,21 @@ void EnumGenerator::Generate(io::Printer* printer) { if (canonical_values_[i]->options().deprecated()) { printer->Print("@java.lang.Deprecated\n"); } - printer->Print(vars, - "$name$($index$, $number$),\n"); + if (ordinal_is_index) { + printer->Print(vars, + "$name$($number$),\n"); + } else { + printer->Print(vars, + "$name$($index$, $number$),\n"); + } } if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print("UNRECOGNIZED(-1, -1),\n"); + if (ordinal_is_index) { + printer->Print("UNRECOGNIZED(-1),\n"); + } else { + printer->Print("UNRECOGNIZED(-1, -1),\n"); + } } printer->Print( @@ -141,11 +160,19 @@ void EnumGenerator::Generate(io::Printer* printer) { "\n" "public final int getNumber() {\n"); if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print( - " if (index == -1) {\n" - " throw new java.lang.IllegalArgumentException(\n" - " \"Can't get the number of an unknown enum value.\");\n" - " }\n"); + if (ordinal_is_index) { + printer->Print( + " if (this == UNRECOGNIZED) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"Can't get the number of an unknown enum value.\");\n" + " }\n"); + } else { + printer->Print( + " if (index == -1) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"Can't get the number of an unknown enum value.\");\n" + " }\n"); + } } printer->Print( " return value;\n" @@ -200,14 +227,15 @@ void EnumGenerator::Generate(io::Printer* printer) { printer->Print( "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n" " getValueDescriptor() {\n" - " return getDescriptor().getValues().get(index);\n" + " return getDescriptor().getValues().get($index_text$);\n" "}\n" "public final com.google.protobuf.Descriptors.EnumDescriptor\n" " getDescriptorForType() {\n" " return getDescriptor();\n" "}\n" "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" - " getDescriptor() {\n"); + " getDescriptor() {\n", + "index_text", index_text); // TODO(kenton): Cache statically? Note that we can't access descriptors // at module init time because it wouldn't work with descriptor.proto, but @@ -313,16 +341,27 @@ void EnumGenerator::Generate(io::Printer* printer) { "}\n" "\n"); - printer->Print("private final int index;\n"); + if (!ordinal_is_index) { + printer->Print("private final int index;\n"); + } } // ----------------------------------------------------------------- printer->Print( - "private final int value;\n\n" - "private $classname$(int index, int value) {\n", - "classname", descriptor_->name()); - if (HasDescriptorMethods(descriptor_, context_->EnforceLite())) { + "private final int value;\n\n"); + + if (ordinal_is_index) { + printer->Print( + "private $classname$(int value) {\n", + "classname", descriptor_->name()); + } else { + printer->Print( + "private $classname$(int index, int value) {\n", + "classname", descriptor_->name()); + } + if (HasDescriptorMethods(descriptor_, context_->EnforceLite()) && + !ordinal_is_index) { printer->Print(" this.index = index;\n"); } printer->Print( diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc index 5b98637b..908d6db4 100644 --- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc @@ -262,17 +262,15 @@ GenerateInitializationCode(io::Printer* printer) const { } void ImmutableEnumFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "$name$_ = visitor.visitInt(has$capitalized_name$(), $name$_,\n" + " other.has$capitalized_name$(), other.$name$_);\n"); } else if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print(variables_, - "if (other.$name$_ != $default_number$) {\n" - " set$capitalized_name$Value(other.get$capitalized_name$Value());\n" - "}\n"); + "$name$_ = visitor.visitInt($name$_ != $default_number$, $name$_," + " other.$name$_ != $default_number$, other.$name$_);\n"); } else { GOOGLE_LOG(FATAL) << "Can't reach here."; } @@ -466,14 +464,10 @@ GenerateBuilderMembers(io::Printer* printer) const { } void ImmutableEnumOneofFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { - if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print(variables_, - "set$capitalized_name$Value(other.get$capitalized_name$Value());\n"); - } else { - printer->Print(variables_, - "set$capitalized_name$(other.get$capitalized_name$());\n"); - } +GenerateVisitCode(io::Printer* printer) const { + printer->Print(variables_, + "$oneof_name$_ = visitor.visitOneofInt(\n" + " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n"); } void ImmutableEnumOneofFieldLiteGenerator:: @@ -645,7 +639,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private void ensure$capitalized_name$IsMutable() {\n" " if (!$is_mutable$) {\n" - " $name$_ = newIntList($name$_);\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" " }\n" "}\n"); WriteFieldDocComment(printer, descriptor_); @@ -805,21 +800,9 @@ GenerateInitializationCode(io::Printer* printer) const { } void RepeatedImmutableEnumFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { - // The code below does two optimizations: - // 1. If the other list is empty, there's nothing to do. This ensures we - // don't allocate a new array if we already have an immutable one. - // 2. If the other list is non-empty and our current list is empty, we can - // reuse the other list which is guaranteed to be immutable. - printer->Print(variables_, - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - "}\n"); +GenerateVisitCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_= visitor.visitIntList($name$_, other.$name$_);\n"); } void RepeatedImmutableEnumFieldLiteGenerator:: @@ -831,27 +814,23 @@ GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { void RepeatedImmutableEnumFieldLiteGenerator:: GenerateParsingCode(io::Printer* printer) const { // Read and store the enum + printer->Print(variables_, + "if (!$is_mutable$) {\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" + "}\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "if (!$is_mutable$) {\n" - " $name$_ = newIntList();\n" - "}\n" - "$name$_.addInt(rawValue);\n"); + "$name$_.addInt(input.readEnum());\n"); } else { printer->Print(variables_, "int rawValue = input.readEnum();\n" "$type$ value = $type$.forNumber(rawValue);\n" - "if (value == null) {\n"); - if (PreserveUnknownFields(descriptor_->containing_type())) { - printer->Print(variables_, - " super.mergeVarintField($number$, rawValue);\n"); - } - printer->Print(variables_, + "if (value == null) {\n" + // We store the unknown value in unknown fields. + " super.mergeVarintField($number$, rawValue);\n" "} else {\n" - " if (!$is_mutable$) {\n" - " $name$_ = newIntList();\n" - " }\n" " $name$_.addInt(rawValue);\n" "}\n"); } @@ -859,7 +838,11 @@ GenerateParsingCode(io::Printer* printer) const { void RepeatedImmutableEnumFieldLiteGenerator:: GenerateParsingCodeFromPacked(io::Printer* printer) const { - // Wrap GenerateParsingCode's contents with a while loop. + printer->Print(variables_, + "if (!$is_mutable$) {\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" + "}\n"); printer->Print(variables_, "int length = input.readRawVarint32();\n" @@ -867,7 +850,21 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { "while(input.getBytesUntilLimit() > 0) {\n"); printer->Indent(); - GenerateParsingCode(printer); + // Read and store the enum + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print(variables_, + "$name$_.addInt(input.readEnum());\n"); + } else { + printer->Print(variables_, + "int rawValue = input.readEnum();\n" + "$type$ value = $type$.forNumber(rawValue);\n" + "if (value == null) {\n" + // We store the unknown value in unknown fields. + " super.mergeVarintField($number$, rawValue);\n" + "} else {\n" + " $name$_.addInt(rawValue);\n" + "}\n"); + } printer->Outdent(); printer->Print(variables_, diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.h b/src/google/protobuf/compiler/java/java_enum_field_lite.h index 2c41c3e4..9201b8d6 100644 --- a/src/google/protobuf/compiler/java/java_enum_field_lite.h +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.h @@ -67,7 +67,7 @@ class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingDoneCode(io::Printer* printer) const; @@ -101,7 +101,7 @@ class ImmutableEnumOneofFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; @@ -127,7 +127,7 @@ class RepeatedImmutableEnumFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingCodeFromPacked(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index 0e24da24..4dd4f57f 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -105,7 +105,7 @@ class ImmutableFieldLiteGenerator { virtual void GenerateMembers(io::Printer* printer) const = 0; virtual void GenerateBuilderMembers(io::Printer* printer) const = 0; virtual void GenerateInitializationCode(io::Printer* printer) const = 0; - virtual void GenerateMergingCode(io::Printer* printer) const = 0; + virtual void GenerateVisitCode(io::Printer* printer) const = 0; virtual void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const = 0; virtual void GenerateParsingCode(io::Printer* printer) const = 0; diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc index a648f1c2..62f39302 100644 --- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc @@ -182,12 +182,11 @@ GenerateInitializationCode(io::Printer* printer) const { } void ImmutableLazyMessageFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " $name$_.merge(other.$name$_);\n" - " $set_has_field_bit_message$;\n" - "}\n"); + "$name$_ = visitor.visitLazyMessage(\n" + " has$capitalized_name$(), $name$_,\n" + " other.has$capitalized_name$(), other.$name$_);\n"); } void ImmutableLazyMessageFieldLiteGenerator:: @@ -362,14 +361,12 @@ GenerateBuilderMembers(io::Printer* printer) const { } void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { printer->Print(variables_, - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - "}\n" - "(($lazy_type$) $oneof_name$_).merge(\n" - " ($lazy_type$) other.$oneof_name$_);\n" - "$set_oneof_case_message$;\n"); + "$oneof_name$_ = visitor.visitOneofLazyMessage(\n" + " $has_oneof_case_message$,\n" + " ($lazy_type$) $oneof_name$_,\n" + " ($lazy_type$) other.$oneof_name$_);\n"); } void ImmutableLazyMessageOneofFieldLiteGenerator:: @@ -463,7 +460,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private void ensure$capitalized_name$IsMutable() {\n" " if (!$is_mutable$) {\n" - " $name$_ = newProtobufList($name$_);\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" " }\n" "}\n" "\n"); @@ -678,7 +676,8 @@ void RepeatedImmutableLazyMessageFieldLiteGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "if (!$is_mutable$) {\n" - " $name$_ = newProtobufList();\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" "}\n" "$name$_.add(new com.google.protobuf.LazyFieldLite(\n" " extensionRegistry, input.readBytes()));\n"); diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h index e85ec0f3..47ebeb49 100644 --- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h +++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h @@ -63,7 +63,7 @@ class ImmutableLazyMessageFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; @@ -82,7 +82,7 @@ class ImmutableLazyMessageOneofFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc index 17c3646f..2a551ca4 100644 --- a/src/google/protobuf/compiler/java/java_map_field.cc +++ b/src/google/protobuf/compiler/java/java_map_field.cc @@ -215,7 +215,7 @@ GenerateMembers(io::Printer* printer) const { " if ($name$_ == null) {\n" " return com.google.protobuf.MapField$lite$.emptyMapField(\n" " $map_field_parameter$);\n" - " }\n" + " }\n" " return $name$_;\n" "}\n"); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { @@ -270,7 +270,7 @@ GenerateBuilderMembers(io::Printer* printer) const { " if ($name$_ == null) {\n" " return com.google.protobuf.MapField$lite$.emptyMapField(\n" " $map_field_parameter$);\n" - " }\n" + " }\n" " return $name$_;\n" "}\n" "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc index 6bdebb0d..b80d4139 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc @@ -374,10 +374,10 @@ GenerateInitializationCode(io::Printer* printer) const { } void ImmutableMapFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { printer->Print( variables_, - "internalGetMutable$capitalized_name$().mergeFrom(\n" + "$name$_ = visitor.visitMap(internalGetMutable$capitalized_name$(),\n" " other.internalGet$capitalized_name$());\n"); } diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h index a09cd536..555b5c5b 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.h +++ b/src/google/protobuf/compiler/java/java_map_field_lite.h @@ -52,7 +52,7 @@ class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingDoneCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index dfd8ad08..4c474a48 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -89,7 +89,6 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor) MessageGenerator::~MessageGenerator() {} // =================================================================== -// TODO(api): Move this class to a separate immutable_message.cc file. ImmutableMessageGenerator::ImmutableMessageGenerator( const Descriptor* descriptor, Context* context) : MessageGenerator(descriptor), context_(context), @@ -1226,7 +1225,8 @@ GenerateParsingConstructor(io::Printer* printer) { "default: {\n" " if (!input.skipField(tag)) {\n" " done = true;\n" // it's an endgroup tag - " }\n" + " }\n"); + printer->Print( " break;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc index 049679df..14281816 100644 --- a/src/google/protobuf/compiler/java/java_message_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc @@ -286,11 +286,9 @@ void ImmutableMessageFieldLiteGenerator:: GenerateInitializationCode(io::Printer* printer) const {} void ImmutableMessageFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " merge$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "$name$_ = visitor.visitMessage($name$_, other.$name$_);\n"); } void ImmutableMessageFieldLiteGenerator:: @@ -300,11 +298,18 @@ GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { void ImmutableMessageFieldLiteGenerator:: GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "$type$.Builder subBuilder = null;\n" - "if ($is_field_present_message$) {\n" - " subBuilder = $name$_.toBuilder();\n" - "}\n"); + // TODO(dweis): Update this code to avoid the builder allocation and instead + // only allocate a submessage that isn't made immutable. Rely on the top + // message calling makeImmutable once done to actually traverse the tree and + // finalize state. This will avoid: + // - transitive builder allocations + // - the extra transitive iteration for streamed fields + // - reallocations for copying repeated fields + printer->Print(variables_, + "$type$.Builder subBuilder = null;\n" + "if ($is_field_present_message$) {\n" + " subBuilder = $name$_.toBuilder();\n" + "}\n"); if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, @@ -504,9 +509,12 @@ GenerateBuilderMembers(io::Printer* printer) const { } void ImmutableMessageOneofFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { printer->Print(variables_, - "merge$capitalized_name$(other.get$capitalized_name$());\n"); + "$oneof_name$_ = visitor.visitOneofMessage(\n" + " $has_oneof_case_message$,\n" + " $oneof_name$_,\n" + " other.$oneof_name$_);\n"); } void ImmutableMessageOneofFieldLiteGenerator:: @@ -633,7 +641,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private void ensure$capitalized_name$IsMutable() {\n" " if (!$is_mutable$) {\n" - " $name$_ = newProtobufList($name$_);\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" " }\n" "}\n" "\n"); @@ -851,21 +860,9 @@ GenerateInitializationCode(io::Printer* printer) const { } void RepeatedImmutableMessageFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { - // The code below does two optimizations (non-nested builder case): - // 1. If the other list is empty, there's nothing to do. This ensures we - // don't allocate a new array if we already have an immutable one. - // 2. If the other list is non-empty and our current list is empty, we can - // reuse the other list which is guaranteed to be immutable. - printer->Print(variables_, - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - "}\n"); +GenerateVisitCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_= visitor.visitList($name$_, other.$name$_);\n"); } void RepeatedImmutableMessageFieldLiteGenerator:: @@ -878,7 +875,8 @@ void RepeatedImmutableMessageFieldLiteGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "if (!$is_mutable$) {\n" - " $name$_ = newProtobufList();\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" "}\n"); if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.h b/src/google/protobuf/compiler/java/java_message_field_lite.h index ae26c06a..61321547 100644 --- a/src/google/protobuf/compiler/java/java_message_field_lite.h +++ b/src/google/protobuf/compiler/java/java_message_field_lite.h @@ -67,7 +67,7 @@ class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingDoneCode(io::Printer* printer) const; @@ -101,7 +101,7 @@ class ImmutableMessageOneofFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; @@ -125,7 +125,7 @@ class RepeatedImmutableMessageFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingDoneCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc index 14cc908b..d4d2593a 100644 --- a/src/google/protobuf/compiler/java/java_message_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_lite.cc @@ -199,7 +199,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Indent(); - GenerateParsingConstructor(printer); + GenerateConstructor(printer); // Nested types for (int i = 0; i < descriptor_->enum_type_count(); i++) { @@ -322,10 +322,6 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { GenerateMessageSerializationMethods(printer); - if (HasEqualsAndHashCode(descriptor_)) { - GenerateEqualsAndHashCode(printer); - } - GenerateParseFromMethods(printer); GenerateBuilder(printer); @@ -342,16 +338,8 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { " com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n" " Object arg0, Object arg1) {\n" " switch (method) {\n" - " case PARSE_PARTIAL_FROM: {\n" - " return new $classname$(" - " (com.google.protobuf.CodedInputStream) arg0,\n" - " (com.google.protobuf.ExtensionRegistryLite) arg1);\n" - " }\n" - " case NEW_INSTANCE: {\n" - " return new $classname$(\n" - " com.google.protobuf.Internal.EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" + " case NEW_MUTABLE_INSTANCE: {\n" + " return new $classname$();\n" " }\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); @@ -382,10 +370,18 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Print( "}\n" - "case MERGE_FROM: {\n"); + "case VISIT: {\n"); printer->Indent(); - GenerateDynamicMethodMergeFrom(printer); + GenerateDynamicMethodVisit(printer); + printer->Outdent(); + + printer->Print( + "}\n" + "case MERGE_FROM_STREAM: {\n"); + + printer->Indent(); + GenerateDynamicMethodMergeFromStream(printer); printer->Outdent(); printer->Print( @@ -433,11 +429,8 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Print( "static {\n" - " DEFAULT_INSTANCE = new $classname$(\n" - " com.google.protobuf.Internal\n" - " .EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" + " DEFAULT_INSTANCE = new $classname$();\n" + " DEFAULT_INSTANCE.makeImmutable();\n" "}\n" "\n", "classname", descriptor_->name()); @@ -802,11 +795,13 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable( io::Printer* printer) { + // Output generation code for each field. for (int i = 0; i < descriptor_->field_count(); i++) { field_generators_.get(descriptor_->field(i)) .GenerateDynamicMethodMakeImmutableCode(printer); } + printer->Print( "return null;\n"); } @@ -821,19 +816,17 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder( // =================================================================== -void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom( +void ImmutableMessageLiteGenerator::GenerateDynamicMethodVisit( io::Printer* printer) { printer->Print( - // Optimization: If other is the default instance, we know none of its - // fields are set so we can skip the merge. - "if (arg0 == $classname$.getDefaultInstance()) return this;\n" - "$classname$ other = ($classname$) arg0;\n", + "Visitor visitor = (Visitor) arg0;\n" + "$classname$ other = ($classname$) arg1;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); for (int i = 0; i < descriptor_->field_count(); i++) { if (!descriptor_->field(i)->containing_oneof()) { field_generators_.get( - descriptor_->field(i)).GenerateMergingCode(printer); + descriptor_->field(i)).GenerateVisitCode(printer); } } @@ -852,7 +845,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom( "field_name", ToUpper(field->name())); printer->Indent(); - field_generators_.get(field).GenerateMergingCode(printer); + field_generators_.get(field).GenerateVisitCode(printer); printer->Print( "break;\n"); printer->Outdent(); @@ -861,254 +854,66 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom( } printer->Print( "case $cap_oneof_name$_NOT_SET: {\n" + " visitor.visitOneofNotSet($oneof_name$Case_ != 0);\n" " break;\n" "}\n", "cap_oneof_name", ToUpper(context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name)); - printer->Outdent(); - printer->Print( - "}\n"); - } - - // if message type has extensions - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "this.mergeExtensionFields(other);\n"); - } - - if (PreserveUnknownFields(descriptor_)) { - printer->Print( - "this.mergeUnknownFields(other.unknownFields);\n"); - } - - printer->Print( - "return this;\n"); -} - -// =================================================================== - -namespace { -bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) { - if (field->is_repeated()) { - return false; - } - if (SupportFieldPresence(field->file())) { - return true; - } - return GetJavaType(field) == JAVATYPE_MESSAGE && - field->containing_oneof() == NULL; -} -} // namespace - -void ImmutableMessageLiteGenerator:: -GenerateEqualsAndHashCode(io::Printer* printer) { - printer->Print( - "@java.lang.Override\n" - "public boolean equals(final java.lang.Object obj) {\n"); - printer->Indent(); - printer->Print( - "if (obj == this) {\n" - " return true;\n" - "}\n" - "if (!(obj instanceof $classname$)) {\n" - " return super.equals(obj);\n" - "}\n" - "$classname$ other = ($classname$) obj;\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - printer->Print("boolean result = true;\n"); - // Compare non-oneofs. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() == NULL) { - const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); - bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); - if (check_has_bits) { - printer->Print( - "result = result && (has$name$() == other.has$name$());\n" - "if (has$name$()) {\n", - "name", info->capitalized_name); - printer->Indent(); - } - field_generators_.get(field).GenerateEqualsCode(printer); - if (check_has_bits) { - printer->Outdent(); - printer->Print( - "}\n"); - } - } - } - - // Compare oneofs. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "result = result && get$oneof_capitalized_name$Case().equals(\n" - " other.get$oneof_capitalized_name$Case());\n", - "oneof_capitalized_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name); - printer->Print( - "if (!result) return false;\n" - "switch ($oneof_name$Case_) {\n", + descriptor_->oneof_decl(i))->name), "oneof_name", context_->GetOneofGeneratorInfo( descriptor_->oneof_decl(i))->name); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case $field_number$:\n", - "field_number", - SimpleItoa(field->number())); - printer->Indent(); - field_generators_.get(field).GenerateEqualsCode(printer); - printer->Print("break;\n"); - printer->Outdent(); - } - printer->Print( - "case 0:\n" - "default:\n"); printer->Outdent(); - printer->Print("}\n"); - } - - if (PreserveUnknownFields(descriptor_)) { - // Always consider unknown fields for equality. This will sometimes return - // false for non-canonical ordering when running in LITE_RUNTIME but it's - // the best we can do. printer->Print( - "result = result && unknownFields.equals(other.unknownFields);\n"); + "}\n"); } - printer->Print( - "return result;\n"); - printer->Outdent(); - printer->Print( - "}\n" - "\n"); printer->Print( - "@java.lang.Override\n" - "public int hashCode() {\n"); - printer->Indent(); - printer->Print( - "if (memoizedHashCode != 0) {\n"); + "if (visitor == com.google.protobuf.GeneratedMessageLite.MergeFromVisitor\n" + " .INSTANCE) {\n"); printer->Indent(); - printer->Print( - "return memoizedHashCode;\n"); - printer->Outdent(); - printer->Print( - "}\n" - "int hash = 41;\n"); - - // Include the hash of the class so that two objects with different types - // but the same field values will probably have different hashes. - printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + const OneofDescriptor* field = descriptor_->oneof_decl(i); + printer->Print( + "if (other.$oneof_name$Case_ != 0) {\n" + " $oneof_name$Case_ = other.$oneof_name$Case_;\n" + "}\n", + "oneof_name", context_->GetOneofGeneratorInfo(field)->name); + } - // hashCode non-oneofs. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() == NULL) { - const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); - bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); - if (check_has_bits) { - printer->Print( - "if (has$name$()) {\n", - "name", info->capitalized_name); - printer->Indent(); - } - field_generators_.get(field).GenerateHashCode(printer); - if (check_has_bits) { - printer->Outdent(); - printer->Print("}\n"); - } + if (GenerateHasBits(descriptor_)) { + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += field_generators_.get(descriptor_->field(i)) + .GetNumBitsForMessage(); } - } + int totalInts = (totalBits + 31) / 32; - // hashCode oneofs. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "switch ($oneof_name$Case_) {\n", - "oneof_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + for (int i = 0; i < totalInts; i++) { printer->Print( - "case $field_number$:\n", - "field_number", - SimpleItoa(field->number())); - printer->Indent(); - field_generators_.get(field).GenerateHashCode(printer); - printer->Print("break;\n"); - printer->Outdent(); + "$bit_field_name$ |= other.$bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); } - printer->Print( - "case 0:\n" - "default:\n"); - printer->Outdent(); - printer->Print("}\n"); } - - printer->Print( - "hash = (29 * hash) + unknownFields.hashCode();\n"); - printer->Print( - "memoizedHashCode = hash;\n" - "return hash;\n"); printer->Outdent(); printer->Print( - "}\n" - "\n"); -} + "}\n"); -// =================================================================== -void ImmutableMessageLiteGenerator:: -GenerateExtensionRegistrationCode(io::Printer* printer) { - for (int i = 0; i < descriptor_->extension_count(); i++) { - ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_) - .GenerateRegistrationCode(printer); - } - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) - .GenerateExtensionRegistrationCode(printer); - } + printer->Print( + "return this;\n"); } // =================================================================== -void ImmutableMessageLiteGenerator:: -GenerateParsingConstructor(io::Printer* printer) { - google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields( - SortFieldsByNumber(descriptor_)); - - printer->Print( - "private $classname$(\n" - " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n", - "classname", descriptor_->name()); - printer->Indent(); - - // Initialize all fields to default. - GenerateInitializers(printer); - - // Use builder bits to track mutable repeated fields. - int totalBuilderBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - const ImmutableFieldLiteGenerator& field = - field_generators_.get(descriptor_->field(i)); - totalBuilderBits += field.GetNumBitsForBuilder(); - } - int totalBuilderInts = (totalBuilderBits + 31) / 32; - for (int i = 0; i < totalBuilderInts; i++) { - printer->Print("int mutable_$bit_field_name$ = 0;\n", - "bit_field_name", GetBitFieldName(i)); - } +void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream( + io::Printer* printer) { printer->Print( + "com.google.protobuf.CodedInputStream input =\n" + " (com.google.protobuf.CodedInputStream) arg0;\n" + "com.google.protobuf.ExtensionRegistryLite extensionRegistry =\n" + " (com.google.protobuf.ExtensionRegistryLite) arg1;\n" "try {\n"); printer->Indent(); @@ -1156,6 +961,8 @@ GenerateParsingConstructor(io::Printer* printer) { "}\n"); } + google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields( + SortFieldsByNumber(descriptor_)); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = sorted_fields[i]; uint32 tag = WireFormatLite::MakeTag(field->number(), @@ -1209,19 +1016,54 @@ GenerateParsingConstructor(io::Printer* printer) { "} finally {\n"); printer->Indent(); - // Make repeated field list immutable. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = sorted_fields[i]; - field_generators_.get(field).GenerateParsingDoneCode(printer); + printer->Outdent(); + printer->Print( + "}\n"); // finally +} + +// =================================================================== + +namespace { +bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) { + if (field->is_repeated()) { + return false; + } + if (SupportFieldPresence(field->file())) { + return true; } + return GetJavaType(field) == JAVATYPE_MESSAGE && + field->containing_oneof() == NULL; +} +} // namespace + +// =================================================================== +void ImmutableMessageLiteGenerator:: +GenerateExtensionRegistrationCode(io::Printer* printer) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + ImmutableExtensionLiteGenerator(descriptor_->extension(i), context_) + .GenerateRegistrationCode(printer); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) + .GenerateExtensionRegistrationCode(printer); + } +} + +// =================================================================== +void ImmutableMessageLiteGenerator:: +GenerateConstructor(io::Printer* printer) { printer->Print( - "doneParsing();\n"); + "private $classname$() {\n", + "classname", descriptor_->name()); + printer->Indent(); + + // Initialize all fields to default. + GenerateInitializers(printer); - printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" // finally "}\n"); } diff --git a/src/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h index c8ee99bd..292c1c56 100644 --- a/src/google/protobuf/compiler/java/java_message_lite.h +++ b/src/google/protobuf/compiler/java/java_message_lite.h @@ -70,12 +70,13 @@ class ImmutableMessageLiteGenerator : public MessageGenerator { void GenerateBuilder(io::Printer* printer); void GenerateDynamicMethodIsInitialized(io::Printer* printer); void GenerateDynamicMethodMakeImmutable(io::Printer* printer); - void GenerateDynamicMethodMergeFrom(io::Printer* printer); + void GenerateDynamicMethodVisit(io::Printer* printer); + void GenerateDynamicMethodMergeFromStream(io::Printer* printer); void GenerateDynamicMethodNewBuilder(io::Printer* printer); void GenerateInitializers(io::Printer* printer); void GenerateEqualsAndHashCode(io::Printer* printer); void GenerateParser(io::Printer* printer); - void GenerateParsingConstructor(io::Printer* printer); + void GenerateConstructor(io::Printer* printer); Context* context_; ClassNameResolver* name_resolver_; diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc index fe527623..3e4910c8 100644 --- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc +++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc @@ -44,9 +44,10 @@ #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/io/printer.h> +#include <google/protobuf/testing/file.h> +#include <google/protobuf/testing/file.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> -#include <google/protobuf/testing/file.h> namespace google { namespace protobuf { diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc index d277e4f3..690dad12 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc @@ -86,9 +86,6 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, case JAVATYPE_BOOLEAN: (*variables)["field_list_type"] = "com.google.protobuf.Internal." + capitalized_type + "List"; - (*variables)["new_list"] = "new" + capitalized_type + "List"; - (*variables)["new_list_with_capacity"] = - "new" + capitalized_type + "ListWithCapacity"; (*variables)["empty_list"] = "empty" + capitalized_type + "List()"; (*variables)["make_name_unmodifiable"] = (*variables)["name"] + "_.makeImmutable()"; @@ -98,19 +95,21 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, (*variables)["name"] + "_.add" + capitalized_type; (*variables)["repeated_set"] = (*variables)["name"] + "_.set" + capitalized_type; + (*variables)["visit_type"] = capitalized_type; + (*variables)["visit_type_list"] = "visit" + capitalized_type + "List"; break; default: (*variables)["field_list_type"] = "com.google.protobuf.Internal.ProtobufList<" + (*variables)["boxed_type"] + ">"; - (*variables)["new_list"] = "newProtobufList"; - (*variables)["new_list_with_capacity"] = "newProtobufListWithCapacity"; (*variables)["empty_list"] = "emptyProtobufList()"; (*variables)["make_name_unmodifiable"] = (*variables)["name"] + "_.makeImmutable()"; (*variables)["repeated_get"] = (*variables)["name"] + "_.get"; (*variables)["repeated_add"] = (*variables)["name"] + "_.add"; (*variables)["repeated_set"] = (*variables)["name"] + "_.set"; + (*variables)["visit_type"] = "ByteString"; + (*variables)["visit_type_list"] = "visitList"; } if (IsReferenceType(GetJavaType(descriptor))) { @@ -297,17 +296,16 @@ GenerateBuilderClearCode(io::Printer* printer) const { } void ImmutablePrimitiveFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "$name$_ = visitor.visit$visit_type$(\n" + " has$capitalized_name$(), $name$_,\n" + " other.has$capitalized_name$(), other.$name$_);\n"); } else { printer->Print(variables_, - "if (other.get$capitalized_name$() != $default$) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + "$name$_ = visitor.visit$visit_type$($name$_ != $default$, $name$_,\n" + " other.$name$_ != $default$, other.$name$_);\n"); } } @@ -539,9 +537,10 @@ GenerateBuildingCode(io::Printer* printer) const { } void ImmutablePrimitiveOneofFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { printer->Print(variables_, - "set$capitalized_name$(other.get$capitalized_name$());\n"); + "$oneof_name$_ = visitor.visitOneof$visit_type$(\n" + " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n"); } void ImmutablePrimitiveOneofFieldLiteGenerator:: @@ -641,7 +640,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private void ensure$capitalized_name$IsMutable() {\n" " if (!$is_mutable$) {\n" - " $name$_ = $new_list$($name$_);\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" " }\n" "}\n"); @@ -742,21 +742,9 @@ GenerateBuilderClearCode(io::Printer* printer) const { } void RepeatedImmutablePrimitiveFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { - // The code below does two optimizations: - // 1. If the other list is empty, there's nothing to do. This ensures we - // don't allocate a new array if we already have an immutable one. - // 2. If the other list is non-empty and our current list is empty, we can - // reuse the other list which is guaranteed to be immutable. - printer->Print(variables_, - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - "}\n"); +GenerateVisitCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_= visitor.$visit_type_list$($name$_, other.$name$_);\n"); } void RepeatedImmutablePrimitiveFieldLiteGenerator:: @@ -777,7 +765,8 @@ GenerateParsingCode(io::Printer* printer) const { // TODO(dweis): Scan the input buffer to count and ensure capacity. printer->Print(variables_, "if (!$is_mutable$) {\n" - " $name$_ = $new_list$();\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" "}\n" "$repeated_add$(input.read$capitalized_type$());\n"); } @@ -794,10 +783,13 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { // TODO(dweis): Scan the input buffer to count, then initialize // appropriately. printer->Print(variables_, - " $name$_ = $new_list$();\n"); + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n"); } else { printer->Print(variables_, - " $name$_ = $new_list_with_capacity$(length/$fixed_size$);\n"); + " final int currentSize = $name$_.size();\n" + " $name$_ = $name$_.mutableCopyWithCapacity(\n" + " currentSize + (length/$fixed_size$));\n"); } // TODO(dweis): Scan the input buffer to count and ensure capacity. diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/google/protobuf/compiler/java/java_primitive_field_lite.h index ad603c2a..6cfbbb98 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field_lite.h +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.h @@ -69,7 +69,7 @@ class ImmutablePrimitiveFieldLiteGenerator void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; void GenerateBuilderClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; @@ -105,7 +105,7 @@ class ImmutablePrimitiveOneofFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; @@ -130,7 +130,7 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; void GenerateBuilderClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc index 9012ab5e..0b92c021 100644 --- a/src/google/protobuf/compiler/java/java_string_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc @@ -299,20 +299,16 @@ GenerateInitializationCode(io::Printer* printer) const { } void ImmutableStringFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { +GenerateVisitCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { - // Allow a slight breach of abstraction here in order to avoid forcing - // all string fields to Strings when copying fields from a Message. printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " $set_has_field_bit_message$\n" - " $name$_ = other.$name$_;\n" - "}\n"); + "$name$_ = visitor.visitString(\n" + " has$capitalized_name$(), $name$_,\n" + " other.has$capitalized_name$(), other.$name$_);\n"); } else { printer->Print(variables_, - "if (!other.get$capitalized_name$().isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - "}\n"); + "$name$_ = visitor.visitString(!$name$_.isEmpty(), $name$_,\n" + " !other.$name$_.isEmpty(), other.$name$_);\n"); } } @@ -519,12 +515,10 @@ GenerateBuilderMembers(io::Printer* printer) const { } void ImmutableStringOneofFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { - // Allow a slight breach of abstraction here in order to avoid forcing - // all string fields to Strings when copying fields from a Message. +GenerateVisitCode(io::Printer* printer) const { printer->Print(variables_, - "$set_oneof_case_message$;\n" - "$oneof_name$_ = other.$oneof_name$_;\n"); + "$oneof_name$_ = visitor.visitOneofString(\n" + " $has_oneof_case_message$, $oneof_name$_, other.$oneof_name$_);\n"); } void ImmutableStringOneofFieldLiteGenerator:: @@ -645,8 +639,8 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private void ensure$capitalized_name$IsMutable() {\n" " if (!$is_mutable$) {\n" - " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList(\n" - " $name$_);\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" " }\n" "}\n"); @@ -773,21 +767,9 @@ GenerateInitializationCode(io::Printer* printer) const { } void RepeatedImmutableStringFieldLiteGenerator:: -GenerateMergingCode(io::Printer* printer) const { - // The code below does two optimizations: - // 1. If the other list is empty, there's nothing to do. This ensures we - // don't allocate a new array if we already have an immutable one. - // 2. If the other list is non-empty and our current list is empty, we can - // reuse the other list which is guaranteed to be immutable. - printer->Print(variables_, - "if (!other.$name$_.isEmpty()) {\n" - " if ($name$_.isEmpty()) {\n" - " $name$_ = other.$name$_;\n" - " } else {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.addAll(other.$name$_);\n" - " }\n" - "}\n"); +GenerateVisitCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_= visitor.visitList($name$_, other.$name$_);\n"); } void RepeatedImmutableStringFieldLiteGenerator:: @@ -811,7 +793,8 @@ GenerateParsingCode(io::Printer* printer) const { } printer->Print(variables_, "if (!$is_mutable$) {\n" - " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n" + " $name$_ =\n" + " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" "}\n"); printer->Print(variables_, "$name$_.add(s);\n"); diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.h b/src/google/protobuf/compiler/java/java_string_field_lite.h index 4d9b4bd7..4148aa4d 100644 --- a/src/google/protobuf/compiler/java/java_string_field_lite.h +++ b/src/google/protobuf/compiler/java/java_string_field_lite.h @@ -68,7 +68,7 @@ class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingDoneCode(io::Printer* printer) const; @@ -103,7 +103,7 @@ class ImmutableStringOneofFieldLiteGenerator private: void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; @@ -126,7 +126,7 @@ class RepeatedImmutableStringFieldLiteGenerator void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; + void GenerateVisitCode(io::Printer* printer) const; void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingDoneCode(io::Printer* printer) const; |