diff options
author | Xiao Hang <rocking@google.com> | 2015-08-04 15:07:44 -0700 |
---|---|---|
committer | Xiao Hang <rocking@google.com> | 2015-08-04 15:07:44 -0700 |
commit | 9fd0f1526fab9ee9b7e9d021185bc3507048a6d2 (patch) | |
tree | a10acdb4210cf4d7dc770db88efc694aa35ec1de /src/google | |
parent | f5a3abc20487e423a7b3b2e13ad630e2d5026895 (diff) | |
parent | dc80689af3951d078cb556588eece89dd6860c91 (diff) | |
download | protobuf-9fd0f1526fab9ee9b7e9d021185bc3507048a6d2.tar.gz protobuf-9fd0f1526fab9ee9b7e9d021185bc3507048a6d2.tar.bz2 protobuf-9fd0f1526fab9ee9b7e9d021185bc3507048a6d2.zip |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src/google')
87 files changed, 2030 insertions, 2374 deletions
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index 2c492b04..c2e58131 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -82,9 +82,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fany_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n\031google/protobuf/any.proto\022\017google.prot" "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002" - " \001(\014BC\n\023com.google.protobufB\010AnyProtoP\001\240" - "\001\001\242\002\003GPB\252\002\026Google.ProtocolBuffersb\006proto" - "3", 161); + " \001(\014BK\n\023com.google.protobufB\010AnyProtoP\001\240" + "\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownType" + "sb\006proto3", 169); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/any.proto", &protobuf_RegisterTypes); Any::default_instance_ = new Any(); diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto index e1780fe5..d3ad3acc 100644 --- a/src/google/protobuf/any.proto +++ b/src/google/protobuf/any.proto @@ -35,7 +35,7 @@ option java_generate_equals_and_hash = true; option java_multiple_files = true; option java_outer_classname = "AnyProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index 434320dc..0feddb31 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -123,8 +123,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto() { "quest_type_url\030\002 \001(\t\022\031\n\021request_streamin" "g\030\003 \001(\010\022\031\n\021response_type_url\030\004 \001(\t\022\032\n\022re" "sponse_streaming\030\005 \001(\010\022(\n\007options\030\006 \003(\0132" - "\027.google.protobuf.OptionB\'\n\023com.google.p" - "rotobufB\010ApiProtoP\001\242\002\003GPBb\006proto3", 513); + "\027.google.protobuf.OptionBH\n\023com.google.p" + "rotobufB\010ApiProtoP\001\242\002\003GPB\252\002\036Google.Proto" + "buf.WellKnownTypesb\006proto3", 546); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/api.proto", &protobuf_RegisterTypes); Api::default_instance_ = new Api(); diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto index f368c24d..d6c2a8b3 100644 --- a/src/google/protobuf/api.proto +++ b/src/google/protobuf/api.proto @@ -37,6 +37,7 @@ import "google/protobuf/type.proto"; option java_multiple_files = true; option java_outer_classname = "ApiProto"; option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index c57cfd3d..e8871861 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -189,7 +189,7 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) { bool GetProtocAbsolutePath(string* path) { #ifdef _WIN32 char buffer[MAX_PATH]; - int len = GetModuleFileName(NULL, buffer, MAX_PATH); + int len = GetModuleFileNameA(NULL, buffer, MAX_PATH); #elif __APPLE__ char buffer[PATH_MAX]; int len = 0; diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 51a95b9f..d38fb1ed 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -55,36 +55,29 @@ EnumFieldGenerator::~EnumFieldGenerator() { void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print(variables_, - "object unknown;\n" - "if(input.ReadEnum(ref result.$name$_, out unknown)) {\n"); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - " result.has$property_name$ = true;\n"); - } - printer->Print("} else if(unknown is int) {\n"); - if (!use_lite_runtime()) { - printer->Print(variables_, - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n" - " unknownFields.MergeVarintField($number$, (ulong)(int)unknown);\n"); - } - printer->Print("}\n"); + "$name$_ = ($type_name$) input.ReadEnum();\n"); } void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print(variables_, - "if ($has_property_check$) {\n" - " output.WriteEnum($number$, field_names[$field_ordinal$], (int) $property_name$, $property_name$);\n" - "}\n"); + "if ($has_property_check$) {\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.WriteEnum((int) $property_name$);\n" + "}\n"); } void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( - variables_, - "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" - "}\n"); + variables_, + "if ($has_property_check$) {\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n" + "}\n"); +} + +void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) { + printer->Print( + variables_, + "pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x)"); } EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor, @@ -96,30 +89,19 @@ EnumOneofFieldGenerator::~EnumOneofFieldGenerator() { } void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + // TODO(jonskeet): What about if we read the default value? printer->Print( variables_, - "object unknown;\n" - "$type_name$ enumValue = $default_value$;\n" - "if(input.ReadEnum(ref enumValue, out unknown)) {\n" - " result.$oneof_name$_ = enumValue;\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - "} else if(unknown is int) {\n"); - if (!use_lite_runtime()) { - printer->Print( - variables_, - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n" - " unknownFields.MergeVarintField($number$, (ulong)(int)unknown);\n"); - } - printer->Print("}\n"); + "$oneof_name$_ = input.ReadEnum();\n" + "$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); } void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, field_names[$field_ordinal$], (int) $property_name$, $property_name$);\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.WriteEnum((int) $property_name$);\n" "}\n"); } @@ -127,7 +109,7 @@ void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h index e627b7cc..08364157 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h @@ -46,6 +46,7 @@ class EnumFieldGenerator : public PrimitiveFieldGenerator { EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~EnumFieldGenerator(); + virtual void GenerateCodecCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.cc b/src/google/protobuf/compiler/csharp/csharp_extension.cc deleted file mode 100644 index 8b665ae4..00000000 --- a/src/google/protobuf/compiler/csharp/csharp_extension.cc +++ /dev/null @@ -1,184 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <sstream> - -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/plugin.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> - -#include <google/protobuf/compiler/csharp/csharp_extension.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_field_base.h> - -using google::protobuf::internal::scoped_ptr; - -namespace google { -namespace protobuf { -namespace compiler { -namespace csharp { - -ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) - : FieldGeneratorBase(descriptor, 0) { - if (descriptor_->extension_scope()) { - variables_["scope"] = GetClassName(descriptor_->extension_scope()); - } else { - variables_["scope"] = GetFullUmbrellaClassName(descriptor_->file()); - } - variables_["extends"] = GetClassName(descriptor_->containing_type()); - variables_["capitalized_type_name"] = capitalized_type_name(); - variables_["full_name"] = descriptor_->full_name(); - variables_["access_level"] = class_access_level(); - variables_["index"] = SimpleItoa(descriptor_->index()); - variables_["property_name"] = property_name(); - variables_["type_name"] = type_name(); - if (use_lite_runtime()) { - variables_["generated_extension"] = descriptor_->is_repeated() ? - "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite"; - } else { - variables_["generated_extension"] = descriptor_->is_repeated() ? - "GeneratedRepeatExtension" : "GeneratedExtension"; - } -} - -ExtensionGenerator::~ExtensionGenerator() { -} - -void ExtensionGenerator::Generate(io::Printer* printer) { - printer->Print( - "public const int $constant_name$ = $number$;\n", - "constant_name", GetFieldConstantName(descriptor_), - "number", SimpleItoa(descriptor_->number())); - - if (use_lite_runtime()) { - // TODO(jtattermusch): include the following check - //if (Descriptor.MappedType == MappedType.Message && Descriptor.MessageType.Options.MessageSetWireFormat) - //{ - // throw new ArgumentException( - // "option message_set_wire_format = true; is not supported in Lite runtime extensions."); - //} - - printer->Print( - variables_, - "$access_level$ static pb::$generated_extension$<$extends$, $type_name$> $property_name$;\n"); - } else if (descriptor_->is_repeated()) { - printer->Print( - variables_, - "$access_level$ static pb::GeneratedExtensionBase<scg::IList<$type_name$>> $property_name$;\n"); - } else { - printer->Print( - variables_, - "$access_level$ static pb::GeneratedExtensionBase<$type_name$> $property_name$;\n"); - } -} - -void ExtensionGenerator::GenerateStaticVariableInitializers(io::Printer* printer) { - if (use_lite_runtime()) { - printer->Print( - variables_, - "$scope$.$property_name$ = \n"); - printer->Indent(); - printer->Print( - variables_, - "new pb::$generated_extension$<$extends$, $type_name$>(\n"); - printer->Indent(); - printer->Print( - variables_, - "\"$full_name$\",\n" - "$extends$.DefaultInstance,\n"); - if (!descriptor_->is_repeated()) { - std::string default_val; - if (descriptor_->has_default_value()) { - default_val = default_value(); - } else { - default_val = is_nullable_type() ? "null" : ("default(" + type_name() + ")"); - } - printer->Print("$default_val$,\n", "default_val", default_val); - } - printer->Print( - "$message_val$,\n", - "message_val", - (GetCSharpType(descriptor_->type()) == CSHARPTYPE_MESSAGE) ? - type_name() + ".DefaultInstance" : "null"); - printer->Print( - "$enum_val$,\n", - "enum_val", - (GetCSharpType(descriptor_->type()) == CSHARPTYPE_ENUM) ? - "new EnumLiteMap<" + type_name() + ">()" : "null"); - printer->Print( - variables_, - "$scope$.$property_name$FieldNumber,\n" - "pbd::FieldType.$capitalized_type_name$"); - if (descriptor_->is_repeated()) { - printer->Print( - ",\n" - "$is_packed$", - "is_packed", descriptor_->is_packed() ? "true" : "false"); - } - printer->Outdent(); - printer->Print(");\n"); - printer->Outdent(); - } - else if (descriptor_->is_repeated()) - { - printer->Print( - variables_, - "$scope$.$property_name$ = pb::GeneratedRepeatExtension<$type_name$>.CreateInstance($scope$.Descriptor.Extensions[$index$]);\n"); - } - else - { - printer->Print( - variables_, - "$scope$.$property_name$ = pb::GeneratedSingleExtension<$type_name$>.CreateInstance($scope$.Descriptor.Extensions[$index$]);\n"); - } -} - -void ExtensionGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { - printer->Print( - variables_, - "registry.Add($scope$.$property_name$);\n"); -} - -void ExtensionGenerator::WriteHash(io::Printer* printer) { -} - -void ExtensionGenerator::WriteEquals(io::Printer* printer) { -} - -void ExtensionGenerator::WriteToString(io::Printer* printer) { -} - -} // namespace csharp -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 4c6a3d72..7e3bbeef 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -35,13 +35,16 @@ #include <google/protobuf/compiler/plugin.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/mathlimits.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/wire_format.h> #include <google/protobuf/compiler/csharp/csharp_field_base.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> +#include <google/protobuf/compiler/csharp/csharp_names.h> using google::protobuf::internal::scoped_ptr; @@ -52,6 +55,23 @@ namespace csharp { void FieldGeneratorBase::SetCommonFieldVariables( map<string, string>* variables) { + // Note: this will be valid even though the tag emitted for packed and unpacked versions of + // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which + // never effects the tag size. + int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); + uint tag = FixedMakeTag(descriptor_); + uint8 tag_array[5]; + io::CodedOutputStream::WriteTagToArray(tag, tag_array); + string tag_bytes = SimpleItoa(tag_array[0]); + for (int i = 1; i < tag_size; i++) { + tag_bytes += ", " + SimpleItoa(tag_array[i]); + } + + (*variables)["access_level"] = class_access_level(); + (*variables)["tag"] = SimpleItoa(tag); + (*variables)["tag_size"] = SimpleItoa(tag_size); + (*variables)["tag_bytes"] = tag_bytes; + (*variables)["property_name"] = property_name(); (*variables)["type_name"] = type_name(); (*variables)["name"] = name(); @@ -65,16 +85,10 @@ void FieldGeneratorBase::SetCommonFieldVariables( } (*variables)["capitalized_type_name"] = capitalized_type_name(); (*variables)["number"] = number(); - (*variables)["field_ordinal"] = field_ordinal(); - if (SupportFieldPresence(descriptor_->file())) { - (*variables)["has_property_check"] = "has" + (*variables)["property_name"]; - (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"]; - } else { - (*variables)["has_property_check"] = - (*variables)["property_name"] + " != " + (*variables)["default_value"]; - (*variables)["other_has_property_check"] = "other." + - (*variables)["property_name"] + " != " + (*variables)["default_value"]; - } + (*variables)["has_property_check"] = + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + (*variables)["other_has_property_check"] = "other." + + (*variables)["property_name"] + " != " + (*variables)["default_value"]; } void FieldGeneratorBase::SetCommonOneofFieldVariables( @@ -96,21 +110,20 @@ FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor, FieldGeneratorBase::~FieldGeneratorBase() { } -void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) { - if (descriptor_->options().deprecated()) - { - printer->Print("[global::System.ObsoleteAttribute()]\n"); - } +void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) { + // No-op: only message fields and repeated fields need + // special handling for freezing, so default to not generating any code. } -void FieldGeneratorBase::AddNullCheck(io::Printer* printer) { - AddNullCheck(printer, "value"); +void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) { + // No-op: expect this to be overridden by appropriate types. + // Could fail if we get called here though... } -void FieldGeneratorBase::AddNullCheck(io::Printer* printer, const std::string& name) { - if (is_nullable_type()) { - printer->Print(" pb::ThrowHelper.ThrowIfNull($name$, \"$name$\");\n", - "name", name); +void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) { + if (descriptor_->options().deprecated()) + { + printer->Print("[global::System.ObsoleteAttribute()]\n"); } } @@ -135,12 +148,28 @@ std::string FieldGeneratorBase::name() { } std::string FieldGeneratorBase::type_name() { - switch (descriptor_->type()) { + return type_name(descriptor_); +} + +std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) { + switch (descriptor->type()) { case FieldDescriptor::TYPE_ENUM: - return GetClassName(descriptor_->enum_type()); + return GetClassName(descriptor->enum_type()); case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_GROUP: - return GetClassName(descriptor_->message_type()); + if (IsWrapperType(descriptor)) { + const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); + string wrapped_field_type_name = type_name(wrapped_field); + // String and ByteString go to the same type; other wrapped types go to the + // nullable equivalent. + if (wrapped_field->type() == FieldDescriptor::TYPE_STRING || + wrapped_field->type() == FieldDescriptor::TYPE_BYTES) { + return wrapped_field_type_name; + } else { + return wrapped_field_type_name + "?"; + } + } + return GetClassName(descriptor->message_type()); case FieldDescriptor::TYPE_DOUBLE: return "double"; case FieldDescriptor::TYPE_FLOAT: @@ -259,48 +288,33 @@ bool AllPrintableAscii(const std::string& text) { } std::string FieldGeneratorBase::GetStringDefaultValueInternal() { - if (!descriptor_->has_default_value()) { - return "\"\""; - } - if (AllPrintableAscii(descriptor_->default_value_string())) { - // All chars are ASCII and printable. In this case we only - // need to escape quotes and backslashes. - std::string temp = descriptor_->default_value_string(); - temp = StringReplace(temp, "\\", "\\\\", true); - temp = StringReplace(temp, "'", "\\'", true); - temp = StringReplace(temp, "\"", "\\\"", true); - return "\"" + temp + "\""; - } - if (use_lite_runtime()) { - return "pb::ByteString.FromBase64(\"" - + StringToBase64(descriptor_->default_value_string()) - + "\").ToStringUtf8()"; - } - return "(string) " + GetClassName(descriptor_->containing_type()) - + ".Descriptor.Fields[" + SimpleItoa(descriptor_->index()) - + "].DefaultValue"; + // No other default values needed for proto3... + return "\"\""; } std::string FieldGeneratorBase::GetBytesDefaultValueInternal() { - if (!descriptor_->has_default_value()) { - return "pb::ByteString.Empty"; - } - if (use_lite_runtime()) { - return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor_->default_value_string()) + "\")"; - } - return "(pb::ByteString) "+ GetClassName(descriptor_->containing_type()) + - ".Descriptor.Fields[" + SimpleItoa(descriptor_->index()) + "].DefaultValue"; + // No other default values needed for proto3... + return "pb::ByteString.Empty"; } std::string FieldGeneratorBase::default_value() { - switch (descriptor_->type()) { + return default_value(descriptor_); +} + +std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) { + switch (descriptor->type()) { case FieldDescriptor::TYPE_ENUM: - return type_name() + "." + descriptor_->default_value_enum()->name(); + return type_name() + "." + descriptor->default_value_enum()->name(); case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_GROUP: - return type_name() + ".DefaultInstance"; + if (IsWrapperType(descriptor)) { + const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); + return default_value(wrapped_field); + } else { + return "null"; + } case FieldDescriptor::TYPE_DOUBLE: { - double value = descriptor_->default_value_double(); + double value = descriptor->default_value_double(); if (value == numeric_limits<double>::infinity()) { return "double.PositiveInfinity"; } else if (value == -numeric_limits<double>::infinity()) { @@ -311,7 +325,7 @@ std::string FieldGeneratorBase::default_value() { return SimpleDtoa(value) + "D"; } case FieldDescriptor::TYPE_FLOAT: { - float value = descriptor_->default_value_float(); + float value = descriptor->default_value_float(); if (value == numeric_limits<float>::infinity()) { return "float.PositiveInfinity"; } else if (value == -numeric_limits<float>::infinity()) { @@ -322,17 +336,17 @@ std::string FieldGeneratorBase::default_value() { return SimpleFtoa(value) + "F"; } case FieldDescriptor::TYPE_INT64: - return SimpleItoa(descriptor_->default_value_int64()) + "L"; + return SimpleItoa(descriptor->default_value_int64()) + "L"; case FieldDescriptor::TYPE_UINT64: - return SimpleItoa(descriptor_->default_value_uint64()) + "UL"; + return SimpleItoa(descriptor->default_value_uint64()) + "UL"; case FieldDescriptor::TYPE_INT32: - return SimpleItoa(descriptor_->default_value_int32()); + return SimpleItoa(descriptor->default_value_int32()); case FieldDescriptor::TYPE_FIXED64: - return SimpleItoa(descriptor_->default_value_uint64()) + "UL"; + return SimpleItoa(descriptor->default_value_uint64()) + "UL"; case FieldDescriptor::TYPE_FIXED32: - return SimpleItoa(descriptor_->default_value_uint32()); + return SimpleItoa(descriptor->default_value_uint32()); case FieldDescriptor::TYPE_BOOL: - if (descriptor_->default_value_bool()) { + if (descriptor->default_value_bool()) { return "true"; } else { return "false"; @@ -342,15 +356,15 @@ std::string FieldGeneratorBase::default_value() { case FieldDescriptor::TYPE_BYTES: return GetBytesDefaultValueInternal(); case FieldDescriptor::TYPE_UINT32: - return SimpleItoa(descriptor_->default_value_uint32()); + return SimpleItoa(descriptor->default_value_uint32()); case FieldDescriptor::TYPE_SFIXED32: - return SimpleItoa(descriptor_->default_value_int32()); + return SimpleItoa(descriptor->default_value_int32()); case FieldDescriptor::TYPE_SFIXED64: - return SimpleItoa(descriptor_->default_value_int64()) + "L"; + return SimpleItoa(descriptor->default_value_int64()) + "L"; case FieldDescriptor::TYPE_SINT32: - return SimpleItoa(descriptor_->default_value_int32()); + return SimpleItoa(descriptor->default_value_int32()); case FieldDescriptor::TYPE_SINT64: - return SimpleItoa(descriptor_->default_value_int64()) + "L"; + return SimpleItoa(descriptor->default_value_int64()) + "L"; default: GOOGLE_LOG(FATAL)<< "Unknown field type."; return ""; @@ -361,11 +375,6 @@ std::string FieldGeneratorBase::number() { return SimpleItoa(descriptor_->number()); } -std::string FieldGeneratorBase::message_or_group() { - return - (descriptor_->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; -} - std::string FieldGeneratorBase::capitalized_type_name() { switch (descriptor_->type()) { case FieldDescriptor::TYPE_ENUM: @@ -410,10 +419,6 @@ std::string FieldGeneratorBase::capitalized_type_name() { } } -std::string FieldGeneratorBase::field_ordinal() { - return SimpleItoa(fieldOrdinal_); -} - } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index b1570587..d83543bd 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -42,23 +42,23 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class FieldGeneratorBase : public SourceGeneratorBase { public: FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal); ~FieldGeneratorBase(); + virtual void GenerateCloningCode(io::Printer* printer) = 0; + virtual void GenerateFreezingCode(io::Printer* printer); + virtual void GenerateCodecCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer) = 0; - virtual void GenerateBuilderMembers(io::Printer* printer) = 0; virtual void GenerateMergingCode(io::Printer* printer) = 0; - virtual void GenerateBuildingCode(io::Printer* printer) = 0; virtual void GenerateParsingCode(io::Printer* printer) = 0; virtual void GenerateSerializationCode(io::Printer* printer) = 0; virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0; virtual void WriteHash(io::Printer* printer) = 0; virtual void WriteEquals(io::Printer* printer) = 0; + // Currently unused, as we use reflection to generate JSON virtual void WriteToString(io::Printer* printer) = 0; protected: @@ -78,13 +78,13 @@ class FieldGeneratorBase : public SourceGeneratorBase { std::string property_name(); std::string name(); std::string type_name(); + std::string type_name(const FieldDescriptor* descriptor); bool has_default_value(); bool is_nullable_type(); std::string default_value(); + std::string default_value(const FieldDescriptor* descriptor); std::string number(); - std::string message_or_group(); std::string capitalized_type_name(); - std::string field_ordinal(); private: void SetCommonFieldVariables(map<string, string>* variables); diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index 2a416fac..e0a6c83a 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -50,7 +50,7 @@ namespace csharp { std::string GetOutputFile(const google::protobuf::FileDescriptor* file, const std::string file_extension) { - return GetFileUmbrellaClassname(file) + file_extension; + return GetUmbrellaClassUnqualifiedName(file) + file_extension; } void GenerateFile(const google::protobuf::FileDescriptor* file, @@ -68,6 +68,12 @@ bool Generator::Generate( vector<pair<string, string> > options; ParseGeneratorParameter(parameter, &options); + // We only support proto3 - but we make an exception for descriptor.proto. + if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) { + *error = "C# code generation only supports proto3 syntax"; + return false; + } + std::string file_extension = ".cs"; for (int i = 0; i < options.size(); i++) { if (options[i].first == "file_extension") { diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 76e2c850..46f4fc33 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -46,11 +46,13 @@ #include <google/protobuf/compiler/csharp/csharp_field_base.h> #include <google/protobuf/compiler/csharp/csharp_enum_field.h> +#include <google/protobuf/compiler/csharp/csharp_map_field.h> #include <google/protobuf/compiler/csharp/csharp_message_field.h> #include <google/protobuf/compiler/csharp/csharp_primitive_field.h> #include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h> #include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h> #include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h> +#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> namespace google { namespace protobuf { @@ -112,24 +114,21 @@ std::string GetFileNamespace(const FileDescriptor* descriptor) { if (descriptor->options().has_csharp_namespace()) { return descriptor->options().csharp_namespace(); } - return descriptor->package(); + return UnderscoresToCamelCase(descriptor->package(), true, true); } -std::string GetUmbrellaClassNameInternal(const std::string& proto_file) { +std::string GetUmbrellaClassUnqualifiedName(const FileDescriptor* descriptor) { + // umbrella_classname can no longer be set using message option. + std::string proto_file = descriptor->name(); int lastslash = proto_file.find_last_of("/"); std::string base = proto_file.substr(lastslash + 1); return UnderscoresToPascalCase(StripDotProto(base)); } -std::string GetFileUmbrellaClassname(const FileDescriptor* descriptor) { - // umbrella_classname can no longer be set using message option. - return GetUmbrellaClassNameInternal(descriptor->name()); -} - -std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor) { +std::string GetUmbrellaClassNestedNamespace(const FileDescriptor* descriptor) { // TODO(jtattermusch): reintroduce csharp_umbrella_namespace option bool collision = false; - std::string umbrella_classname = GetFileUmbrellaClassname(descriptor); + std::string umbrella_classname = GetUmbrellaClassUnqualifiedName(descriptor); for(int i = 0; i < descriptor->message_type_count(); i++) { if (descriptor->message_type(i)->name() == umbrella_classname) { collision = true; @@ -153,7 +152,8 @@ std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor) { // TODO(jtattermusch): can we reuse a utility function? std::string UnderscoresToCamelCase(const std::string& input, - bool cap_next_letter) { + bool cap_next_letter, + bool preserve_period) { string result; // Note: I distrust ctype.h due to locales. for (int i = 0; i < input.size(); i++) { @@ -179,6 +179,9 @@ std::string UnderscoresToCamelCase(const std::string& input, cap_next_letter = true; } else { cap_next_letter = true; + if (input[i] == '.' && preserve_period) { + result += '.'; + } } } // Add a trailing "_" if the name should be altered. @@ -205,30 +208,21 @@ std::string ToCSharpName(const std::string& name, const FileDescriptor* file) { // the C# namespace. classname = name.substr(file->package().size() + 1); } - result += StringReplace(classname, ".", ".Types.", false); + result += StringReplace(classname, ".", ".Types.", true); return "global::" + result; } - - -std::string GetFullUmbrellaClassName(const FileDescriptor* descriptor) { +std::string GetUmbrellaClassName(const FileDescriptor* descriptor) { std::string result = GetFileNamespace(descriptor); if (!result.empty()) { result += '.'; } - result += GetQualifiedUmbrellaClassName(descriptor); - return "global::" + result; -} - -std::string GetQualifiedUmbrellaClassName(const FileDescriptor* descriptor) { - std::string umbrellaNamespace = GetFileUmbrellaNamespace(descriptor); - std::string umbrellaClassname = GetFileUmbrellaClassname(descriptor); - - std::string fullName = umbrellaClassname; + std::string umbrellaNamespace = GetUmbrellaClassNestedNamespace(descriptor); if (!umbrellaNamespace.empty()) { - fullName = umbrellaNamespace + "." + umbrellaClassname; + result += umbrellaNamespace + "."; } - return fullName; + result += GetUmbrellaClassUnqualifiedName(descriptor); + return "global::" + result; } std::string GetClassName(const Descriptor* descriptor) { @@ -257,7 +251,13 @@ std::string GetFieldConstantName(const FieldDescriptor* field) { std::string GetPropertyName(const FieldDescriptor* descriptor) { // TODO(jtattermusch): consider introducing csharp_property_name field option std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor)); - if (property_name == descriptor->containing_type()->name()) { + // Avoid either our own type name or reserved names. Note that not all names + // are reserved - a field called to_string, write_to etc would still cause a problem. + // There are various ways of ending up with naming collisions, but we try to avoid obvious + // ones. + if (property_name == descriptor->containing_type()->name() + || property_name == "Types" + || property_name == "Descriptor") { property_name += "_"; } return property_name; @@ -338,84 +338,67 @@ std::string FileDescriptorToBase64(const FileDescriptor* descriptor) { return StringToBase64(fdp_bytes); } +// TODO(jonskeet): Remove this when internal::WireFormat::MakeTag works +// properly... +// Workaround for issue #493 +uint FixedMakeTag(const FieldDescriptor* field) { + internal::WireFormatLite::WireType field_type = field->is_packed() + ? internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED + : internal::WireFormat::WireTypeForFieldType(field->type()); + + return internal::WireFormatLite::MakeTag(field->number(), field_type); +} + FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) { switch (descriptor->type()) { case FieldDescriptor::TYPE_GROUP: case FieldDescriptor::TYPE_MESSAGE: if (descriptor->is_repeated()) { - return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal); + if (descriptor->is_map()) { + return new MapFieldGenerator(descriptor, fieldOrdinal); + } else { + return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal); + } } else { - if (descriptor->containing_oneof()) { - return new MessageOneofFieldGenerator(descriptor, fieldOrdinal); - } else { - return new MessageFieldGenerator(descriptor, fieldOrdinal); - } + if (IsWrapperType(descriptor)) { + if (descriptor->containing_oneof()) { + return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new WrapperFieldGenerator(descriptor, fieldOrdinal); + } + } else { + if (descriptor->containing_oneof()) { + return new MessageOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new MessageFieldGenerator(descriptor, fieldOrdinal); + } + } } case FieldDescriptor::TYPE_ENUM: if (descriptor->is_repeated()) { return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal); } else { - if (descriptor->containing_oneof()) { - return new EnumOneofFieldGenerator(descriptor, fieldOrdinal); - } else { - return new EnumFieldGenerator(descriptor, fieldOrdinal); - } + if (descriptor->containing_oneof()) { + return new EnumOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new EnumFieldGenerator(descriptor, fieldOrdinal); + } } default: if (descriptor->is_repeated()) { return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal); } else { - if (descriptor->containing_oneof()) { - return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal); - } else { - return new PrimitiveFieldGenerator(descriptor, fieldOrdinal); - } + if (descriptor->containing_oneof()) { + return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new PrimitiveFieldGenerator(descriptor, fieldOrdinal); + } } } } -bool HasRequiredFields(const Descriptor* descriptor, std::set<const Descriptor*>* already_seen) { - if (already_seen->find(descriptor) != already_seen->end()) { - // The type is already in cache. This means that either: - // a. The type has no required fields. - // b. We are in the midst of checking if the type has required fields, - // somewhere up the stack. In this case, we know that if the type - // has any required fields, they'll be found when we return to it, - // and the whole call to HasRequiredFields() will return true. - // Therefore, we don't have to check if this type has required fields - // here. - return false; - } - already_seen->insert(descriptor); - - // If the type has extensions, an extension with message type could contain - // required fields, so we have to be conservative and assume such an - // extension exists. - if (descriptor->extension_count() > 0) { - return true; - } - - for (int i = 0; i < descriptor->field_count(); i++) { - const FieldDescriptor* field = descriptor->field(i); - if (field->is_required()) { - return true; - } - if (GetCSharpType(field->type()) == CSHARPTYPE_MESSAGE) { - if (HasRequiredFields(field->message_type(), already_seen)) { - return true; - } - } - } - return false; -} - -bool HasRequiredFields(const Descriptor* descriptor) { - std::set<const Descriptor*> already_seen; - return HasRequiredFields(descriptor, &already_seen); -} - -} // namespace java +} // namespace csharp } // namespace compiler } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index bc77f43a..1d17af61 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -69,15 +69,15 @@ CSharpType GetCSharpType(FieldDescriptor::Type type); std::string StripDotProto(const std::string& proto_file); -std::string GetFileNamespace(const FileDescriptor* descriptor); -std::string GetFileUmbrellaClassname(const FileDescriptor* descriptor); -std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor); +// Gets unqualified name of the umbrella class +std::string GetUmbrellaClassUnqualifiedName(const FileDescriptor* descriptor); -std::string GetFullUmbrellaClassName(const FileDescriptor* descriptor); - -std::string GetQualifiedUmbrellaClassName(const FileDescriptor* descriptor); +// Gets name of the nested for umbrella class (just the nested part, +// not including the GetFileNamespace part). +std::string GetUmbrellaClassNestedNamespace(const FileDescriptor* descriptor); std::string GetClassName(const Descriptor* descriptor); + std::string GetClassName(const EnumDescriptor* descriptor); std::string GetFieldName(const FieldDescriptor* descriptor); @@ -88,7 +88,11 @@ std::string GetPropertyName(const FieldDescriptor* descriptor); int GetFixedSize(FieldDescriptor::Type type); -std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter); +std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter, bool preserve_period); + +inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) { + return UnderscoresToCamelCase(input, cap_next_letter, false); +} std::string UnderscoresToPascalCase(const std::string& input); @@ -97,12 +101,28 @@ std::string StringToBase64(const std::string& input); std::string FileDescriptorToBase64(const FileDescriptor* descriptor); +uint FixedMakeTag(const FieldDescriptor* descriptor); + FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); -bool HasRequiredFields(const Descriptor* descriptor); +// Determines whether the given message is a map entry message, i.e. one implicitly created +// by protoc due to a map<key, value> field. +inline bool IsMapEntryMessage(const Descriptor* descriptor) { + return descriptor->options().map_entry(); +} + +// Determines whether we're generating code for the proto representation of descriptors etc, +// for use in the runtime. This is the only type which is allowed to use proto2 syntax, +// and it generates internal classes. +inline bool IsDescriptorProto(const FileDescriptor* descriptor) { + // TODO: Do this better! (Currently this depends on a hack in generate_protos.sh to rename + // the file...) + return descriptor->name() == "google/protobuf/descriptor_proto_file.proto"; +} -inline bool SupportFieldPresence(const FileDescriptor* file) { - return file->syntax() != FileDescriptor::SYNTAX_PROTO3; +inline bool IsWrapperType(const FieldDescriptor* descriptor) { + return descriptor->type() == FieldDescriptor::TYPE_MESSAGE && + descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto"; } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc new file mode 100644 index 00000000..f84ad6f7 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc @@ -0,0 +1,137 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <sstream> + +#include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/compiler/plugin.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/stubs/strutil.h> + +#include <google/protobuf/compiler/csharp/csharp_helpers.h> +#include <google/protobuf/compiler/csharp/csharp_map_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : FieldGeneratorBase(descriptor, fieldOrdinal) { +} + +MapFieldGenerator::~MapFieldGenerator() { +} + +void MapFieldGenerator::GenerateMembers(io::Printer* printer) { + const FieldDescriptor* key_descriptor = + descriptor_->message_type()->FindFieldByName("key"); + const FieldDescriptor* value_descriptor = + descriptor_->message_type()->FindFieldByName("value"); + variables_["key_type_name"] = type_name(key_descriptor); + variables_["value_type_name"] = type_name(value_descriptor); + variables_["true_for_wrappers"] = IsWrapperType(value_descriptor) ? "true" : ""; + scoped_ptr<FieldGeneratorBase> key_generator(CreateFieldGenerator(key_descriptor, 1)); + scoped_ptr<FieldGeneratorBase> value_generator(CreateFieldGenerator(value_descriptor, 2)); + + printer->Print( + variables_, + "private static readonly pbc::MapField<$key_type_name$, $value_type_name$>.Codec _map_$name$_codec\n" + " = new pbc::MapField<$key_type_name$, $value_type_name$>.Codec("); + key_generator->GenerateCodecCode(printer); + printer->Print(", "); + value_generator->GenerateCodecCode(printer); + printer->Print( + variables_, + ", $tag$);\n" + "private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>($true_for_wrappers$);\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n" + " get { return $name$_; }\n" + "}\n"); +} + +void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "$name$_.Add(other.$name$_);\n"); +} + +void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n"); +} + +void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "$name$_.WriteTo(output, _map_$name$_codec);\n"); +} + +void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "size += $name$_.CalculateSize(_map_$name$_codec);\n"); +} + +void MapFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "hash ^= $property_name$.GetHashCode();\n"); +} +void MapFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); +} + +void MapFieldGenerator::WriteToString(io::Printer* printer) { + // TODO: If we ever actually use ToString, we'll need to impleme this... +} + +void MapFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_ = other.$name$_.Clone();\n"); +} + +void MapFieldGenerator::GenerateFreezingCode(io::Printer* printer) { +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h index f251a21c..f33fe1c3 100644 --- a/src/google/protobuf/compiler/csharp/csharp_extension.h +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h @@ -28,8 +28,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ -#define GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__ #include <string> @@ -41,32 +41,25 @@ namespace protobuf { namespace compiler { namespace csharp { -class ExtensionGenerator : public FieldGeneratorBase { +class MapFieldGenerator : public FieldGeneratorBase { public: - ExtensionGenerator(const FieldDescriptor* descriptor); - ~ExtensionGenerator(); + MapFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~MapFieldGenerator(); - void GenerateStaticVariableInitializers(io::Printer* printer); - void GenerateExtensionRegistrationCode(io::Printer* printer); - void Generate(io::Printer* printer); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); virtual void WriteHash(io::Printer* printer); virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); - virtual void GenerateMembers(io::Printer* printer) {}; - virtual void GenerateBuilderMembers(io::Printer* printer) {}; - virtual void GenerateMergingCode(io::Printer* printer) {}; - virtual void GenerateBuildingCode(io::Printer* printer) {}; - virtual void GenerateParsingCode(io::Printer* printer) {}; - virtual void GenerateSerializationCode(io::Printer* printer) {}; - virtual void GenerateSerializedSizeCode(io::Printer* printer) {}; - private: - std::string scope_; - std::string extends_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); }; } // namespace csharp @@ -74,5 +67,5 @@ class ExtensionGenerator : public FieldGeneratorBase { } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 66b87110..6ea568ca 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -43,10 +43,10 @@ #include <google/protobuf/wire_format_lite.h> #include <google/protobuf/compiler/csharp/csharp_enum.h> -#include <google/protobuf/compiler/csharp/csharp_extension.h> -#include <google/protobuf/compiler/csharp/csharp_message.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_field_base.h> +#include <google/protobuf/compiler/csharp/csharp_helpers.h> +#include <google/protobuf/compiler/csharp/csharp_message.h> +#include <google/protobuf/compiler/csharp/csharp_names.h> using google::protobuf::internal::scoped_ptr; @@ -96,197 +96,88 @@ const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() return fields_by_number_; } -/// Get an identifier that uniquely identifies this type within the file. -/// This is used to declare static variables related to this type at the -/// outermost file scope. -std::string GetUniqueFileScopeIdentifier(const Descriptor* descriptor) { - std::string result = descriptor->full_name(); - std::replace(result.begin(), result.end(), '.', '_'); - return "static_" + result; -} - -void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { - // Because descriptor.proto (Google.ProtocolBuffers.DescriptorProtos) is - // used in the construction of descriptors, we have a tricky bootstrapping - // problem. To help control static initialization order, we make sure all - // descriptors and other static data that depends on them are members of - // the proto-descriptor class. This way, they will be initialized in - // a deterministic order. - - std::string identifier = GetUniqueFileScopeIdentifier(descriptor_); - - if (!use_lite_runtime()) { - // The descriptor for this type. - printer->Print( - "internal static pbd::MessageDescriptor internal__$identifier$__Descriptor;\n" - "internal static pb::FieldAccess.FieldAccessorTable<$full_class_name$, $full_class_name$.Builder> internal__$identifier$__FieldAccessorTable;\n", - "identifier", GetUniqueFileScopeIdentifier(descriptor_), - "full_class_name", full_class_name()); - } - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateStaticVariables(printer); - } -} - -void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer) { - map<string, string> vars; - vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_); - vars["index"] = SimpleItoa(descriptor_->index()); - vars["full_class_name"] = full_class_name(); - if (descriptor_->containing_type() != NULL) { - vars["parent"] = GetUniqueFileScopeIdentifier( - descriptor_->containing_type()); - } - if (!use_lite_runtime()) { - printer->Print(vars, "internal__$identifier$__Descriptor = "); - - if (!descriptor_->containing_type()) { - printer->Print(vars, "Descriptor.MessageTypes[$index$];\n"); - } else { - printer->Print(vars, "internal__$parent$__Descriptor.NestedTypes[$index$];\n"); - } - - printer->Print( - vars, - "internal__$identifier$__FieldAccessorTable = \n" - " new pb::FieldAccess.FieldAccessorTable<$full_class_name$, $full_class_name$.Builder>(internal__$identifier$__Descriptor,\n"); - printer->Print(" new string[] { "); - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print("\"$property_name$\", ", - "property_name", GetPropertyName(descriptor_->field(i))); - } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("\"$oneof_name$\", ", - "oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - } - printer->Print("});\n"); - } - - // Generate static member initializers for all nested types. - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateStaticVariableInitializers(printer); - } - - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(printer); - } -} - void MessageGenerator::Generate(io::Printer* printer) { map<string, string> vars; vars["class_name"] = class_name(); vars["access_level"] = class_access_level(); - vars["extendable_or_generated"] = descriptor_->extension_range_count() > 0 ? - "Extendable" : "Generated"; - vars["suffix"] = runtime_suffix(); - vars["umbrella_class_name"] = GetFullUmbrellaClassName(descriptor_->file()); - vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_); printer->Print( - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); WriteGeneratedCodeAttributes(printer); printer->Print( vars, - "$access_level$ sealed partial class $class_name$ : pb::$extendable_or_generated$Message$suffix$<$class_name$, $class_name$.Builder> {\n"); + "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n"); printer->Indent(); + + // All static fields and properties printer->Print( - vars, - "private $class_name$() { }\n" // Private ctor. - // Must call MakeReadOnly() to make sure all lists are made read-only - "private static readonly $class_name$ defaultInstance = new $class_name$().MakeReadOnly();\n"); + vars, + "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n" + "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n"); - if (optimize_speed()) { - printer->Print( - "private static readonly string[] _$name$FieldNames = " - "new string[] { $slash$$field_names$$slash$ };\n", - "name", UnderscoresToCamelCase(class_name(), false), - "field_names", JoinStrings(field_names(), "\", \""), - "slash", field_names().size() > 0 ? "\"" : ""); - std::vector<std::string> tags; - for (int i = 0; i < field_names().size(); i++) { - uint32 tag = internal::WireFormat::MakeTag( - descriptor_->FindFieldByName(field_names()[i])); - tags.push_back(SimpleItoa(tag)); - } - printer->Print( - "private static readonly uint[] _$name$FieldTags = new uint[] { $tags$ };\n", - "name", UnderscoresToCamelCase(class_name(), false), - "tags", JoinStrings(tags, ", ")); + // Access the message descriptor via the relevant file descriptor or containing message descriptor. + if (!descriptor_->containing_type()) { + vars["descriptor_accessor"] = GetUmbrellaClassName(descriptor_->file()) + + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]"; + } else { + vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type()) + + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]"; } + printer->Print( vars, - "public static $class_name$ DefaultInstance {\n" - " get { return defaultInstance; }\n" + "public static pbr::MessageDescriptor Descriptor {\n" + " get { return $descriptor_accessor$; }\n" "}\n" "\n" - "public override $class_name$ DefaultInstanceForType {\n" - " get { return DefaultInstance; }\n" + "pbr::MessageDescriptor pb::IMessage.Descriptor {\n" + " get { return Descriptor; }\n" "}\n" - "\n" - "protected override $class_name$ ThisMessage {\n" - " get { return this; }\n" - "}\n\n"); + "\n"); - if (!use_lite_runtime()) { - printer->Print( - vars, - "public static pbd::MessageDescriptor Descriptor {\n" - " get { return $umbrella_class_name$.internal__$identifier$__Descriptor; }\n" - "}\n" - "\n" - "protected override pb::FieldAccess.FieldAccessorTable<$class_name$, $class_name$.Builder> InternalFieldAccessors {\n" - " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n" - "}\n" - "\n"); - } + // Parameterless constructor and partial OnConstruction method. + printer->Print( + vars, + "public $class_name$() {\n" + " OnConstruction();\n" + "}\n\n" + "partial void OnConstruction();\n\n"); - // Extensions don't need to go in an extra nested type - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.Generate(printer); - } + GenerateCloningCode(printer); + GenerateFreezingCode(printer); - if (descriptor_->enum_type_count() + descriptor_->nested_type_count() > 0) { - printer->Print("#region Nested types\n" - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print("public static partial class Types {\n"); - printer->Indent(); - for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator enumGenerator(descriptor_->enum_type(i)); - enumGenerator.Generate(printer); - } - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.Generate(printer); - } - printer->Outdent(); - printer->Print("}\n" - "#endregion\n" - "\n"); + // Fields/properties + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + + // Rats: we lose the debug comment here :( + printer->Print( + "public const int $field_constant_name$ = $index$;\n", + "field_constant_name", GetFieldConstantName(fieldDescriptor), + "index", SimpleItoa(fieldDescriptor->number())); + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(fieldDescriptor)); + generator->GenerateMembers(printer); + printer->Print("\n"); } - // oneof + // oneof properties for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + vars["original_name"] = descriptor_->oneof_decl(i)->name(); printer->Print( vars, "private object $name$_;\n" "public enum $property_name$OneofCase {\n"); printer->Indent(); + printer->Print("None = 0,\n"); for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); printer->Print("$field_property_name$ = $index$,\n", "field_property_name", GetPropertyName(field), "index", SimpleItoa(field->number())); } - printer->Print("None = 0,\n"); printer->Outdent(); printer->Print("}\n"); printer->Print( @@ -294,243 +185,192 @@ void MessageGenerator::Generate(io::Printer* printer) { "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n" "public $property_name$OneofCase $property_name$Case {\n" " get { return $name$Case_; }\n" + "}\n\n" + "public void Clear$property_name$() {\n" + " $name$Case_ = $property_name$OneofCase.None;\n" + " $name$_ = null;\n" "}\n\n"); } - // Fields - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + // Standard methods + GenerateFrameworkMethods(printer); + GenerateMessageSerializationMethods(printer); + GenerateMergingMethods(printer); - // Rats: we lose the debug comment here :( - printer->Print( - "public const int $field_constant_name$ = $index$;\n", - "field_constant_name", GetFieldConstantName(fieldDescriptor), - "index", SimpleItoa(fieldDescriptor->number())); - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(fieldDescriptor)); - generator->GenerateMembers(printer); - printer->Print("\n"); - } - - if (optimize_speed()) { - if (SupportFieldPresence(descriptor_->file())) { - GenerateIsInitialized(printer); + // Nested messages and enums + if (HasNestedGeneratedTypes()) { + printer->Print("#region Nested types\n" + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print("public static partial class Types {\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + EnumGenerator enumGenerator(descriptor_->enum_type(i)); + enumGenerator.Generate(printer); } - GenerateMessageSerializationMethods(printer); - } - if (use_lite_runtime()) { - GenerateLiteRuntimeMethods(printer); + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // Don't generate nested types for maps... + if (!IsMapEntryMessage(descriptor_->nested_type(i))) { + MessageGenerator messageGenerator(descriptor_->nested_type(i)); + messageGenerator.Generate(printer); + } + } + printer->Outdent(); + printer->Print("}\n" + "#endregion\n" + "\n"); } - GenerateParseFromMethods(printer); - GenerateBuilder(printer); - - // Force the static initialization code for the file to run, since it may - // initialize static variables declared in this class. - printer->Print(vars, "static $class_name$() {\n"); - // We call object.ReferenceEquals() just to make it a valid statement on its own. - // Another option would be GetType(), but that causes problems in DescriptorProtoFile, - // where the bootstrapping is somewhat recursive - type initializers call - // each other, effectively. We temporarily see Descriptor as null. - printer->Print( - vars, - " object.ReferenceEquals($umbrella_class_name$.Descriptor, null);\n" - "}\n"); - printer->Outdent(); printer->Print("}\n"); printer->Print("\n"); +} +// Helper to work out whether we need to generate a class to hold nested types/enums. +// Only tricky because we don't want to generate map entry types. +bool MessageGenerator::HasNestedGeneratedTypes() +{ + if (descriptor_->enum_type_count() > 0) { + return true; + } + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + if (!IsMapEntryMessage(descriptor_->nested_type(i))) { + return true; + } + } + return false; } -void MessageGenerator::GenerateLiteRuntimeMethods(io::Printer* printer) { +void MessageGenerator::GenerateCloningCode(io::Printer* printer) { map<string, string> vars; vars["class_name"] = class_name(); - - bool callbase = descriptor_->extension_range_count() > 0; - printer->Print("#region Lite runtime methods\n" - "public override int GetHashCode() {\n"); + printer->Print( + vars, + "public $class_name$($class_name$ other) : this() {\n"); printer->Indent(); - printer->Print("int hash = GetType().GetHashCode();\n"); + // Clone non-oneof fields first for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() == NULL) { + if (!descriptor_->field(i)->containing_oneof()) { scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(field)); - generator->WriteHash(printer); + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->GenerateCloningCode(printer); } } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - printer->Print( - "if ($name$Case_ != $property_name$OneofCase.None) {\n" - " hash ^= $name$_.GetHashCode();\n" - "}\n", - "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false), - "property_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - } - if (callbase) { - printer->Print("hash ^= base.GetHashCode();\n"); + // Clone just the right field for each oneof + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + printer->Print(vars, "switch (other.$property_name$Case) {\n"); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + scoped_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field)); + vars["field_property_name"] = GetPropertyName(field); + printer->Print( + vars, + "case $property_name$OneofCase.$field_property_name$:\n"); + printer->Indent(); + generator->GenerateCloningCode(printer); + printer->Print("break;\n"); + printer->Outdent(); + } + printer->Outdent(); + printer->Print("}\n\n"); } - printer->Print("return hash;\n"); + printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); + printer->Print("}\n\n"); - printer->Print("public override bool Equals(object obj) {\n"); - printer->Indent(); printer->Print( vars, - "$class_name$ other = obj as $class_name$;\n" - "if (other == null) return false;\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->WriteEquals(printer); - } - if (callbase) { - printer->Print("if (!base.Equals(other)) return false;\n"); - } - printer->Print("return true;\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); + "public $class_name$ Clone() {\n" + " return new $class_name$(this);\n" + "}\n\n"); +} - printer->Print( - "public override void PrintTo(global::System.IO.TextWriter writer) {\n"); - printer->Indent(); +void MessageGenerator::GenerateFreezingCode(io::Printer* printer) { +} - for (int i = 0; i < fields_by_number().size(); i++) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(fields_by_number()[i])); - generator->WriteToString(printer); - } +void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { + map<string, string> vars; + vars["class_name"] = class_name(); - if (callbase) { - printer->Print("base.PrintTo(writer);\n"); - } - printer->Outdent(); - printer->Print("}\n"); - printer->Print("#endregion\n"); - printer->Print("\n"); -} + // Equality + printer->Print( + vars, + "public override bool Equals(object other) {\n" + " return Equals(other as $class_name$);\n" + "}\n\n" + "public bool Equals($class_name$ other) {\n" + " if (ReferenceEquals(other, null)) {\n" + " return false;\n" + " }\n" + " if (ReferenceEquals(other, this)) {\n" + " return true;\n" + " }\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteEquals(printer); + } + printer->Outdent(); + printer->Print( + " return true;\n" + "}\n\n"); + + // GetHashCode + // Start with a non-zero value to easily distinguish between null and "empty" messages. + printer->Print( + "public override int GetHashCode() {\n" + " int hash = 1;\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteHash(printer); + } + printer->Print("return hash;\n"); + printer->Outdent(); + printer->Print("}\n\n"); -bool CompareExtensionRangesStart(const Descriptor::ExtensionRange* r1, - const Descriptor::ExtensionRange* r2) { - return r1->start < r2->start; + printer->Print( + "public override string ToString() {\n" + " return pb::JsonFormatter.Default.Format(this);\n" + "}\n\n"); } void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) { - std::vector<const Descriptor::ExtensionRange*> extension_ranges_sorted; - for (int i = 0; i < descriptor_->extension_range_count(); i++) { - extension_ranges_sorted.push_back(descriptor_->extension_range(i)); - } - std::sort(extension_ranges_sorted.begin(), extension_ranges_sorted.end(), - CompareExtensionRangesStart); - printer->Print( - "public override void WriteTo(pb::ICodedOutputStream output) {\n"); + "public void WriteTo(pb::CodedOutputStream output) {\n"); printer->Indent(); - // Make sure we've computed the serialized length, so that packed fields are generated correctly. - printer->Print("CalcSerializedSize();\n" - "string[] field_names = _$class_name$FieldNames;\n", - "class_name", UnderscoresToCamelCase(class_name(), false)); - if (descriptor_->extension_range_count()) { - printer->Print( - "pb::ExtendableMessage$runtime_suffix$<$class_name$, $class_name$.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);\n", - "class_name", class_name(), - "runtime_suffix", runtime_suffix()); - } - - // Merge the fields and the extension ranges, both sorted by field number. - for (int i = 0, j = 0; - i < fields_by_number().size() || j < extension_ranges_sorted.size();) { - if (i == fields_by_number().size()) { - GenerateSerializeOneExtensionRange(printer, extension_ranges_sorted[j++]); - } else if (j == extension_ranges_sorted.size()) { - GenerateSerializeOneField(printer, fields_by_number()[i++]); - } else if (fields_by_number()[i]->number() - < extension_ranges_sorted[j]->start) { - GenerateSerializeOneField(printer, fields_by_number()[i++]); - } else { - GenerateSerializeOneExtensionRange(printer, extension_ranges_sorted[j++]); - } - } - if (!use_lite_runtime()) { - if (descriptor_->options().message_set_wire_format()) - { - printer->Print("UnknownFields.WriteAsMessageSetTo(output);\n"); - } else { - printer->Print("UnknownFields.WriteTo(output);\n"); - } + // Serialize all the fields + for (int i = 0; i < fields_by_number().size(); i++) { + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(fields_by_number()[i])); + generator->GenerateSerializationCode(printer); } + // TODO(jonskeet): Memoize size of frozen messages? printer->Outdent(); printer->Print( "}\n" "\n" - "private int memoizedSerializedSize = -1;\n" - "public override int SerializedSize {\n"); - printer->Indent(); - printer->Print("get {\n"); - printer->Indent(); - printer->Print( - "int size = memoizedSerializedSize;\n" - "if (size != -1) return size;\n" - "return CalcSerializedSize();\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); - - printer->Print("private int CalcSerializedSize() {\n"); + "public int CalculateSize() {\n"); printer->Indent(); - printer->Print( - "int size = memoizedSerializedSize;\n" - "if (size != -1) return size;\n" - "\n" - "size = 0;\n"); + printer->Print("int size = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { scoped_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(descriptor_->field(i))); generator->GenerateSerializedSizeCode(printer); } - if (descriptor_->extension_range_count() > 0) { - printer->Print("size += ExtensionsSerializedSize;\n"); - } - - if (!use_lite_runtime()) { - if (descriptor_->options().message_set_wire_format()) { - printer->Print("size += UnknownFields.SerializedSizeAsMessageSet;\n"); - } else { - printer->Print("size += UnknownFields.SerializedSize;\n"); - } - } - printer->Print( - "memoizedSerializedSize = size;\n" - "return size;\n"); + printer->Print("return size;\n"); printer->Outdent(); - printer->Print("}\n"); -} - -void MessageGenerator::GenerateSerializeOneField( - io::Printer* printer, const FieldDescriptor* fieldDescriptor) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(fieldDescriptor)); - generator->GenerateSerializationCode(printer); -} - -void MessageGenerator::GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* extensionRange) { - printer->Print("extensionWriter.WriteUntil($range_end$, output);\n", - "range_end", SimpleItoa(extensionRange->end)); + printer->Print("}\n\n"); } -void MessageGenerator::GenerateParseFromMethods(io::Printer* printer) { +void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized // for code size. @@ -539,346 +379,69 @@ void MessageGenerator::GenerateParseFromMethods(io::Printer* printer) { printer->Print( vars, - "public static $class_name$ ParseFrom(pb::ByteString data) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(byte[] data) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(global::System.IO.Stream input) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseDelimitedFrom(global::System.IO.Stream input) {\n" - " return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {\n" - " return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(pb::ICodedInputStream input) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();\n" - "}\n"); -} - -void MessageGenerator::GenerateBuilder(io::Printer* printer) { - map<string, string> vars; - vars["class_name"] = class_name(); - vars["access_level"] = class_access_level(); - vars["extendable_or_generated"] = descriptor_->extension_range_count() > 0 ? - "Extendable" : "Generated"; - vars["suffix"] = runtime_suffix(); - - printer->Print(vars, "private $class_name$ MakeReadOnly() {\n"); + "public void MergeFrom($class_name$ other) {\n"); printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateBuildingCode(printer); - } - printer->Print("return this;\n"); - printer->Outdent(); - printer->Print("}\n\n"); - printer->Print( - vars, - "public static Builder CreateBuilder() { return new Builder(); }\n" - "public override Builder ToBuilder() { return CreateBuilder(this); }\n" - "public override Builder CreateBuilderForType() { return new Builder(); }\n" - "public static Builder CreateBuilder($class_name$ prototype) {\n" - " return new Builder(prototype);\n" - "}\n" - "\n" - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "$access_level$ sealed partial class Builder : pb::$extendable_or_generated$Builder$suffix$<$class_name$, Builder> {\n"); - printer->Indent(); - printer->Print( - "protected override Builder ThisBuilder {\n" - " get { return this; }\n" + "if (other == null) {\n" + " return;\n" "}\n"); - GenerateCommonBuilderMethods(printer); - if (optimize_speed()) { - GenerateBuilderParsingMethods(printer); - } + // Merge non-oneof fields for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - printer->Print("\n"); - // No field comment :( - generator->GenerateBuilderMembers(printer); - } - - // oneof - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("\n"); - string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - printer->Print( - "public $property_name$OneofCase $property_name$Case {\n" - " get { return result.$name$Case_; }\n" - "}\n" - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_ = null;\n" - " result.$name$Case_ = $property_name$OneofCase.None;\n" - " return this;\n" - "}\n", - "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false), - "property_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - } - - printer->Outdent(); - printer->Print("}\n"); -} - -void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { - map<string, string> vars; - vars["class_name"] = class_name(); - vars["full_class_name"] = full_class_name(); - vars["suffix"] = runtime_suffix(); - - printer->Print( - vars, - //default constructor - "public Builder() {\n" - //Durring static initialization of message, DefaultInstance is expected to return null. - " result = DefaultInstance;\n" - " resultIsReadOnly = true;\n" - "}\n" - //clone constructor - "internal Builder($class_name$ cloneFrom) {\n" - " result = cloneFrom;\n" - " resultIsReadOnly = true;\n" - "}\n" - "\n" - "private bool resultIsReadOnly;\n" - "private $class_name$ result;\n" - "\n" - "private $class_name$ PrepareBuilder() {\n" - " if (resultIsReadOnly) {\n" - " $class_name$ original = result;\n" - " result = new $class_name$();\n" - " resultIsReadOnly = false;\n" - " MergeFrom(original);\n" - " }\n" - " return result;\n" - "}\n" - "\n" - "public override bool IsInitialized {\n" - " get { return result.IsInitialized; }\n" - "}\n" - "\n" - "protected override $class_name$ MessageBeingBuilt {\n" - " get { return PrepareBuilder(); }\n" - "}\n" - "\n"); - //Not actually expecting that DefaultInstance would ever be null here; however, we will ensure it does not break - printer->Print( - "public override Builder Clear() {\n" - " result = DefaultInstance;\n" - " resultIsReadOnly = true;\n" - " return this;\n" - "}\n" - "\n" - "public override Builder Clone() {\n" - " if (resultIsReadOnly) {\n" - " return new Builder(result);\n" - " } else {\n" - " return new Builder().MergeFrom(result);\n" - " }\n" - "}\n" - "\n"); - if (!use_lite_runtime()) { - printer->Print( - vars, - "public override pbd::MessageDescriptor DescriptorForType {\n" - " get { return $full_class_name$.Descriptor; }\n" - "}\n\n"); + if (!descriptor_->field(i)->containing_oneof()) { + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->GenerateMergingCode(printer); + } } - printer->Print( - vars, - "public override $class_name$ DefaultInstanceForType {\n" - " get { return $full_class_name$.DefaultInstance; }\n" - "}\n\n"); - - printer->Print( - vars, - "public override $class_name$ BuildPartial() {\n" - " if (resultIsReadOnly) {\n" - " return result;\n" - " }\n" - " resultIsReadOnly = true;\n" - " return result.MakeReadOnly();\n" - "}\n\n"); - - if (optimize_speed()) { - printer->Print( - vars, - "public override Builder MergeFrom(pb::IMessage$suffix$ other) {\n" - " if (other is $class_name$) {\n" - " return MergeFrom(($class_name$) other);\n" - " } else {\n" - " base.MergeFrom(other);\n" - " return this;\n" - " }\n" - "}\n\n"); - - printer->Print(vars,"public override Builder MergeFrom($class_name$ other) {\n"); - // Optimization: If other is the default instance, we know none of its - // fields are set so we can skip the merge. + // Merge oneof fields + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + printer->Print(vars, "switch (other.$property_name$Case) {\n"); printer->Indent(); - printer->Print( - vars, - "if (other == $full_class_name$.DefaultInstance) return this;\n" - "PrepareBuilder();\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - scoped_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateMergingCode(printer); - } - } - - // Merge oneof fields - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - printer->Print(vars, "switch (other.$property_name$Case) {\n"); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - vars["field_property_name"] = GetPropertyName(field); - printer->Print( - vars, - "case $property_name$OneofCase.$field_property_name$: {\n"); - if (field->type() == FieldDescriptor::TYPE_GROUP || - field->type() == FieldDescriptor::TYPE_MESSAGE) { - printer->Print( - vars, - " Merge$field_property_name$(other.$field_property_name$);\n"); - } else { - printer->Print( - vars, - " Set$field_property_name$(other.$field_property_name$);\n"); - } - printer->Print(" break;\n"); - printer->Print("}\n"); - } - printer->Print(vars, "case $property_name$OneofCase.None: { break; }\n"); - printer->Outdent(); - printer->Print("}\n"); - } - - // if message type has extensions - if (descriptor_->extension_range_count() > 0) { - printer->Print(" this.MergeExtensionFields(other);\n"); - } - if (!use_lite_runtime()) { - printer->Print("this.MergeUnknownFields(other.UnknownFields);\n"); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + vars["field_property_name"] = GetPropertyName(field); + printer->Print( + vars, + "case $property_name$OneofCase.$field_property_name$:\n" + " $field_property_name$ = other.$field_property_name$;\n" + " break;\n"); } - printer->Print("return this;\n"); printer->Outdent(); printer->Print("}\n\n"); } - -} - -void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { - printer->Print( - "public override Builder MergeFrom(pb::ICodedInputStream input) {\n" - " return MergeFrom(input, pb::ExtensionRegistry.Empty);\n" - "}\n\n"); - - printer->Print( - "public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\n"); + printer->Outdent(); + printer->Print("}\n\n"); + printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n"); printer->Indent(); - printer->Print("PrepareBuilder();\n"); - if (!use_lite_runtime()) { - printer->Print("pb::UnknownFieldSet.Builder unknownFields = null;\n"); - } printer->Print( "uint tag;\n" - "string field_name;\n" - "while (input.ReadTag(out tag, out field_name)) {\n"); - printer->Indent(); - printer->Print("if(tag == 0 && field_name != null) {\n"); + "while (input.ReadTag(out tag)) {\n" + " switch(tag) {\n"); printer->Indent(); - //if you change from StringComparer.Ordinal, the array sort in FieldNames { get; } must also change - printer->Print( - "int field_ordinal = global::System.Array.BinarySearch(_$camel_class_name$FieldNames, field_name, global::System.StringComparer.Ordinal);\n" - "if(field_ordinal >= 0)\n" - " tag = _$camel_class_name$FieldTags[field_ordinal];\n" - "else {\n", - "camel_class_name", UnderscoresToCamelCase(class_name(), false)); - if (!use_lite_runtime()) { - printer->Print( - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n"); - } - printer->Print( - " ParseUnknownField(input, $prefix$extensionRegistry, tag, field_name);\n", - "prefix", use_lite_runtime() ? "" : "unknownFields, "); - printer->Print(" continue;\n"); - printer->Print("}\n"); - printer->Outdent(); - printer->Print("}\n"); - - printer->Print("switch (tag) {\n"); printer->Indent(); printer->Print( - "case 0: {\n" // 0 signals EOF / limit reached + "case 0:\n" // 0 signals EOF / limit reached " throw pb::InvalidProtocolBufferException.InvalidTag();\n" - "}\n" - "default: {\n" - " if (pb::WireFormat.IsEndGroupTag(tag)) {\n"); - if (!use_lite_runtime()) { - printer->Print( - " if (unknownFields != null) {\n" - " this.UnknownFields = unknownFields.Build();\n" - " }\n"); - } - printer->Print( - " return this;\n" // it's an endgroup tag - " }\n"); - if (!use_lite_runtime()) { - printer->Print( - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n"); - } - printer->Print( - " ParseUnknownField(input, $prefix$extensionRegistry, tag, field_name);\n", - "prefix", use_lite_runtime() ? "" : "unknownFields, "); - printer->Print(" break;\n"); - printer->Print("}\n"); - + "default:\n" + " if (pb::WireFormat.IsEndGroupTag(tag)) {\n" + " return;\n" + " }\n" + " break;\n"); // Note: we're ignoring unknown fields here. for (int i = 0; i < fields_by_number().size(); i++) { const FieldDescriptor* field = fields_by_number()[i]; internal::WireFormatLite::WireType wt = internal::WireFormat::WireTypeForFieldType(field->type()); uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt); - if (field->is_repeated() - && (wt == internal::WireFormatLite::WIRETYPE_VARINT - || wt == internal::WireFormatLite::WIRETYPE_FIXED32 - || wt == internal::WireFormatLite::WIRETYPE_FIXED64)) { + // Handle both packed and unpacked repeated fields with the same Read*Array call; + // the two generated cases are the packed and unpacked tags. + // TODO(jonskeet): Check that is_packable is equivalent to is_repeated && wt in { VARINT, FIXED32, FIXED64 }. + // It looks like it is... + if (field->is_packable()) { printer->Print( - "case $number$:\n", - "number", + "case $packed_tag$:\n", + "packed_tag", SimpleItoa( internal::WireFormatLite::MakeTag( field->number(), @@ -894,95 +457,12 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { printer->Outdent(); printer->Print("}\n"); } - printer->Outdent(); - printer->Print("}\n"); + printer->Print("}\n"); // switch printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); - if (!use_lite_runtime()) { - printer->Print( - "if (unknownFields != null) {\n" - " this.UnknownFields = unknownFields.Build();\n" - "}\n"); - } - printer->Print("return this;\n"); + printer->Print("}\n"); // while printer->Outdent(); - printer->Print("}\n\n"); -} - -void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { - printer->Print("public override bool IsInitialized {\n"); - printer->Indent(); - printer->Print("get {\n"); - printer->Indent(); - - // Check that all required fields in this message are set. - // TODO(kenton): We can optimize this when we switch to putting all the - // "has" fields into a single bitfield. - for (int i = 0; i < descriptor_->field_count(); i++) { - if (descriptor_->field(i)->is_required()) { - printer->Print("if (!has$property_name$) return false;\n", - "property_name", GetPropertyName(descriptor_->field(i))); - } - } - - // Now check that all embedded messages are initialized. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - - if (field->type() != FieldDescriptor::TYPE_MESSAGE || - !HasRequiredFields(field->message_type())) - { - continue; - } - // TODO(jtattermusch): shouldn't we use GetPropertyName here? - string propertyName = UnderscoresToPascalCase(GetFieldName(field)); - if (field->is_repeated()) - { - printer->Print( - "foreach ($class_name$ element in $property_name$List) {\n" - " if (!element.IsInitialized) return false;\n" - "}\n", - "class_name", GetClassName(field->message_type()), - "property_name", propertyName); - } - else if (field->is_optional()) - { - printer->Print( - "if (Has$property_name$) {\n" - " if (!$property_name$.IsInitialized) return false;\n" - "}\n", - "property_name", propertyName); - } - else - { - printer->Print( - "if (!$property_name$.IsInitialized) return false;\n", - "property_name", propertyName); - } - } - - if (descriptor_->extension_range_count() > 0) { - printer->Print("if (!ExtensionsAreInitialized) return false;\n"); - } - printer->Print("return true;\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); -} - -void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.GenerateExtensionRegistrationCode(printer); - } - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateExtensionRegistrationCode(printer); - } + printer->Print("}\n\n"); // method } int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) { diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index ebe58618..f0c49ac9 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -43,7 +43,6 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; class FieldGeneratorBase; class MessageGenerator : public SourceGeneratorBase { @@ -51,9 +50,9 @@ class MessageGenerator : public SourceGeneratorBase { MessageGenerator(const Descriptor* descriptor); ~MessageGenerator(); - void GenerateStaticVariables(io::Printer* printer); - void GenerateStaticVariableInitializers(io::Printer* printer); - void GenerateExtensionRegistrationCode(io::Printer* printer); + void GenerateCloningCode(io::Printer* printer); + void GenerateFreezingCode(io::Printer* printer); + void GenerateFrameworkMethods(io::Printer* printer); void Generate(io::Printer* printer); private: @@ -61,22 +60,15 @@ class MessageGenerator : public SourceGeneratorBase { std::vector<std::string> field_names_; std::vector<const FieldDescriptor*> fields_by_number_; - void GenerateLiteRuntimeMethods(io::Printer* printer); void GenerateMessageSerializationMethods(io::Printer* printer); - void GenerateSerializeOneField(io::Printer* printer, - const FieldDescriptor* fieldDescriptor); - void GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* extendsionRange); - void GenerateParseFromMethods(io::Printer* printer); - void GenerateBuilder(io::Printer* printer); - void GenerateCommonBuilderMethods(io::Printer* printer); - void GenerateBuilderParsingMethods(io::Printer* printer); - void GenerateIsInitialized(io::Printer* printer); + void GenerateMergingMethods(io::Printer* printer); int GetFieldOrdinal(const FieldDescriptor* descriptor); FieldGeneratorBase* CreateFieldGeneratorInternal( const FieldDescriptor* descriptor); + bool HasNestedGeneratedTypes(); + std::string class_name(); std::string full_class_name(); @@ -95,4 +87,3 @@ class MessageGenerator : public SourceGeneratorBase { } // namespace google #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__ - diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 50eb9df6..4f576cd1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -49,8 +49,8 @@ namespace csharp { MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - variables_["has_property_check"] = "has" + property_name(); - variables_["message_or_group"] = message_or_group(); + variables_["has_property_check"] = name() + "_ != null"; + variables_["has_not_property_check"] = name() + "_ == null"; } MessageFieldGenerator::~MessageFieldGenerator() { @@ -60,125 +60,45 @@ MessageFieldGenerator::~MessageFieldGenerator() { void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( variables_, - "private bool has$property_name$;\n" "private $type_name$ $name$_;\n"); AddDeprecatedFlag(printer); printer->Print( variables_, - "public bool Has$property_name$ {\n" - " get { return has$property_name$; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return $name$_ ?? $default_value$; }\n" - "}\n"); -} - -void MessageFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return result.has$property_name$; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$property_name$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.has$property_name$ = true;\n" - " result.$name$_ = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.has$property_name$ = true;\n" - " result.$name$_ = builderForValue.Build();\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Merge$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " if (result.has$property_name$ &&\n" - " result.$name$_ != $default_value$) {\n" - " result.$name$_ = $type_name$.CreateBuilder(result.$name$_).MergeFrom(value).BuildPartial();\n" - " } else {\n" - " result.$name$_ = value;\n" + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $name$_; }\n" + " set {\n" + " $name$_ = value;\n" " }\n" - " result.has$property_name$ = true;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.has$property_name$ = false;\n" - " result.$name$_ = null;\n" - " return this;\n" "}\n"); } void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "if (other.Has$property_name$) {\n" - " Merge$property_name$(other.$property_name$);\n" + "if (other.$has_property_check$) {\n" + " if ($has_not_property_check$) {\n" + " $name$_ = new $type_name$();\n" + " }\n" + " $property_name$.MergeFrom(other.$property_name$);\n" "}\n"); } -void MessageFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - // Nothing to do for singular fields -} - void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "$type_name$.Builder subBuilder = $type_name$.CreateBuilder();\n" - "if (result.has$property_name$) {\n" - " subBuilder.MergeFrom($property_name$);\n" - "}\n"); - - if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - printer->Print( - variables_, - "input.ReadGroup($number$, subBuilder, extensionRegistry);\n"); - } else { - printer->Print("input.ReadMessage(subBuilder, extensionRegistry);\n"); - } - printer->Print( - variables_, - "$property_name$ = subBuilder.BuildPartial();\n"); + "if ($has_not_property_check$) {\n" + " $name$_ = new $type_name$();\n" + "}\n" + // TODO(jonskeet): Do we really need merging behaviour like this? + "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP... } void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.Write$message_or_group$($number$, field_names[$field_ordinal$], $property_name$);\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.WriteMessage($property_name$);\n" "}\n"); } @@ -186,19 +106,19 @@ void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.Compute$message_or_group$Size($number$, $property_name$);\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n" "}\n"); } void MessageFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "if (has$property_name$) hash ^= $name$_.GetHashCode();\n"); + "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); } void MessageFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if (has$property_name$ != other.has$property_name$ || (has$property_name$ && !$name$_.Equals(other.$name$_))) return false;\n"); + "if (!object.Equals($property_name$, other.$property_name$)) return false;\n"); } void MessageFieldGenerator::WriteToString(io::Printer* printer) { variables_["field_name"] = GetFieldName(descriptor_); @@ -207,6 +127,20 @@ void MessageFieldGenerator::WriteToString(io::Printer* printer) { "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n"); } +void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n"); +} + +void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) { +} + +void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) { + printer->Print( + variables_, + "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)"); +} + MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : MessageFieldGenerator(descriptor, fieldOrdinal) { @@ -218,124 +152,41 @@ MessageOneofFieldGenerator::~MessageOneofFieldGenerator() { } void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return $has_property_check$; }\n" - "}\n"); - } - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" - "}\n"); -} - -void MessageOneofFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return result.$has_property_check$; }\n" - "}\n"); - } AddDeprecatedFlag(printer); printer->Print( variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$has_property_check$ ? ($type_name$) result.$oneof_name$_ : $default_value$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " result.$oneof_name$_ = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " result.$oneof_name$_ = builderForValue.Build();\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Merge$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " if (result.$has_property_check$ &&\n" - " result.$property_name$ != $default_value$) {\n" - " result.$oneof_name$_ = $type_name$.CreateBuilder(result.$property_name$).MergeFrom(value).BuildPartial();\n" - " } else {\n" - " result.$oneof_name$_ = value;\n" - " }\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " if (result.$has_property_check$) {\n" - " PrepareBuilder();\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.None;\n" - " result.$oneof_name$_ = null;\n" + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n" + " set {\n" + " $oneof_name$_ = value;\n" + " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" " }\n" - " return this;\n" "}\n"); } void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + // TODO(jonskeet): We may be able to do better than this printer->Print( variables_, - "$type_name$.Builder subBuilder = $type_name$.CreateBuilder();\n" - "if (result.$has_property_check$) {\n" + "$type_name$ subBuilder = new $type_name$();\n" + "if ($has_property_check$) {\n" " subBuilder.MergeFrom($property_name$);\n" - "}\n"); - - if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - printer->Print( - variables_, - "input.ReadGroup($number$, subBuilder, extensionRegistry);\n"); - } else { - printer->Print("input.ReadMessage(subBuilder, extensionRegistry);\n"); - } - printer->Print( - variables_, - "result.$oneof_name$_ = subBuilder.BuildPartial();\n" - "result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); + "}\n" + "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP + "$property_name$ = subBuilder;\n"); } -void MessageOneofFieldGenerator::WriteEquals(io::Printer* printer) { - printer->Print( - variables_, - "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); -} void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) { printer->Print( variables_, "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n"); } +void MessageOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$property_name$ = other.$property_name$.Clone();\n"); +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h index d820908c..dc6e4dc5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h @@ -41,17 +41,16 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class MessageFieldGenerator : public FieldGeneratorBase { public: MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~MessageFieldGenerator(); + virtual void GenerateCodecCode(io::Printer* printer); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); @@ -69,9 +68,8 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~MessageOneofFieldGenerator(); + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); - virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_writer.h b/src/google/protobuf/compiler/csharp/csharp_names.h index 26c59b31..ccd2e720 100644 --- a/src/google/protobuf/compiler/csharp/csharp_writer.h +++ b/src/google/protobuf/compiler/csharp/csharp_names.h @@ -31,63 +31,52 @@ // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +// +// Provides a mechanism for mapping a descriptor to the +// fully-qualified name of the corresponding C# class. -#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ -#define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ #include <string> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/io/printer.h> namespace google { namespace protobuf { -namespace compiler { -namespace csharp { - -// Simple wrapper around Printer that supports customizable line endings -// and number-based variables (e.g. $0$). -class Writer { - public: - Writer(io::Printer* printer); - ~Writer(); - - void Indent(); - void Outdent(); - - void Write(const char* text); - - void Write(const char* text, const string& value0); - - void Write(const char* text, const string& value0, const string& value1); - - void Write(const char* text, const string& value0, const string& value1, - const string& value2); - void Write(const char* text, const string& value0, const string& value1, - const string& value2, const string& value3); +class Descriptor; +class EnumDescriptor; +class FileDescriptor; +class ServiceDescriptor; - void WriteLine(); - - void WriteLine(const char* text); - - void WriteLine(const char* text, const string& value0); +namespace compiler { +namespace csharp { - void WriteLine(const char* text, const string& value0, const string& value1); +// Requires: +// descriptor != NULL +// +// Returns: +// The namespace to use for given file descriptor. +string GetFileNamespace(const FileDescriptor* descriptor); - void WriteLine(const char* text, const string& value0, const string& value1, - const string& value2); +// Requires: +// descriptor != NULL +// +// Returns: +// The fully-qualified C# class name. +string GetClassName(const Descriptor* descriptor); - void WriteLine(const char* text, const string& value0, const string& value1, - const string& value2, const string& value3); - private: - io::Printer* printer_; - const char* newline_; -}; +// Requires: +// descriptor != NULL +// +// Returns: +// The fully-qualified name of the C# class that provides +// access to the file descriptor. Proto compiler generates +// such class for each .proto file processed. +std::string GetUmbrellaClassName(const FileDescriptor* descriptor); } // namespace csharp } // namespace compiler } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index 652eb6b9..fc043ec0 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -49,81 +49,42 @@ namespace csharp { PrimitiveFieldGenerator::PrimitiveFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { + // TODO(jonskeet): Make this cleaner... + is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING + && descriptor->type() != FieldDescriptor::TYPE_BYTES; + if (!is_value_type) { + variables_["has_property_check"] = variables_["property_name"] + ".Length != 0"; + variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0"; + } } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() { - } void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, "private bool has$property_name$;\n"); - } + // TODO(jonskeet): Work out whether we want to prevent the fields from ever being + // null, or whether we just handle it, in the cases of bytes and string. + // (Basically, should null-handling code be in the getter or the setter?) printer->Print( variables_, "private $type_name$ $name_def_message$;\n"); AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return has$property_name$; }\n" - "}\n"); - } - AddPublicMemberAttributes(printer); printer->Print( variables_, - "public $type_name$ $property_name$ {\n" + "$access_level$ $type_name$ $property_name$ {\n" " get { return $name$_; }\n" - "}\n"); -} - -void PrimitiveFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { + " set {\n"); + if (is_value_type) { printer->Print( variables_, - "public bool Has$property_name$ {\n" - " get { return result.has$property_name$; }\n" - "}\n"); - } - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$property_name$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print(" PrepareBuilder();\n"); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - " result.has$property_name$ = true;\n"); - } - printer->Print( - variables_, - " result.$name$_ = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n"); - if (SupportFieldPresence(descriptor_->file())) { + " $name$_ = value;\n"); + } else { printer->Print( variables_, - " result.has$property_name$ = false;\n"); + " $name$_ = pb::Preconditions.CheckNotNull(value, \"value\");\n"); } printer->Print( - variables_, - " result.$name$_ = $default_value$;\n" - " return this;\n" + " }\n" "}\n"); } @@ -135,60 +96,68 @@ void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { "}\n"); } -void PrimitiveFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - // Nothing to do here for primitive types -} - void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "result.has$property_name$ = input.Read$capitalized_type_name$(ref result.$name$_);\n"); - } else { - printer->Print( - variables_, - "input.Read$capitalized_type_name$(ref result.$name$_);\n"); - } + // Note: invoke the property setter rather than writing straight to the field, + // so that we can normalize "null to empty" for strings and bytes. + printer->Print( + variables_, + "$property_name$ = input.Read$capitalized_type_name$();\n"); } void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.Write$capitalized_type_name$($number$, field_names[$field_ordinal$], $property_name$);\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.Write$capitalized_type_name$($property_name$);\n" "}\n"); } void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, - "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.Compute$capitalized_type_name$Size($number$, $property_name$);\n" - "}\n"); + "if ($has_property_check$) {\n"); + printer->Indent(); + int fixedSize = GetFixedSize(descriptor_->type()); + if (fixedSize == -1) { + printer->Print( + variables_, + "size += $tag_size$ + pb::CodedOutputStream.Compute$capitalized_type_name$Size($property_name$);\n"); + } else { + printer->Print( + "size += $tag_size$ + $fixed_size$;\n", + "fixed_size", SimpleItoa(fixedSize), + "tag_size", variables_["tag_size"]); + } + printer->Outdent(); + printer->Print("}\n"); } void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "if ($has_property_check$) {\n" - " hash ^= $name$_.GetHashCode();\n" - "}\n"); + "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); } void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "if (has$property_name$ != other.has$property_name$ || (has$property_name$ && !$name$_.Equals(other.$name$_))) return false;\n"); - } else { - printer->Print( - variables_, - "if (!$name$_.Equals(other.$name$_)) return false;\n"); - } + printer->Print( + variables_, + "if ($property_name$ != other.$property_name$) return false;\n"); } void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) { printer->Print( variables_, - "PrintField(\"$descriptor_name$\", $has_property_check$, $name$_, writer);\n"); + "PrintField(\"$descriptor_name$\", $has_property_check$, $property_name$, writer);\n"); +} + +void PrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_ = other.$name$_;\n"); +} + +void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) { + printer->Print( + variables_, + "pb::FieldCodec.For$capitalized_type_name$($tag$)"); } PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( @@ -202,79 +171,41 @@ PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() { void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return $has_property_check$; }\n" - "}\n"); - } - AddPublicMemberAttributes(printer); printer->Print( variables_, - "public $type_name$ $property_name$ {\n" + "$access_level$ $type_name$ $property_name$ {\n" " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" - "}\n"); -} - -void PrimitiveOneofFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { + " set {\n"); + if (is_value_type) { + printer->Print( + variables_, + " $oneof_name$_ = value;\n"); + } else { + printer->Print( + variables_, + " $oneof_name$_ = pb::Preconditions.CheckNotNull(value, \"value\");\n"); + } printer->Print( variables_, - "public bool Has$property_name$ {\n" - " get { return result.$has_property_check$; }\n" + " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " }\n" "}\n"); - } - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$has_property_check$ ? ($type_name$) result.$oneof_name$_ : $default_value$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$oneof_name$_ = value;\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " if (result.$has_property_check$) {\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.None;\n" - " }\n" - " return this;\n" - "}\n"); } -void PrimitiveOneofFieldGenerator::WriteEquals(io::Printer* printer) { - printer->Print( - variables_, - "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); -} void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) { printer->Print(variables_, "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n"); } void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { - printer->Print( - variables_, - "$type_name$ value = $default_value$;\n" - "if (input.Read$capitalized_type_name$(ref value)) {\n" - " result.$oneof_name$_ = value;\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - "}\n"); + printer->Print( + variables_, + "$property_name$ = input.Read$capitalized_type_name$();\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$property_name$ = other.$property_name$;\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h index 8a2d5020..8b87ebc4 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h @@ -41,17 +41,15 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class PrimitiveFieldGenerator : public FieldGeneratorBase { public: PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~PrimitiveFieldGenerator(); + virtual void GenerateCodecCode(io::Printer* printer); + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); @@ -60,6 +58,9 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase { virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); + protected: + bool is_value_type; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; @@ -69,9 +70,8 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~PrimitiveOneofFieldGenerator(); + virtual void GenerateCloningCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); - virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index f5ebcfb1..625631df 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -56,187 +56,54 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() { } void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) { - if (descriptor_->is_packed() && optimize_speed()) { - printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); - } - printer->Print(variables_, - "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public scg::IList<$type_name$> $property_name$List {\n" - " get { return pbc::Lists.AsReadOnly($name$_); }\n" - "}\n"); - - // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(printer); printer->Print( variables_, - "public int $property_name$Count {\n" - " get { return $name$_.Count; }\n" - "}\n"); - - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return $name$_[index];\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - // Note: We can return the original list here, because we make it unmodifiable when we build - // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" - " get { return PrepareBuilder().$name$_; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return result.$property_name$Count; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return result.Get$property_name$(index);\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$ value) {\n"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); + "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n" + " = pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x);\n"); printer->Print(variables_, - "public Builder Add$property_name$($type_name$ value) {\n"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(value);\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" - " PrepareBuilder();\n" - " result.$name$_.Add(values);\n" - " return this;\n" - "}\n"); + "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n"); AddDeprecatedFlag(printer); printer->Print( variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_.Clear();\n" - " return this;\n" + "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n" + " get { return $name$_; }\n" "}\n"); } void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "if (other.$name$_.Count != 0) {\n" - " result.$name$_.Add(other.$name$_);\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - printer->Print(variables_, "$name$_.MakeReadOnly();\n"); + "$name$_.Add(other.$name$_);\n"); } void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "scg::ICollection<object> unknownItems;\n" - "input.ReadEnumArray<$type_name$>(tag, field_name, result.$name$_, out unknownItems);\n"); - if (!use_lite_runtime()) { - printer->Print( - variables_, - "if (unknownItems != null) {\n" - " if (unknownFields == null) {\n" - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n" - " foreach (object rawValue in unknownItems)\n" - " if (rawValue is int)\n" - " unknownFields.MergeVarintField($number$, (ulong)(int)rawValue);\n" - "}\n"); - } + "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { - printer->Print(variables_, "if ($name$_.Count > 0) {\n"); - printer->Indent(); - if (descriptor_->is_packed()) { - printer->Print( - variables_, - "output.WritePackedEnumArray($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n"); - } else { - printer->Print(variables_, - "output.WriteEnumArray($number$, field_names[$field_ordinal$], $name$_);\n"); - } - printer->Outdent(); - printer->Print("}\n"); -} - -void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { - printer->Print("{\n"); - printer->Indent(); printer->Print( variables_, - "int dataSize = 0;\n" - "if ($name$_.Count > 0) {\n"); - printer->Indent(); + "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); +} + +void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, - "foreach ($type_name$ element in $name$_) {\n" - " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n" - "}\n" - "size += dataSize;\n"); - int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); - if (descriptor_->is_packed()) { - printer->Print( - "size += $tag_size$;\n" - "size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n", - "tag_size", SimpleItoa(tagSize)); - } else { - printer->Print( - "size += $tag_size$ * $name$_.Count;\n", - "tag_size", SimpleItoa(tagSize), "name", name()); - } - printer->Outdent(); - printer->Print("}\n"); - // cache the data size for packed fields. - if (descriptor_->is_packed()) { - printer->Print(variables_, - "$name$MemoizedSerializedSize = dataSize;\n"); - } - printer->Outdent(); - printer->Print("}\n"); + "size += $name$_.CalculateSize(_repeated_$name$_codec);\n"); } void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_)\n" - " hash ^= i.GetHashCode();\n"); + "hash ^= $name$_.GetHashCode();\n"); } void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if($name$_.Count != other.$name$_.Count) return false;\n" - "for(int ix=0; ix < $name$_.Count; ix++)\n" - " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) { @@ -244,6 +111,14 @@ void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) { "PrintField(\"$descriptor_name$\", $name$_, writer);\n"); } +void RepeatedEnumFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_ = other.$name$_.Clone();\n"); +} + +void RepeatedEnumFieldGenerator::GenerateFreezingCode(io::Printer* printer) { +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h index 68c3d6c9..ee50eef0 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h @@ -41,17 +41,17 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - +// TODO(jonskeet): Refactor repeated field support; all the implementations are *really* similar. We +// should probably have a RepeatedFieldGeneratorBase. class RepeatedEnumFieldGenerator : public FieldGeneratorBase { public: RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedEnumFieldGenerator(); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 2ae1d579..7fbab681 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -39,6 +39,8 @@ #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h> +#include <google/protobuf/compiler/csharp/csharp_message_field.h> +#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> namespace google { namespace protobuf { @@ -48,7 +50,6 @@ namespace csharp { RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - variables_["message_or_group"] = message_or_group(); } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() { @@ -58,162 +59,66 @@ RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() { void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( variables_, - "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public scg::IList<$type_name$> $property_name$List {\n" - " get { return $name$_; }\n" - "}\n"); - - // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return $name$_.Count; }\n" - "}\n"); - - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return $name$_[index];\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - // Note: We can return the original list here, because we make it unmodifiable when we build - // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddDeprecatedFlag(printer); + "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n" + " = "); + // Don't want to duplicate the codec code here... maybe we should have a + // "create single field generator for this repeated field" + // function, but it doesn't seem worth it for just this. + if (IsWrapperType(descriptor_)) { + scoped_ptr<FieldGeneratorBase> single_generator(new WrapperFieldGenerator(descriptor_, fieldOrdinal_)); + single_generator->GenerateCodecCode(printer); + } else { + scoped_ptr<FieldGeneratorBase> single_generator(new MessageFieldGenerator(descriptor_, fieldOrdinal_)); + single_generator->GenerateCodecCode(printer); + } + printer->Print(";\n"); printer->Print( variables_, - "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" - " get { return PrepareBuilder().$name$_; }\n" - "}\n"); + "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n"); AddDeprecatedFlag(printer); printer->Print( variables_, - "public int $property_name$Count {\n" - " get { return result.$property_name$Count; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return result.Get$property_name$(index);\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = value;\n" - " return this;\n" - "}\n"); - // Extra overload for builder (just on messages) - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = builderForValue.Build();\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Add$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(value);\n" - " return this;\n" - "}\n"); - // Extra overload for builder (just on messages) - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Add$property_name$($type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(builderForValue.Build());\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" - " PrepareBuilder();\n" - " result.$name$_.Add(values);\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_.Clear();\n" - " return this;\n" + "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n" + " get { return $name$_; }\n" "}\n"); } void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "if (other.$name$_.Count != 0) {\n" - " result.$name$_.Add(other.$name$_);\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - printer->Print(variables_, "$name$_.MakeReadOnly();\n"); + "$name$_.Add(other.$name$_);\n"); } void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.Read$message_or_group$Array(tag, field_name, result.$name$_, $type_name$.DefaultInstance, extensionRegistry);\n"); + "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, - "if ($name$_.Count > 0) {\n" - " output.Write$message_or_group$Array($number$, field_names[$field_ordinal$], $name$_);\n" - "}\n"); + "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, - "foreach ($type_name$ element in $property_name$List) {\n" - " size += pb::CodedOutputStream.Compute$message_or_group$Size($number$, element);\n" - "}\n"); + "size += $name$_.CalculateSize(_repeated_$name$_codec);\n"); } void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_)\n" - " hash ^= i.GetHashCode();\n"); + "hash ^= $name$_.GetHashCode();\n"); } + void RepeatedMessageFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if($name$_.Count != other.$name$_.Count) return false;\n" - "for(int ix=0; ix < $name$_.Count; ix++)\n" - " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } + void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) { variables_["field_name"] = GetFieldName(descriptor_); printer->Print( @@ -221,6 +126,14 @@ void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) { "PrintField(\"$field_name$\", $name$_, writer);\n"); } +void RepeatedMessageFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_ = other.$name$_.Clone();\n"); +} + +void RepeatedMessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) { +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h index 9db76939..cf601c7e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h @@ -41,17 +41,15 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class RepeatedMessageFieldGenerator : public FieldGeneratorBase { public: RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedMessageFieldGenerator(); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index e27458bb..1163ce73 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -56,183 +56,67 @@ RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() { } void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { - if (descriptor_->is_packed() && optimize_speed()) { - printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); - } - printer->Print(variables_, - "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); - AddPublicMemberAttributes(printer); printer->Print( variables_, - "public scg::IList<$type_name$> $property_name$List {\n" - " get { return pbc::Lists.AsReadOnly($name$_); }\n" - "}\n"); - - // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. + "private static readonly pb::FieldCodec<$type_name$> _repeated_$name$_codec\n" + " = pb::FieldCodec.For$capitalized_type_name$($tag$);\n"); + printer->Print(variables_, + "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n"); AddDeprecatedFlag(printer); printer->Print( variables_, - "public int $property_name$Count {\n" - " get { return $name$_.Count; }\n" + "$access_level$ pbc::RepeatedField<$type_name$> $property_name$ {\n" + " get { return $name$_; }\n" "}\n"); +} - AddPublicMemberAttributes(printer); +void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return $name$_[index];\n" - "}\n"); + "$name$_.Add(other.$name$_);\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - // Note: We can return the original list here, because we make it unmodifiable when we build - // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" - " get { return PrepareBuilder().$name$_; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return result.$property_name$Count; }\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return result.Get$property_name$(index);\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = value;\n" - " return this;\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Add$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(value);\n" - " return this;\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" - " PrepareBuilder();\n" - " result.$name$_.Add(values);\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); +void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_.Clear();\n" - " return this;\n" - "}\n"); + "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { +void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, - "if (other.$name$_.Count != 0) {\n" - " result.$name$_.Add(other.$name$_);\n" - "}\n"); + "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - printer->Print(variables_, "$name$_.MakeReadOnly();\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { - printer->Print(variables_, - "input.Read$capitalized_type_name$Array(tag, field_name, result.$name$_);\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( - io::Printer* printer) { - printer->Print(variables_, "if ($name$_.Count > 0) {\n"); - printer->Indent(); - if (descriptor_->is_packed()) { - printer->Print(variables_, - "output.WritePacked$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n"); - } else { - printer->Print(variables_, - "output.Write$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$_);\n"); - } - printer->Outdent(); - printer->Print("}\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( - io::Printer* printer) { - printer->Print("{\n"); - printer->Indent(); - printer->Print("int dataSize = 0;\n"); - int fixedSize = GetFixedSize(descriptor_->type()); - if (fixedSize == -1) { - printer->Print( - variables_, - "foreach ($type_name$ element in $property_name$List) {\n" - " dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$SizeNoTag(element);\n" - "}\n"); - } else { - printer->Print( - "dataSize = $size$ * $name$_.Count;\n", - "size", SimpleItoa(fixedSize), "name", name()); - } - printer->Print("size += dataSize;\n"); - int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); - if (descriptor_->is_packed()) { - printer->Print( - "if ($name$_.Count != 0) {\n" - " size += $tag_size$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);\n" - "}\n", - "name", name(), "tag_size", SimpleItoa(tagSize)); - } else { - printer->Print( - "size += $tag_size$ * $name$_.Count;\n", - "tag_size", SimpleItoa(tagSize), "name", name()); - } - // cache the data size for packed fields. - if (descriptor_->is_packed()) { - printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n"); - } - printer->Outdent(); - printer->Print("}\n"); +void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "size += $name$_.CalculateSize(_repeated_$name$_codec);\n"); } void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_)\n" - " hash ^= i.GetHashCode();\n"); + "hash ^= $name$_.GetHashCode();\n"); } void RepeatedPrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if($name$_.Count != other.$name$_.Count) return false;\n" - "for(int ix=0; ix < $name$_.Count; ix++)\n" - " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } void RepeatedPrimitiveFieldGenerator::WriteToString(io::Printer* printer) { printer->Print(variables_, "PrintField(\"$descriptor_name$\", $name$_, writer);\n"); } +void RepeatedPrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_ = other.$name$_.Clone();\n"); +} + +void RepeatedPrimitiveFieldGenerator::GenerateFreezingCode(io::Printer* printer) { +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h index 50af9dda..f1ceeb50 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h @@ -41,17 +41,15 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase { public: RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedPrimitiveFieldGenerator(); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc index c52f6092..735d164a 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc @@ -47,14 +47,6 @@ namespace csharp { SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor) : descriptor_(descriptor) { - optimizeSize_ = (descriptor->options().optimize_for() - == FileOptions::CODE_SIZE); - optimizeSpeed_ = (descriptor->options().optimize_for() == FileOptions::SPEED); - useLiteRuntime_ = (descriptor->options().optimize_for() - == FileOptions::LITE_RUNTIME); - - optimizeSpeed_ |= useLiteRuntime_; - runtimeSuffix_ = useLiteRuntime_ ? "Lite" : ""; } SourceGeneratorBase::~SourceGeneratorBase() { @@ -65,7 +57,7 @@ void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) { } std::string SourceGeneratorBase::class_access_level() { - return "public"; // public_classes is always on. + return IsDescriptorProto(descriptor_) ? "internal" : "public"; // public_classes is always on. } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h index 61c19511..6caef171 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h @@ -47,27 +47,10 @@ class SourceGeneratorBase { std::string class_access_level(); - bool optimize_size() { - return optimizeSize_; - } - bool optimize_speed() { - return optimizeSpeed_; - } - bool use_lite_runtime() { - return useLiteRuntime_; - } - std::string runtime_suffix() { - return runtimeSuffix_; - } - void WriteGeneratedCodeAttributes(io::Printer* printer); private: const FileDescriptor* descriptor_; - bool optimizeSize_; - bool optimizeSpeed_; - bool useLiteRuntime_; - std::string runtimeSuffix_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceGeneratorBase); }; diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc index b14bf5e8..0ffae3d4 100644 --- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc @@ -36,12 +36,14 @@ #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/stubs/strutil.h> + -#include <google/protobuf/compiler/csharp/csharp_umbrella_class.h> #include <google/protobuf/compiler/csharp/csharp_enum.h> -#include <google/protobuf/compiler/csharp/csharp_extension.h> #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_message.h> +#include <google/protobuf/compiler/csharp/csharp_names.h> +#include <google/protobuf/compiler/csharp/csharp_umbrella_class.h> namespace google { namespace protobuf { @@ -52,8 +54,8 @@ UmbrellaClassGenerator::UmbrellaClassGenerator(const FileDescriptor* file) : SourceGeneratorBase(file), file_(file) { namespace_ = GetFileNamespace(file); - umbrellaClassname_ = GetFileUmbrellaClassname(file); - umbrellaNamespace_ = GetFileUmbrellaNamespace(file); + umbrellaClassname_ = GetUmbrellaClassUnqualifiedName(file); + umbrellaNamespace_ = GetUmbrellaClassNestedNamespace(file); } UmbrellaClassGenerator::~UmbrellaClassGenerator() { @@ -61,30 +63,8 @@ UmbrellaClassGenerator::~UmbrellaClassGenerator() { void UmbrellaClassGenerator::Generate(io::Printer* printer) { WriteIntroduction(printer); - WriteExtensionRegistration(printer); - // write children: Extensions - if (file_->extension_count() > 0) { - printer->Print("#region Extensions\n"); - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.Generate(printer); - } - printer->Print("#endregion\n"); - printer->Print("\n"); - } - - printer->Print("#region Static variables\n"); - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariables(printer); - } - printer->Print("#endregion\n"); - if (!use_lite_runtime()) { - WriteDescriptor(printer); - } else { - WriteLiteExtensions(printer); - } + WriteDescriptor(printer); // Close the class declaration. printer->Outdent(); printer->Print("}\n"); @@ -134,9 +114,9 @@ void UmbrellaClassGenerator::WriteIntroduction(io::Printer* printer) { "#pragma warning disable 1591, 0612, 3021\n" "#region Designer generated code\n" "\n" - "using pb = global::Google.ProtocolBuffers;\n" - "using pbc = global::Google.ProtocolBuffers.Collections;\n" - "using pbd = global::Google.ProtocolBuffers.Descriptors;\n" + "using pb = global::Google.Protobuf;\n" + "using pbc = global::Google.Protobuf.Collections;\n" + "using pbr = global::Google.Protobuf.Reflection;\n" "using scg = global::System.Collections.Generic;\n", "file_name", file_->name()); @@ -165,31 +145,13 @@ void UmbrellaClassGenerator::WriteIntroduction(io::Printer* printer) { printer->Indent(); } -void UmbrellaClassGenerator::WriteExtensionRegistration(io::Printer* printer) { - printer->Print( - "#region Extension registration\n" - "public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {\n"); - printer->Indent(); - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateExtensionRegistrationCode(printer); - } - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateExtensionRegistrationCode(printer); - } - printer->Outdent(); - printer->Print("}\n"); - printer->Print("#endregion\n"); -} - void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) { printer->Print( "#region Descriptor\n" - "public static pbd::FileDescriptor Descriptor {\n" + "public static pbr::FileDescriptor Descriptor {\n" " get { return descriptor; }\n" "}\n" - "private static pbd::FileDescriptor descriptor;\n" + "private static pbr::FileDescriptor descriptor;\n" "\n" "static $umbrella_class_name$() {\n", "umbrella_class_name", umbrellaClassname_); @@ -207,82 +169,124 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) { printer->Print("\"$base64$\", \n", "base64", base64.substr(0, 60)); base64 = base64.substr(60); } - printer->Outdent(); printer->Print("\"$base64$\"));\n", "base64", base64); printer->Outdent(); printer->Outdent(); - printer->Print( - "pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {\n"); - printer->Indent(); - printer->Print("descriptor = root;\n"); - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariableInitializers(printer); - } - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(printer); - } - - if (uses_extensions()) { - // Must construct an ExtensionRegistry containing all possible extensions - // and return it. - printer->Print( - "pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();\n"); - printer->Print("RegisterAllExtensions(registry);\n"); - for (int i = 0; i < file_->dependency_count(); i++) { - printer->Print("$dependency$.RegisterAllExtensions(registry);\n", - "dependency", GetFullUmbrellaClassName(file_->dependency(i))); - } - printer->Print("return registry;\n"); - } else { - printer->Print("return null;\n"); - } printer->Outdent(); - printer->Print("};\n"); // ----------------------------------------------------------------- - // Invoke internalBuildGeneratedFileFrom() to build the file. + // Invoke InternalBuildGeneratedFileFrom() to build the file. printer->Print( - "pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n"); - printer->Print(" new pbd::FileDescriptor[] {\n"); + "descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n"); + printer->Print(" new pbr::FileDescriptor[] { "); for (int i = 0; i < file_->dependency_count(); i++) { printer->Print( - " $full_umbrella_class_name$.Descriptor, \n", + "$full_umbrella_class_name$.Descriptor, ", "full_umbrella_class_name", - GetFullUmbrellaClassName(file_->dependency(i))); + GetUmbrellaClassName(file_->dependency(i))); + } + printer->Print("},\n" + " new pbr::GeneratedCodeInfo("); + // Specify all the generated code information, recursively. + if (file_->enum_type_count() > 0) { + printer->Print("new[] {"); + for (int i = 0; i < file_->enum_type_count(); i++) { + printer->Print("typeof($type_name$), ", "type_name", GetClassName(file_->enum_type(i))); + } + printer->Print("}, "); + } + else { + printer->Print("null, "); + } + if (file_->message_type_count() > 0) { + printer->Print("new pbr::GeneratedCodeInfo[] {\n"); + printer->Indent(); + printer->Indent(); + printer->Indent(); + for (int i = 0; i < file_->message_type_count(); i++) { + WriteGeneratedCodeInfo(file_->message_type(i), printer, i == file_->message_type_count() - 1); + } + printer->Outdent(); + printer->Print("\n}));\n"); + printer->Outdent(); + printer->Outdent(); + } + else { + printer->Print("null));\n"); } - printer->Print(" }, assigner);\n"); + printer->Outdent(); printer->Print("}\n"); printer->Print("#endregion\n\n"); } -void UmbrellaClassGenerator::WriteLiteExtensions(io::Printer* printer) { - printer->Print( - "#region Extensions\n" - "internal static readonly object Descriptor;\n" - "static $umbrella_class_name$() {\n", - "umbrella_class_name", umbrellaClassname_); - printer->Indent(); - printer->Print("Descriptor = null;\n"); - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariableInitializers(printer); +// Write out the generated code for a particular message. This consists of the CLR type, property names +// corresponding to fields, names corresponding to oneofs, nested enums, and nested types. Each array part +// can be specified as null if it would be empty, to make the generated code somewhat simpler to read. +// We write a line break at the end of each generated code info, so that in the final file we'll see all +// the types, pre-ordered depth first, one per line. The indentation will be slightly unusual, +// in that it will look like a single array when it's actually constructing a tree, but it'll be easy to +// read even with multiple levels of nesting. +// The "last" parameter indicates whether this message descriptor is the last one being printed in this immediate +// context. It governs whether or not a trailing comma and newline is written after the constructor, effectively +// just controlling the formatting in the generated code. +void UmbrellaClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last) { + if (IsMapEntryMessage(descriptor)) { + printer->Print("null, "); + return; } - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(printer); + // Generated message type + printer->Print("new pbr::GeneratedCodeInfo(typeof($type_name$), ", "type_name", GetClassName(descriptor)); + + // Fields + if (descriptor->field_count() > 0) { + std::vector<std::string> fields; + for (int i = 0; i < descriptor->field_count(); i++) { + fields.push_back(GetPropertyName(descriptor->field(i))); + } + printer->Print("new[]{ \"$fields$\" }, ", "fields", JoinStrings(fields, "\", \"")); + } + else { + printer->Print("null, "); + } + + // Oneofs + if (descriptor->oneof_decl_count() > 0) { + std::vector<std::string> oneofs; + for (int i = 0; i < descriptor->oneof_decl_count(); i++) { + oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true)); + } + printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", JoinStrings(oneofs, "\", \"")); + } + else { + printer->Print("null, "); + } + + // Nested enums + if (descriptor->enum_type_count() > 0) { + std::vector<std::string> enums; + for (int i = 0; i < descriptor->enum_type_count(); i++) { + enums.push_back(GetClassName(descriptor->enum_type(i))); + } + printer->Print("new[]{ typeof($enums$) }, ", "enums", JoinStrings(enums, "), typeof(")); + } + else { + printer->Print("null, "); } - printer->Outdent(); - printer->Print("}\n"); - printer->Print("#endregion\n\n"); -} -bool UmbrellaClassGenerator::uses_extensions() { - // TODO(jtattermusch): implement recursive descent that looks for extensions. - // For now, we conservatively assume that extensions are used. - return true; + // Nested types + if (descriptor->nested_type_count() > 0) { + // Need to specify array type explicitly here, as all elements may be null. + printer->Print("new pbr::GeneratedCodeInfo[] { "); + for (int i = 0; i < descriptor->nested_type_count(); i++) { + WriteGeneratedCodeInfo(descriptor->nested_type(i), printer, i == descriptor->nested_type_count() - 1); + } + printer->Print("}"); + } + else { + printer->Print("null"); + } + printer->Print(last ? ")" : "),\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h index 83e1f347..b8bd2133 100644 --- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h @@ -41,8 +41,6 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class UmbrellaClassGenerator : public SourceGeneratorBase { public: UmbrellaClassGenerator(const FileDescriptor* file); @@ -58,11 +56,8 @@ class UmbrellaClassGenerator : public SourceGeneratorBase { std::string umbrellaNamespace_; void WriteIntroduction(io::Printer* printer); - void WriteExtensionRegistration(io::Printer* printer); void WriteDescriptor(io::Printer* printer); - void WriteLiteExtensions(io::Printer* printer); - - bool uses_extensions(); + void WriteGeneratedCodeInfo(const Descriptor* descriptor, io::Printer* printer, bool last); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UmbrellaClassGenerator); }; @@ -73,4 +68,3 @@ class UmbrellaClassGenerator : public SourceGeneratorBase { } // namespace google #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_UMBRELLA_CLASS_H__ - diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc new file mode 100644 index 00000000..44f832bf --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc @@ -0,0 +1,207 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <sstream> + +#include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/compiler/plugin.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/zero_copy_stream.h> + +#include <google/protobuf/compiler/csharp/csharp_helpers.h> +#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : FieldGeneratorBase(descriptor, fieldOrdinal) { + variables_["has_property_check"] = name() + "_ != null"; + variables_["has_not_property_check"] = name() + "_ == null"; + const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); + is_value_type = wrapped_field->type() != FieldDescriptor::TYPE_STRING && + wrapped_field->type() != FieldDescriptor::TYPE_BYTES; + if (is_value_type) { + variables_["nonnullable_type_name"] = type_name(wrapped_field); + } +} + +WrapperFieldGenerator::~WrapperFieldGenerator() { +} + +void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) { + printer->Print( + variables_, + "private static readonly pb::FieldCodec<$type_name$> _single_$name$_codec = "); + GenerateCodecCode(printer); + printer->Print( + variables_, + ";\n" + "private $type_name$ $name$_;\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $name$_; }\n" + " set {\n" + " $name$_ = value;\n" + " }\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if (other.$has_property_check$) {\n" + " if ($has_not_property_check$ || other.$property_name$ != $default_value$) {\n" + " $property_name$ = other.$property_name$;\n" + " }\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$type_name$ value = _single_$name$_codec.Read(input);\n" + "if ($has_not_property_check$ || value != $default_value$) {\n" + " $property_name$ = value;\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n" + "}\n"); +} + +void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += _single_$name$_codec.CalculateSizeWithTag($property_name$);\n" + "}\n"); +} + +void WrapperFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); +} + +void WrapperFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if ($property_name$ != other.$property_name$) return false;\n"); +} + +void WrapperFieldGenerator::WriteToString(io::Printer* printer) { + // TODO: Implement if we ever actually need it... +} + +void WrapperFieldGenerator::GenerateCloningCode(io::Printer* printer) { + printer->Print(variables_, + "$property_name$ = other.$property_name$;\n"); +} + +void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) { + if (is_value_type) { + printer->Print( + variables_, + "pb::FieldCodec.ForStructWrapper<$nonnullable_type_name$>($tag$)"); + } else { + printer->Print( + variables_, + "pb::FieldCodec.ForClassWrapper<$type_name$>($tag$)"); + } +} + +WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : WrapperFieldGenerator(descriptor, fieldOrdinal) { + SetCommonOneofFieldVariables(&variables_); +} + +WrapperOneofFieldGenerator::~WrapperOneofFieldGenerator() { +} + +void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) { + // Note: deliberately _oneof_$name$_codec, not _$oneof_name$_codec... we have one codec per field. + printer->Print( + variables_, + "private static readonly pb::FieldCodec<$type_name$> _oneof_$name$_codec = "); + GenerateCodecCode(printer); + printer->Print(";\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : ($type_name$) null; }\n" + " set {\n" + " $oneof_name$_ = value;\n" + " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" + " }\n" + "}\n"); +} + +void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$property_name$ = _oneof_$name$_codec.Read(input);\n"); +} + +void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + // TODO: I suspect this is wrong... + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n" + "}\n"); +} + +void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + // TODO: I suspect this is wrong... + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += _oneof_$name$_codec.CalculateSizeWithTag($property_name$);\n" + "}\n"); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h new file mode 100644 index 00000000..6e2414af --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h @@ -0,0 +1,85 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__ + +#include <string> + +#include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/compiler/csharp/csharp_field_base.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class WrapperFieldGenerator : public FieldGeneratorBase { + public: + WrapperFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~WrapperFieldGenerator(); + + virtual void GenerateCodecCode(io::Printer* printer); + virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); + + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); + + private: + bool is_value_type; // True for int32 etc; false for bytes and string + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperFieldGenerator); +}; + +class WrapperOneofFieldGenerator : public WrapperFieldGenerator { + public: + WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~WrapperOneofFieldGenerator(); + + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WrapperOneofFieldGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_writer.cc b/src/google/protobuf/compiler/csharp/csharp_writer.cc deleted file mode 100644 index 2bcafde5..00000000 --- a/src/google/protobuf/compiler/csharp/csharp_writer.cc +++ /dev/null @@ -1,136 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include <algorithm> -#include <google/protobuf/stubs/hash.h> -#include <limits> -#include <vector> - -#include <google/protobuf/compiler/csharp/csharp_writer.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> - -#include <google/protobuf/compiler/csharp/csharp_field_base.h> -#include <google/protobuf/compiler/csharp/csharp_enum_field.h> -#include <google/protobuf/compiler/csharp/csharp_message_field.h> -#include <google/protobuf/compiler/csharp/csharp_primitive_field.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace csharp { - -Writer::Writer(google::protobuf::io::Printer* printer) - : printer_(printer), - newline_("\n") { - // TODO(jtattermusch): make newline customizable. -} - -Writer::~Writer() { -} - -void Writer::Indent() { - printer_->Indent(); -} - -void Writer::Outdent() { - printer_->Outdent(); -} - -void Writer::Write(const char* text) { - printer_->Print(text); -} - -void Writer::Write(const char* text, const string& value0) { - printer_->Print(text, "0", value0); -} - -void Writer::Write(const char* text, const string& value0, - const string& value1) { - printer_->Print(text, "0", value0, "1", value1); -} - -void Writer::Write(const char* text, const string& value0, const string& value1, - const string& value2) { - printer_->Print(text, "0", value0, "1", value1, "2", value2); -} - -void Writer::Write(const char* text, const string& value0, const string& value1, - const string& value2, const string& value3) { - printer_->Print(text, "0", value0, "1", value1, "2", value2, "3", value3); -} - -void Writer::WriteLine() { - printer_->Print(newline_); -} - -void Writer::WriteLine(const char* text) { - Write(text); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0) { - Write(text, value0); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0, - const string& value1) { - Write(text, value0, value1); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0, - const string& value1, const string& value2) { - Write(text, value0, value1, value2); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0, - const string& value1, const string& value2, - const string& value3) { - Write(text, value0, value1, value2, value3); - WriteLine(); -} - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc index f25970e5..44b86cd7 100644 --- a/src/google/protobuf/compiler/java/java_map_field.cc +++ b/src/google/protobuf/compiler/java/java_map_field.cc @@ -156,9 +156,7 @@ ImmutableMapFieldGenerator(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h index 80a94f45..f2768f3a 100644 --- a/src/google/protobuf/compiler/java/java_map_field.h +++ b/src/google/protobuf/compiler/java/java_map_field.h @@ -68,9 +68,6 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { private: const FieldDescriptor* descriptor_; map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; ClassNameResolver* name_resolver_; }; 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 ccc1b32e..cd1698f0 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc @@ -139,9 +139,7 @@ ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); 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 82472602..a09cd536 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.h +++ b/src/google/protobuf/compiler/java/java_map_field_lite.h @@ -67,9 +67,6 @@ class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator { private: const FieldDescriptor* descriptor_; map<string, string> variables_; - const int messageBitIndex_; - const int builderBitIndex_; - Context* context_; ClassNameResolver* name_resolver_; }; diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index d2070bc4..5e7eeaa7 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -755,10 +755,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "tion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004s" "pan\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022" "\031\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_de" - "tached_comments\030\006 \003(\tBh\n\023com.google.prot" + "tached_comments\030\006 \003(\tB[\n\023com.google.prot" "obufB\020DescriptorProtosH\001Z\ndescriptor\242\002\003G" - "PB\252\002\'Google.ProtocolBuffers.DescriptorPr" - "otos\260\002\001", 5007); + "PB\252\002\032Google.Protobuf.Reflection\260\002\001", 4994); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index b70b385b..9d3dd8fb 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -44,7 +44,7 @@ option go_package = "descriptor"; option java_package = "com.google.protobuf"; option javanano_use_deprecated_package = true; option java_outer_classname = "DescriptorProtos"; -option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos"; +option csharp_namespace = "Google.Protobuf.Reflection"; option objc_class_prefix = "GPB"; // descriptor.proto must be optimized for speed because reflection-based diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index f78fce21..2e22ccb1 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -82,9 +82,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n\036google/protobuf/duration.proto\022\017google" ".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r" - "\n\005nanos\030\002 \001(\005BH\n\023com.google.protobufB\rDu" - "rationProtoP\001\240\001\001\242\002\003GPB\252\002\026Google.Protocol" - "Buffersb\006proto3", 175); + "\n\005nanos\030\002 \001(\005BP\n\023com.google.protobufB\rDu" + "rationProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Protobuf" + ".WellKnownTypesb\006proto3", 183); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/duration.proto", &protobuf_RegisterTypes); Duration::default_instance_ = new Duration(); diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto index e466341a..0762c3c2 100644 --- a/src/google/protobuf/duration.proto +++ b/src/google/protobuf/duration.proto @@ -35,7 +35,7 @@ option java_generate_equals_and_hash = true; option java_multiple_files = true; option java_outer_classname = "DurationProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; // A Duration represents a signed, fixed-length span of time represented diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index 1a9a6661..1e1c2c8c 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -79,8 +79,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n\033google/protobuf/empty.proto\022\017google.pr" - "otobuf\"\007\n\005EmptyB)\n\023com.google.protobufB\n" - "EmptyProtoP\001\242\002\003GPBb\006proto3", 106); + "otobuf\"\007\n\005EmptyBJ\n\023com.google.protobufB\n" + "EmptyProtoP\001\242\002\003GPB\252\002\036Google.Protobuf.Wel" + "lKnownTypesb\006proto3", 139); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/empty.proto", &protobuf_RegisterTypes); Empty::default_instance_ = new Empty(); diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto index 94df0397..363ec175 100644 --- a/src/google/protobuf/empty.proto +++ b/src/google/protobuf/empty.proto @@ -34,6 +34,7 @@ package google.protobuf; option java_multiple_files = true; option java_outer_classname = "EmptyProto"; option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index 68314fd3..88020ef2 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -81,8 +81,9 @@ void protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n google/protobuf/field_mask.proto\022\017goog" "le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB" - "F\n\023com.google.protobufB\016FieldMaskProtoP\001" - "\242\002\003GPB\252\002\026Google.ProtocolBuffersb\006proto3", 159); + "N\n\023com.google.protobufB\016FieldMaskProtoP\001" + "\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypesb" + "\006proto3", 167); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/field_mask.proto", &protobuf_RegisterTypes); FieldMask::default_instance_ = new FieldMask(); diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto index 35b1acc3..c19f4410 100644 --- a/src/google/protobuf/field_mask.proto +++ b/src/google/protobuf/field_mask.proto @@ -34,7 +34,7 @@ package google.protobuf; option java_multiple_files = true; option java_outer_classname = "FieldMaskProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index 961c1a3f..ad351dc3 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -112,8 +112,8 @@ #include <string> #include <utility> #ifdef _MSC_VER - #if defined(_M_IX86) && \ - !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + // Assuming windows is always little-endian. + #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) #define PROTOBUF_LITTLE_ENDIAN 1 #endif #if _MSC_VER >= 1300 diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 163ce9dc..d928b7a7 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -172,7 +172,7 @@ class Map { !defined(GOOGLE_PROTOBUF_OS_NACL) && !defined(GOOGLE_PROTOBUF_OS_ANDROID) template<class NodeType, class... Args> void construct(NodeType* p, Args&&... args) { - new (p) NodeType(std::forward<Args>(args)...); + new ((void*)p) NodeType(std::forward<Args>(args)...); } template<class NodeType> diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h index 8de11766..52746da5 100644 --- a/src/google/protobuf/map_entry_lite.h +++ b/src/google/protobuf/map_entry_lite.h @@ -162,19 +162,7 @@ class MapEntryLite : public MessageLite { if (!KeyWireHandler::Read(input, mutable_key())) return false; set_has_key(); if (!input->ExpectTag(kValueTag)) break; - // BEGIN GOOGLE LOCAL MODIFICATION - // Add __has_cpp_attribute and NaCl and Emscripten checks. -#if defined(__clang__) && defined(__has_cpp_attribute) \ - && !defined(GOOGLE_PROTOBUF_OS_APPLE) -#if defined(GOOGLE_PROTOBUF_OS_NACL) || defined(EMSCRIPTEN) - [[clang::fallthrough]]; -#elif __has_cpp_attribute(clang::fallthrough) - [[clang::fallthrough]]; -#endif -#else GOOGLE_FALLTHROUGH_INTENDED; -#endif - // END GOOGLE LOCAL MODIFICATION case kValueTag: if (!ValueWireHandler::Read(input, mutable_value())) return false; diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto index febfe5f6..c69e8d94 100644 --- a/src/google/protobuf/map_lite_unittest.proto +++ b/src/google/protobuf/map_lite_unittest.proto @@ -32,7 +32,6 @@ syntax = "proto2"; option cc_enable_arenas = true; option optimize_for = LITE_RUNTIME; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; import "google/protobuf/unittest_lite.proto"; diff --git a/src/google/protobuf/map_proto2_unittest.proto b/src/google/protobuf/map_proto2_unittest.proto index 04ca6170..3d4af28e 100644 --- a/src/google/protobuf/map_proto2_unittest.proto +++ b/src/google/protobuf/map_proto2_unittest.proto @@ -36,8 +36,6 @@ syntax = "proto2"; // In map_test_util.h we do "using namespace unittest = protobuf_unittest". package protobuf_unittest; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; - enum Proto2MapEnum { PROTO2_MAP_ENUM_FOO = 0; PROTO2_MAP_ENUM_BAR = 1; diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto index cbf747d9..b308c7ff 100644 --- a/src/google/protobuf/map_unittest.proto +++ b/src/google/protobuf/map_unittest.proto @@ -31,7 +31,6 @@ syntax = "proto3"; option cc_enable_arenas = true; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; import "google/protobuf/unittest.proto"; diff --git a/src/google/protobuf/map_unittest_proto3.proto b/src/google/protobuf/map_unittest_proto3.proto new file mode 100644 index 00000000..16be2773 --- /dev/null +++ b/src/google/protobuf/map_unittest_proto3.proto @@ -0,0 +1,120 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file is mostly equivalent to map_unittest.proto, but imports +// unittest_proto3.proto instead of unittest.proto, so that it only +// uses proto3 messages. This makes it suitable for testing +// implementations which only support proto3. +// The TestRequiredMessageMap message has been removed as there are no +// required fields in proto3. +syntax = "proto3"; + +option cc_enable_arenas = true; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +import "google/protobuf/unittest_proto3.proto"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In map_test_util.h we do "using namespace unittest = protobuf_unittest". +package protobuf_unittest; + +// Tests maps. +message TestMap { + map<int32 , int32 > map_int32_int32 = 1; + map<int64 , int64 > map_int64_int64 = 2; + map<uint32 , uint32 > map_uint32_uint32 = 3; + map<uint64 , uint64 > map_uint64_uint64 = 4; + map<sint32 , sint32 > map_sint32_sint32 = 5; + map<sint64 , sint64 > map_sint64_sint64 = 6; + map<fixed32 , fixed32 > map_fixed32_fixed32 = 7; + map<fixed64 , fixed64 > map_fixed64_fixed64 = 8; + map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9; + map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10; + map<int32 , float > map_int32_float = 11; + map<int32 , double > map_int32_double = 12; + map<bool , bool > map_bool_bool = 13; + map<string , string > map_string_string = 14; + map<int32 , bytes > map_int32_bytes = 15; + map<int32 , MapEnum > map_int32_enum = 16; + map<int32 , ForeignMessage> map_int32_foreign_message = 17; +} + +message TestMapSubmessage { + TestMap test_map = 1; +} + +message TestMessageMap { + map<int32, TestAllTypes> map_int32_message = 1; +} + +// Two map fields share the same entry default instance. +message TestSameTypeMap { + map<int32, int32> map1 = 1; + map<int32, int32> map2 = 2; +} + +enum MapEnum { + MAP_ENUM_FOO = 0; + MAP_ENUM_BAR = 1; + MAP_ENUM_BAZ = 2; +} + +message TestArenaMap { + map<int32 , int32 > map_int32_int32 = 1; + map<int64 , int64 > map_int64_int64 = 2; + map<uint32 , uint32 > map_uint32_uint32 = 3; + map<uint64 , uint64 > map_uint64_uint64 = 4; + map<sint32 , sint32 > map_sint32_sint32 = 5; + map<sint64 , sint64 > map_sint64_sint64 = 6; + map<fixed32 , fixed32 > map_fixed32_fixed32 = 7; + map<fixed64 , fixed64 > map_fixed64_fixed64 = 8; + map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9; + map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10; + map<int32 , float > map_int32_float = 11; + map<int32 , double > map_int32_double = 12; + map<bool , bool > map_bool_bool = 13; + map<int32 , MapEnum > map_int32_enum = 14; + map<int32 , ForeignMessage> map_int32_foreign_message = 15; +} + +// Previously, message containing enum called Type cannot be used as value of +// map field. +message MessageContainingEnumCalledType { + enum Type { + TYPE_FOO = 0; + } + map<int32, MessageContainingEnumCalledType> type = 1; +} + +// Previously, message cannot contain map field called "entry". +message MessageContainingMapCalledEntry { + map<int32, int32> entry = 1; +} diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index 3b3799a9..5c88363f 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -81,8 +81,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n$google/protobuf/source_context.proto\022\017" "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile" - "_name\030\001 \001(\tB1\n\023com.google.protobufB\022Sour" - "ceContextProtoP\001\242\002\003GPBb\006proto3", 150); + "_name\030\001 \001(\tBR\n\023com.google.protobufB\022Sour" + "ceContextProtoP\001\242\002\003GPB\252\002\036Google.Protobuf" + ".WellKnownTypesb\006proto3", 183); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/source_context.proto", &protobuf_RegisterTypes); SourceContext::default_instance_ = new SourceContext(); diff --git a/src/google/protobuf/source_context.proto b/src/google/protobuf/source_context.proto index 2c8a17a8..98d4920a 100644 --- a/src/google/protobuf/source_context.proto +++ b/src/google/protobuf/source_context.proto @@ -34,6 +34,7 @@ package google.protobuf; option java_multiple_files = true; option java_outer_classname = "SourceContextProto"; option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index 30113cdb..a7e2eafd 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -165,9 +165,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto() { "\000\0220\n\nlist_value\030\006 \001(\0132\032.google.protobuf." "ListValueH\000B\006\n\004kind\"3\n\tListValue\022&\n\006valu" "es\030\001 \003(\0132\026.google.protobuf.Value*\033\n\tNull" - "Value\022\016\n\nNULL_VALUE\020\000BF\n\023com.google.prot" - "obufB\013StructProtoP\001\240\001\001\242\002\003GPB\252\002\026Google.Pr" - "otocolBuffersb\006proto3", 581); + "Value\022\016\n\nNULL_VALUE\020\000BN\n\023com.google.prot" + "obufB\013StructProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Pr" + "otobuf.WellKnownTypesb\006proto3", 589); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/struct.proto", &protobuf_RegisterTypes); Struct::default_instance_ = new Struct(); diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto index cd102731..4ff10cd0 100644 --- a/src/google/protobuf/struct.proto +++ b/src/google/protobuf/struct.proto @@ -35,7 +35,7 @@ option java_generate_equals_and_hash = true; option java_multiple_files = true; option java_outer_classname = "StructProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/stubs/mutex.h b/src/google/protobuf/stubs/mutex.h index 2cce0561..7ef1cb69 100644 --- a/src/google/protobuf/stubs/mutex.h +++ b/src/google/protobuf/stubs/mutex.h @@ -30,6 +30,10 @@ #ifndef GOOGLE_PROTOBUF_STUBS_MUTEX_H_ #define GOOGLE_PROTOBUF_STUBS_MUTEX_H_ +#ifdef GOOGLE_PROTOBUF_NO_THREADLOCAL +#include <pthread.h> +#endif + #include <google/protobuf/stubs/macros.h> // =================================================================== diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h index c86cf35b..8a5d1a13 100644 --- a/src/google/protobuf/stubs/port.h +++ b/src/google/protobuf/stubs/port.h @@ -204,8 +204,19 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF); #define GOOGLE_SAFE_CONCURRENT_WRITES_END() #endif +#if defined(__clang__) && defined(__has_cpp_attribute) \ + && !defined(GOOGLE_PROTOBUF_OS_APPLE) +# if defined(GOOGLE_PROTOBUF_OS_NACL) || defined(EMSCRIPTEN) || \ + __has_cpp_attribute(clang::fallthrough) +# define GOOGLE_FALLTHROUGH_INTENDED [[clang::fallthrough]] +# endif +#endif + +#ifndef GOOGLE_FALLTHROUGH_INTENDED +# define GOOGLE_FALLTHROUGH_INTENDED +#endif + #define GOOGLE_GUARDED_BY(x) -#define GOOGLE_FALLTHROUGH_INTENDED #define GOOGLE_ATTRIBUTE_COLD // x86 and x86-64 can perform unaligned loads/stores directly. diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 877dc8f3..2ee0ec29 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -82,9 +82,9 @@ void protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto() { ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( "\n\037google/protobuf/timestamp.proto\022\017googl" "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003" - "\022\r\n\005nanos\030\002 \001(\005BI\n\023com.google.protobufB\016" - "TimestampProtoP\001\240\001\001\242\002\003GPB\252\002\026Google.Proto" - "colBuffersb\006proto3", 178); + "\022\r\n\005nanos\030\002 \001(\005BQ\n\023com.google.protobufB\016" + "TimestampProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Proto" + "buf.WellKnownTypesb\006proto3", 186); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/timestamp.proto", &protobuf_RegisterTypes); Timestamp::default_instance_ = new Timestamp(); diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto index 381ff997..11f258da 100644 --- a/src/google/protobuf/timestamp.proto +++ b/src/google/protobuf/timestamp.proto @@ -35,7 +35,7 @@ option java_generate_equals_and_hash = true; option java_multiple_files = true; option java_outer_classname = "TimestampProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index 8b08909e..029a72c6 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -221,9 +221,9 @@ void protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto() { "ntext\"S\n\tEnumValue\022\014\n\004name\030\001 \001(\t\022\016\n\006numb" "er\030\002 \001(\005\022(\n\007options\030\003 \003(\0132\027.google.proto" "buf.Option\";\n\006Option\022\014\n\004name\030\001 \001(\t\022#\n\005va" - "lue\030\002 \001(\0132\024.google.protobuf.AnyB(\n\023com.g" - "oogle.protobufB\tTypeProtoP\001\242\002\003GPBb\006proto" - "3", 1321); + "lue\030\002 \001(\0132\024.google.protobuf.AnyBI\n\023com.g" + "oogle.protobufB\tTypeProtoP\001\242\002\003GPB\252\002\036Goog" + "le.Protobuf.WellKnownTypesb\006proto3", 1354); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/type.proto", &protobuf_RegisterTypes); Type::default_instance_ = new Type(); diff --git a/src/google/protobuf/type.proto b/src/google/protobuf/type.proto index ace5d995..ce22d33d 100644 --- a/src/google/protobuf/type.proto +++ b/src/google/protobuf/type.proto @@ -37,6 +37,7 @@ import "google/protobuf/source_context.proto"; option java_multiple_files = true; option java_outer_classname = "TypeProto"; option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto index 834c9b56..85fe6153 100644 --- a/src/google/protobuf/unittest.proto +++ b/src/google/protobuf/unittest.proto @@ -42,7 +42,6 @@ option cc_generic_services = true; // auto-added option java_generic_services = true; // auto-added option py_generic_services = true; // auto-added option cc_enable_arenas = true; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; import "google/protobuf/unittest_import.proto"; diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto index 8f9fb582..d4d6e869 100644 --- a/src/google/protobuf/unittest_custom_options.proto +++ b/src/google/protobuf/unittest_custom_options.proto @@ -41,7 +41,6 @@ syntax = "proto2"; option cc_generic_services = true; // auto-added option java_generic_services = true; // auto-added option py_generic_services = true; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; // A custom file option (defined below). option (file_opt1) = 9876543210; diff --git a/src/google/protobuf/unittest_drop_unknown_fields.proto b/src/google/protobuf/unittest_drop_unknown_fields.proto index faaddc6e..8aa3a37b 100644 --- a/src/google/protobuf/unittest_drop_unknown_fields.proto +++ b/src/google/protobuf/unittest_drop_unknown_fields.proto @@ -33,7 +33,7 @@ syntax = "proto3"; package unittest_drop_unknown_fields; option objc_class_prefix = "DropUnknowns"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; +option csharp_namespace = "Google.Protobuf.TestProtos"; message Foo { enum NestedEnum { diff --git a/src/google/protobuf/unittest_embed_optimize_for.proto b/src/google/protobuf/unittest_embed_optimize_for.proto index c4ccccb7..d8b0f9b9 100644 --- a/src/google/protobuf/unittest_embed_optimize_for.proto +++ b/src/google/protobuf/unittest_embed_optimize_for.proto @@ -39,8 +39,6 @@ import "google/protobuf/unittest_optimize_for.proto"; package protobuf_unittest; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; - // We optimize for speed here, but we are importing a proto that is optimized // for code size. option optimize_for = SPEED; diff --git a/src/google/protobuf/unittest_enormous_descriptor.proto b/src/google/protobuf/unittest_enormous_descriptor.proto index f8fcc9c0..6e65dc18 100644 --- a/src/google/protobuf/unittest_enormous_descriptor.proto +++ b/src/google/protobuf/unittest_enormous_descriptor.proto @@ -40,7 +40,6 @@ syntax = "proto2"; package google.protobuf; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; // Avoid generating insanely long methods. option optimize_for = CODE_SIZE; diff --git a/src/google/protobuf/unittest_import.proto b/src/google/protobuf/unittest_import.proto index ae2e90b8..7e165220 100644 --- a/src/google/protobuf/unittest_import.proto +++ b/src/google/protobuf/unittest_import.proto @@ -47,7 +47,6 @@ option cc_enable_arenas = true; // Exercise the java_package option. option java_package = "com.google.protobuf.test"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; // Do not set a java_outer_classname here to verify that Proto2 works without // one. diff --git a/src/google/protobuf/unittest_import_lite.proto b/src/google/protobuf/unittest_import_lite.proto index ca208582..a7afa452 100644 --- a/src/google/protobuf/unittest_import_lite.proto +++ b/src/google/protobuf/unittest_import_lite.proto @@ -38,7 +38,6 @@ package protobuf_unittest_import; option optimize_for = LITE_RUNTIME; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; import public "google/protobuf/unittest_import_public_lite.proto"; diff --git a/src/google/protobuf/unittest_import_proto3.proto b/src/google/protobuf/unittest_import_proto3.proto new file mode 100644 index 00000000..59673eaf --- /dev/null +++ b/src/google/protobuf/unittest_import_proto3.proto @@ -0,0 +1,68 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file which is imported by unittest_proto3.proto to test importing. + +syntax = "proto3"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do +// "using namespace unittest_import = protobuf_unittest_import". +package protobuf_unittest_import; + +option optimize_for = SPEED; +option cc_enable_arenas = true; + +// Exercise the java_package option. +option java_package = "com.google.protobuf.test"; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +// Do not set a java_outer_classname here to verify that Proto2 works without +// one. + +// Test public import +import public "google/protobuf/unittest_import_public_proto3.proto"; + +message ImportMessage { + int32 d = 1; +} + +enum ImportEnum { + IMPORT_ENUM_UNSPECIFIED = 0; + IMPORT_FOO = 7; + IMPORT_BAR = 8; + IMPORT_BAZ = 9; +} + diff --git a/src/google/protobuf/unittest_import_public.proto b/src/google/protobuf/unittest_import_public.proto index 0bc5d617..ffaf7736 100644 --- a/src/google/protobuf/unittest_import_public.proto +++ b/src/google/protobuf/unittest_import_public.proto @@ -35,7 +35,6 @@ syntax = "proto2"; package protobuf_unittest_import; option java_package = "com.google.protobuf.test"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; message PublicImportMessage { optional int32 e = 1; diff --git a/src/google/protobuf/unittest_import_public_lite.proto b/src/google/protobuf/unittest_import_public_lite.proto index 231ab9dd..33549c22 100644 --- a/src/google/protobuf/unittest_import_public_lite.proto +++ b/src/google/protobuf/unittest_import_public_lite.proto @@ -37,7 +37,6 @@ package protobuf_unittest_import; option optimize_for = LITE_RUNTIME; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; message PublicImportMessageLite { optional int32 e = 1; diff --git a/src/google/protobuf/unittest_import_public_proto3.proto b/src/google/protobuf/unittest_import_public_proto3.proto new file mode 100644 index 00000000..d6f11e28 --- /dev/null +++ b/src/google/protobuf/unittest_import_public_proto3.proto @@ -0,0 +1,42 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: liujisi@google.com (Pherl Liu) + +syntax = "proto3"; + +package protobuf_unittest_import; + +option java_package = "com.google.protobuf.test"; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +message PublicImportMessage { + int32 e = 1; +} diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto index 0040874b..662c0e46 100644 --- a/src/google/protobuf/unittest_lite.proto +++ b/src/google/protobuf/unittest_lite.proto @@ -40,7 +40,6 @@ import "google/protobuf/unittest_import_lite.proto"; option optimize_for = LITE_RUNTIME; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; // Same as TestAllTypes but with the lite runtime. message TestAllTypesLite { diff --git a/src/google/protobuf/unittest_lite_imports_nonlite.proto b/src/google/protobuf/unittest_lite_imports_nonlite.proto index d955cc14..132d6a82 100644 --- a/src/google/protobuf/unittest_lite_imports_nonlite.proto +++ b/src/google/protobuf/unittest_lite_imports_nonlite.proto @@ -38,7 +38,6 @@ package protobuf_unittest; import "google/protobuf/unittest.proto"; option optimize_for = LITE_RUNTIME; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; message TestLiteImportsNonlite { optional TestAllTypes message = 1; diff --git a/src/google/protobuf/unittest_mset.proto b/src/google/protobuf/unittest_mset.proto index 425c9a5a..3aa31fa9 100644 --- a/src/google/protobuf/unittest_mset.proto +++ b/src/google/protobuf/unittest_mset.proto @@ -39,7 +39,6 @@ package protobuf_unittest; option cc_enable_arenas = true; option optimize_for = SPEED; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; // A message with message_set_wire_format. message TestMessageSet { diff --git a/src/google/protobuf/unittest_no_field_presence.proto b/src/google/protobuf/unittest_no_field_presence.proto index f5cc4cc3..994afff4 100644 --- a/src/google/protobuf/unittest_no_field_presence.proto +++ b/src/google/protobuf/unittest_no_field_presence.proto @@ -37,8 +37,6 @@ import "google/protobuf/unittest.proto"; package proto2_nofieldpresence_unittest; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos.Proto3"; - // This proto includes every type of field in both singular and repeated // forms. message TestAllTypes { diff --git a/src/google/protobuf/unittest_optimize_for.proto b/src/google/protobuf/unittest_optimize_for.proto index 2bcd16e4..ee9cc7bd 100644 --- a/src/google/protobuf/unittest_optimize_for.proto +++ b/src/google/protobuf/unittest_optimize_for.proto @@ -40,7 +40,6 @@ import "google/protobuf/unittest.proto"; package protobuf_unittest; option optimize_for = CODE_SIZE; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; message TestOptimizedForSize { optional int32 i = 1; diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto index abc3de28..2f91332c 100644 --- a/src/google/protobuf/unittest_preserve_unknown_enum.proto +++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto @@ -33,7 +33,7 @@ syntax = "proto3"; package proto3_preserve_unknown_enum_unittest; option objc_class_prefix = "UnknownEnums"; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; +option csharp_namespace = "Google.Protobuf.TestProtos"; enum MyEnum { FOO = 0; diff --git a/src/google/protobuf/unittest_preserve_unknown_enum2.proto b/src/google/protobuf/unittest_preserve_unknown_enum2.proto index 168b2407..adf42968 100644 --- a/src/google/protobuf/unittest_preserve_unknown_enum2.proto +++ b/src/google/protobuf/unittest_preserve_unknown_enum2.proto @@ -32,8 +32,6 @@ syntax = "proto2"; package proto2_preserve_unknown_enum_unittest; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; - enum MyEnum { FOO = 0; BAR = 1; diff --git a/src/google/protobuf/unittest_proto3.proto b/src/google/protobuf/unittest_proto3.proto new file mode 100644 index 00000000..f59d2178 --- /dev/null +++ b/src/google/protobuf/unittest_proto3.proto @@ -0,0 +1,388 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. + +syntax = "proto3"; + +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added +option java_generic_services = true; // auto-added +option py_generic_services = true; // auto-added +option cc_enable_arenas = true; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +import "google/protobuf/unittest_import_proto3.proto"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do "using namespace unittest = protobuf_unittest". +package protobuf_unittest; + +// Protos optimized for SPEED use a strict superset of the generated code +// of equivalent ones optimized for CODE_SIZE, so we should optimize all our +// tests for speed unless explicitly testing code size optimization. +option optimize_for = SPEED; + +option java_outer_classname = "UnittestProto"; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + enum NestedEnum { + NESTED_ENUM_UNSPECIFIED = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 single_int32 = 1; + int64 single_int64 = 2; + uint32 single_uint32 = 3; + uint64 single_uint64 = 4; + sint32 single_sint32 = 5; + sint64 single_sint64 = 6; + fixed32 single_fixed32 = 7; + fixed64 single_fixed64 = 8; + sfixed32 single_sfixed32 = 9; + sfixed64 single_sfixed64 = 10; + float single_float = 11; + double single_double = 12; + bool single_bool = 13; + string single_string = 14; + bytes single_bytes = 15; + + NestedMessage single_nested_message = 18; + ForeignMessage single_foreign_message = 19; + protobuf_unittest_import.ImportMessage single_import_message = 20; + + NestedEnum single_nested_enum = 21; + ForeignEnum single_foreign_enum = 22; + protobuf_unittest_import.ImportEnum single_import_enum = 23; + + // Defined in unittest_import_public.proto + protobuf_unittest_import.PublicImportMessage + single_public_import_message = 26; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + // Defined in unittest_import_public.proto + repeated protobuf_unittest_import.PublicImportMessage + repeated_public_import_message = 54; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; + repeated NestedTestAllTypes repeated_child = 3; +} + +message TestDeprecatedFields { + int32 deprecated_int32 = 1 [deprecated=true]; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_UNSPECIFIED = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +message TestReservedFields { + reserved 2, 15, 9 to 11; + reserved "bar", "baz"; +} + + +// Test that we can use NestedMessage from outside TestAllTypes. +message TestForeignNested { + TestAllTypes.NestedMessage foreign_nested = 1; +} + +// Test that really large tag numbers don't break anything. +message TestReallyLargeTagNumber { + // The largest possible tag number is 2^28 - 1, since the wire format uses + // three bits to communicate wire type. + int32 a = 1; + int32 bb = 268435455; +} + +message TestRecursiveMessage { + TestRecursiveMessage a = 1; + int32 i = 2; +} + +// Test that mutual recursion works. +message TestMutualRecursionA { + TestMutualRecursionB bb = 1; +} + +message TestMutualRecursionB { + TestMutualRecursionA a = 1; + int32 optional_int32 = 2; +} + + +// Test an enum that has multiple values with the same number. +enum TestEnumWithDupValue { + TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0; + option allow_alias = true; + + FOO1 = 1; + BAR1 = 2; + BAZ = 3; + FOO2 = 1; + BAR2 = 2; +} + +// Test an enum with large, unordered values. +enum TestSparseEnum { + TEST_SPARSE_ENUM_UNSPECIFIED = 0; + SPARSE_A = 123; + SPARSE_B = 62374; + SPARSE_C = 12589234; + SPARSE_D = -15; + SPARSE_E = -53452; + // In proto3, value 0 must be the first one specified + // SPARSE_F = 0; + SPARSE_G = 2; +} + +// Test message with CamelCase field names. This violates Protocol Buffer +// standard style. +message TestCamelCaseFieldNames { + int32 PrimitiveField = 1; + string StringField = 2; + ForeignEnum EnumField = 3; + ForeignMessage MessageField = 4; + + repeated int32 RepeatedPrimitiveField = 7; + repeated string RepeatedStringField = 8; + repeated ForeignEnum RepeatedEnumField = 9; + repeated ForeignMessage RepeatedMessageField = 10; +} + + +// We list fields out of order, to ensure that we're using field number and not +// field index to determine serialization order. +message TestFieldOrderings { + string my_string = 11; + int64 my_int = 1; + float my_float = 101; + message NestedMessage { + int64 oo = 2; + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + NestedMessage single_nested_message = 200; +} + +message SparseEnumMessage { + TestSparseEnum sparse_enum = 1; +} + +// Test String and Bytes: string is for valid UTF-8 strings +message OneString { + string data = 1; +} + +message MoreString { + repeated string data = 1; +} + +message OneBytes { + bytes data = 1; +} + +message MoreBytes { + bytes data = 1; +} + +// Test int32, uint32, int64, uint64, and bool are all compatible +message Int32Message { + int32 data = 1; +} + +message Uint32Message { + uint32 data = 1; +} + +message Int64Message { + int64 data = 1; +} + +message Uint64Message { + uint64 data = 1; +} + +message BoolMessage { + bool data = 1; +} + +// Test oneofs. +message TestOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + } +} + +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// A message with the same fields as TestPackedTypes, but without packing. Used +// to test packed <-> unpacked wire compatibility. +message TestUnpackedTypes { + repeated int32 unpacked_int32 = 90 [packed = false]; + repeated int64 unpacked_int64 = 91 [packed = false]; + repeated uint32 unpacked_uint32 = 92 [packed = false]; + repeated uint64 unpacked_uint64 = 93 [packed = false]; + repeated sint32 unpacked_sint32 = 94 [packed = false]; + repeated sint64 unpacked_sint64 = 95 [packed = false]; + repeated fixed32 unpacked_fixed32 = 96 [packed = false]; + repeated fixed64 unpacked_fixed64 = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 99 [packed = false]; + repeated float unpacked_float = 100 [packed = false]; + repeated double unpacked_double = 101 [packed = false]; + repeated bool unpacked_bool = 102 [packed = false]; + repeated ForeignEnum unpacked_enum = 103 [packed = false]; +} + +message TestRepeatedScalarDifferentTagSizes { + // Parsing repeated fixed size values used to fail. This message needs to be + // used in order to get a tag of the right size; all of the repeated fields + // in TestAllTypes didn't trigger the check. + repeated fixed32 repeated_fixed32 = 12; + // Check for a varint type, just for good measure. + repeated int32 repeated_int32 = 13; + + // These have two-byte tags. + repeated fixed64 repeated_fixed64 = 2046; + repeated int64 repeated_int64 = 2047; + + // Three byte tags. + repeated float repeated_float = 262142; + repeated uint64 repeated_uint64 = 262143; +} + +message TestCommentInjectionMessage { + // */ <- This should not close the generated doc comment + string a = 1; +} + + +// Test that RPC services work. +message FooRequest {} +message FooResponse {} + +message FooClientMessage {} +message FooServerMessage{} + +service TestService { + rpc Foo(FooRequest) returns (FooResponse); + rpc Bar(BarRequest) returns (BarResponse); +} + + +message BarRequest {} +message BarResponse {} + diff --git a/src/google/protobuf/unittest_well_known_types.proto b/src/google/protobuf/unittest_well_known_types.proto index e157260e..2cb7775c 100644 --- a/src/google/protobuf/unittest_well_known_types.proto +++ b/src/google/protobuf/unittest_well_known_types.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package protobuf_unittest; +option csharp_namespace = "Google.Protobuf.TestProtos"; option java_multiple_files = true; option java_package = "com.google.protobuf.test"; @@ -17,6 +18,8 @@ import "google/protobuf/type.proto"; import "google/protobuf/wrappers.proto"; // Test that we can include all well-known types. +// Each wrapper type is included separately, as languages +// map handle different wrappers in different ways. message TestWellKnownTypes { google.protobuf.Any any_field = 1; google.protobuf.Api api_field = 2; @@ -27,5 +30,83 @@ message TestWellKnownTypes { google.protobuf.Struct struct_field = 7; google.protobuf.Timestamp timestamp_field = 8; google.protobuf.Type type_field = 9; - google.protobuf.Int32Value int32_field = 10; + google.protobuf.DoubleValue double_field = 10; + google.protobuf.FloatValue float_field = 11; + google.protobuf.Int64Value int64_field = 12; + google.protobuf.UInt64Value uint64_field = 13; + google.protobuf.Int32Value int32_field = 14; + google.protobuf.UInt32Value uint32_field = 15; + google.protobuf.BoolValue bool_field = 16; + google.protobuf.StringValue string_field = 17; + google.protobuf.BytesValue bytes_field = 18; +} + +// A repeated field for each well-known type. +message RepeatedWellKnownTypes { + repeated google.protobuf.Any any_field = 1; + repeated google.protobuf.Api api_field = 2; + repeated google.protobuf.Duration duration_field = 3; + repeated google.protobuf.Empty empty_field = 4; + repeated google.protobuf.FieldMask field_mask_field = 5; + repeated google.protobuf.SourceContext source_context_field = 6; + repeated google.protobuf.Struct struct_field = 7; + repeated google.protobuf.Timestamp timestamp_field = 8; + repeated google.protobuf.Type type_field = 9; + // These don't actually make a lot of sense, but they're not prohibited... + repeated google.protobuf.DoubleValue double_field = 10; + repeated google.protobuf.FloatValue float_field = 11; + repeated google.protobuf.Int64Value int64_field = 12; + repeated google.protobuf.UInt64Value uint64_field = 13; + repeated google.protobuf.Int32Value int32_field = 14; + repeated google.protobuf.UInt32Value uint32_field = 15; + repeated google.protobuf.BoolValue bool_field = 16; + repeated google.protobuf.StringValue string_field = 17; + repeated google.protobuf.BytesValue bytes_field = 18; +} + +message OneofWellKnownTypes { + oneof oneof_field { + google.protobuf.Any any_field = 1; + google.protobuf.Api api_field = 2; + google.protobuf.Duration duration_field = 3; + google.protobuf.Empty empty_field = 4; + google.protobuf.FieldMask field_mask_field = 5; + google.protobuf.SourceContext source_context_field = 6; + google.protobuf.Struct struct_field = 7; + google.protobuf.Timestamp timestamp_field = 8; + google.protobuf.Type type_field = 9; + google.protobuf.DoubleValue double_field = 10; + google.protobuf.FloatValue float_field = 11; + google.protobuf.Int64Value int64_field = 12; + google.protobuf.UInt64Value uint64_field = 13; + google.protobuf.Int32Value int32_field = 14; + google.protobuf.UInt32Value uint32_field = 15; + google.protobuf.BoolValue bool_field = 16; + google.protobuf.StringValue string_field = 17; + google.protobuf.BytesValue bytes_field = 18; + } +} + +// A map field for each well-known type. We only +// need to worry about the value part of the map being the +// well-known types, as messages can't be map keys. +message MapWellKnownTypes { + map<int32,google.protobuf.Any> any_field = 1; + map<int32,google.protobuf.Api> api_field = 2; + map<int32,google.protobuf.Duration> duration_field = 3; + map<int32,google.protobuf.Empty> empty_field = 4; + map<int32,google.protobuf.FieldMask> field_mask_field = 5; + map<int32,google.protobuf.SourceContext> source_context_field = 6; + map<int32,google.protobuf.Struct> struct_field = 7; + map<int32,google.protobuf.Timestamp> timestamp_field = 8; + map<int32,google.protobuf.Type> type_field = 9; + map<int32,google.protobuf.DoubleValue> double_field = 10; + map<int32,google.protobuf.FloatValue> float_field = 11; + map<int32,google.protobuf.Int64Value> int64_field = 12; + map<int32,google.protobuf.UInt64Value> uint64_field = 13; + map<int32,google.protobuf.Int32Value> int32_field = 14; + map<int32,google.protobuf.UInt32Value> uint32_field = 15; + map<int32,google.protobuf.BoolValue> bool_field = 16; + map<int32,google.protobuf.StringValue> string_field = 17; + map<int32,google.protobuf.BytesValue> bytes_field = 18; } diff --git a/src/google/protobuf/unknown_enum_test.proto b/src/google/protobuf/unknown_enum_test.proto index 3c549cc7..0ea1ede3 100644 --- a/src/google/protobuf/unknown_enum_test.proto +++ b/src/google/protobuf/unknown_enum_test.proto @@ -36,8 +36,6 @@ syntax = "proto2"; package google.protobuf.util; -option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; - message DownRevision { enum Enum { DEFAULT_VALUE = 2; diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index ffc77f1c..db75db15 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -262,9 +262,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto() { "e\030\001 \001(\004\"\033\n\nInt32Value\022\r\n\005value\030\001 \001(\005\"\034\n\013" "UInt32Value\022\r\n\005value\030\001 \001(\r\"\032\n\tBoolValue\022" "\r\n\005value\030\001 \001(\010\"\034\n\013StringValue\022\r\n\005value\030\001" - " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014BE\n\023com" + " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014BM\n\023com" ".google.protobufB\rWrappersProtoP\001\242\002\003GPB\252" - "\002\026Google.ProtocolBuffersb\006proto3", 392); + "\002\036Google.Protobuf.WellKnownTypesb\006proto3", 400); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/wrappers.proto", &protobuf_RegisterTypes); DoubleValue::default_instance_ = new DoubleValue(); diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto index a13e6edb..6d3181bf 100644 --- a/src/google/protobuf/wrappers.proto +++ b/src/google/protobuf/wrappers.proto @@ -40,7 +40,7 @@ package google.protobuf; option java_multiple_files = true; option java_outer_classname = "WrappersProto"; option java_package = "com.google.protobuf"; -option csharp_namespace = "Google.ProtocolBuffers"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option objc_class_prefix = "GPB"; |