Commit f5242682 authored by Jon Skeet's avatar Jon Skeet

First stab at new proto3-only code generator

parent 8fe039a6
......@@ -369,8 +369,6 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/csharp/csharp_enum.h \
google/protobuf/compiler/csharp/csharp_enum_field.cc \
google/protobuf/compiler/csharp/csharp_enum_field.h \
google/protobuf/compiler/csharp/csharp_extension.cc \
google/protobuf/compiler/csharp/csharp_extension.h \
google/protobuf/compiler/csharp/csharp_field_base.cc \
google/protobuf/compiler/csharp/csharp_field_base.h \
google/protobuf/compiler/csharp/csharp_generator.cc \
......@@ -391,9 +389,7 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/csharp/csharp_source_generator_base.cc \
google/protobuf/compiler/csharp/csharp_source_generator_base.h \
google/protobuf/compiler/csharp/csharp_umbrella_class.cc \
google/protobuf/compiler/csharp/csharp_umbrella_class.h \
google/protobuf/compiler/csharp/csharp_writer.cc \
google/protobuf/compiler/csharp/csharp_writer.h
google/protobuf/compiler/csharp/csharp_umbrella_class.h
bin_PROGRAMS = protoc
protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
......
......@@ -58,7 +58,7 @@ EnumGenerator::~EnumGenerator() {
void EnumGenerator::Generate(io::Printer* printer) {
WriteGeneratedCodeAttributes(printer);
printer->Print("$access_level$ enum $name$ {\n",
printer->Print("$access_level$ enum $name$ : long {\n",
"access_level", class_access_level(),
"name", descriptor_->name());
printer->Indent();
......
......@@ -55,27 +55,13 @@ 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");
"input.ReadEnum(ref $name$_);\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"
" output.WriteEnum($number$, fieldNames[$field_ordinal$], (long) $property_name$, $property_name$);\n"
"}\n");
}
......@@ -83,7 +69,7 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n"
" size += pb::CodedOutputStream.ComputeEnumSize($number$, (long) $property_name$);\n"
"}\n");
}
......@@ -96,30 +82,21 @@ 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"
"if(input.ReadEnum(ref enumValue)) {\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");
"}\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.WriteEnum($number$, fieldNames[$field_ordinal$], (long) $property_name$, $property_name$);\n"
"}\n");
}
......@@ -127,7 +104,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 += pb::CodedOutputStream.ComputeEnumSize($number$, (long) $property_name$);\n"
"}\n");
}
......
// 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
// 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_EXTENSION_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_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 ExtensionGenerator : public FieldGeneratorBase {
public:
ExtensionGenerator(const FieldDescriptor* descriptor);
~ExtensionGenerator();
void GenerateStaticVariableInitializers(io::Printer* printer);
void GenerateExtensionRegistrationCode(io::Printer* printer);
void Generate(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);
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__
......@@ -263,37 +263,13 @@ bool AllPrintableAscii(const std::string& text) {
}
std::string FieldGeneratorBase::GetStringDefaultValueInternal() {
if (!descriptor_->has_default_value()) {
// No other default values needed for proto3...
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";
}
std::string FieldGeneratorBase::GetBytesDefaultValueInternal() {
if (!descriptor_->has_default_value()) {
// No other default values needed for proto3...
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";
}
std::string FieldGeneratorBase::default_value() {
......@@ -365,11 +341,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:
......
......@@ -42,17 +42,13 @@ namespace protobuf {
namespace compiler {
namespace csharp {
class Writer;
class FieldGeneratorBase : public SourceGeneratorBase {
public:
FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal);
~FieldGeneratorBase();
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;
......@@ -82,7 +78,6 @@ class FieldGeneratorBase : public SourceGeneratorBase {
bool is_nullable_type();
std::string default_value();
std::string number();
std::string message_or_group();
std::string capitalized_type_name();
std::string field_ordinal();
......
......@@ -43,7 +43,6 @@
#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>
......@@ -106,7 +105,7 @@ std::string GetUniqueFileScopeIdentifier(const Descriptor* descriptor) {
}
void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
// Because descriptor.proto (Google.ProtocolBuffers.DescriptorProtos) is
// Because descriptor.proto (Google.Protobuf.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
......@@ -115,14 +114,12 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
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",
"internal static pb::FieldAccess.FieldAccessorTable<$full_class_name$> 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));
......@@ -139,7 +136,6 @@ void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer)
vars["parent"] = GetUniqueFileScopeIdentifier(
descriptor_->containing_type());
}
if (!use_lite_runtime()) {
printer->Print(vars, "internal__$identifier$__Descriptor = ");
if (!descriptor_->containing_type()) {
......@@ -151,7 +147,7 @@ void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer)
printer->Print(
vars,
"internal__$identifier$__FieldAccessorTable = \n"
" new pb::FieldAccess.FieldAccessorTable<$full_class_name$, $full_class_name$.Builder>(internal__$identifier$__Descriptor,\n");
" new pb::FieldAccess.FieldAccessorTable<$full_class_name$>(internal__$identifier$__Descriptor,\n");
printer->Print(" new string[] { ");
for (int i = 0; i < descriptor_->field_count(); i++) {
printer->Print("\"$property_name$\", ",
......@@ -163,27 +159,18 @@ void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer)
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_);
......@@ -192,19 +179,13 @@ void MessageGenerator::Generate(io::Printer* printer) {
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();
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");
if (optimize_speed()) {
// All static fields and properties
printer->Print(
"private static readonly string[] _$name$FieldNames = "
"private static readonly string[] _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;
......@@ -214,64 +195,47 @@ void MessageGenerator::Generate(io::Printer* printer) {
tags.push_back(SimpleItoa(tag));
}
printer->Print(
"private static readonly uint[] _$name$FieldTags = new uint[] { $tags$ };\n",
"name", UnderscoresToCamelCase(class_name(), false),
"private static readonly uint[] _fieldTags = new uint[] { $tags$ };\n",
"tags", JoinStrings(tags, ", "));
}
printer->Print(
vars,
"public static $class_name$ DefaultInstance {\n"
" get { return defaultInstance; }\n"
"}\n"
"\n"
"public override $class_name$ DefaultInstanceForType {\n"
" get { return DefaultInstance; }\n"
"}\n"
"\n"
"protected override $class_name$ ThisMessage {\n"
" get { return this; }\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"
"protected override pb::FieldAccess.FieldAccessorTable<$class_name$> InternalFieldAccessors {\n"
" get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n"
"}\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);
}
// Constructors
printer->Print(
vars,
"public $class_name$() { }\n"); // Public parameterless ctor.
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");
printer->Print(
vars,
"public $class_name$($class_name$ other) {\n"
" MergeWith(other);\n"
"}\n"); // Merge ctor.
// 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);
......@@ -280,13 +244,13 @@ void MessageGenerator::Generate(io::Printer* printer) {
"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 +258,78 @@ 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"
"private Clear$property_name$() {;\n"
" $name$Case_ = $property_name$OneofCase.None;"
" $name$_ = null;"
"}\n\n");
}
// Fields
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");
}
// TODO(jonskeet): Map properties
if (optimize_speed()) {
if (SupportFieldPresence(descriptor_->file())) {
GenerateIsInitialized(printer);
}
// Standard methods
GenerateMessageSerializationMethods(printer);
}
if (use_lite_runtime()) {
GenerateLiteRuntimeMethods(printer);
}
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");
}
void MessageGenerator::GenerateLiteRuntimeMethods(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->Indent();
printer->Print("int hash = GetType().GetHashCode();\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->containing_oneof() == NULL) {
scoped_ptr<FieldGeneratorBase> generator(
CreateFieldGeneratorInternal(field));
generator->WriteHash(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");
}
printer->Print("return hash;\n");
printer->Outdent();
printer->Print("}\n");
printer->Print("\n");
GenerateMergingMethods(printer);
printer->Print("public override bool Equals(object obj) {\n");
// Nested messages and enums
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();
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);
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
EnumGenerator enumGenerator(descriptor_->enum_type(i));
enumGenerator.Generate(printer);
}
if (callbase) {
printer->Print("if (!base.Equals(other)) return false;\n");
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
MessageGenerator messageGenerator(descriptor_->nested_type(i));
messageGenerator.Generate(printer);
}
printer->Print("return true;\n");
printer->Outdent();
printer->Print("}\n");
printer->Print("\n");
printer->Print(
"public override void PrintTo(global::System.IO.TextWriter writer) {\n");
printer->Indent();
for (int i = 0; i < fields_by_number().size(); i++) {
scoped_ptr<FieldGeneratorBase> generator(
CreateFieldGeneratorInternal(fields_by_number()[i]));
generator->WriteToString(printer);
printer->Print("}\n"
"#endregion\n"
"\n");
}
if (callbase) {
printer->Print("base.PrintTo(writer);\n");
}
printer->Outdent();
printer->Print("}\n");
printer->Print("#endregion\n");
printer->Print("\n");
}
bool CompareExtensionRangesStart(const Descriptor::ExtensionRange* r1,
const Descriptor::ExtensionRange* r2) {
return r1->start < r2->start;
}
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::ICodedOutputStream 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());
}
printer->Print("string[] fieldNames = _fieldNames;\n");
// 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 CalculateSerializedSize() {\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));
}
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,212 +338,14 @@ 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");
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");
"public void MergeWith($class_name$ other) {\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);
}
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");
}
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.
printer->Indent();
printer->Print(
vars,
"if (other == $full_class_name$.DefaultInstance) return this;\n"
"PrepareBuilder();\n");
// TODO(jonskeet): Maps?
// Merge non-oneof fields
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->containing_oneof()) {
scoped_ptr<FieldGeneratorBase> generator(
......@@ -752,7 +353,6 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
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);
......@@ -764,114 +364,46 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
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");
"case $property_name$OneofCase.$field_property_name$:\n"
" $field_property_name$ = other.$field_property_name$;\n"
" break;\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");
printer->Print("}\n\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->Print("public void MergeFrom(pb::ICodedInputStream 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");
"string fieldName;\n"
"while (input.ReadTag(out tag, out fieldName)) {\n"
" if (tag == 0 && fieldName != null) {");
printer->Indent();
printer->Print("if(tag == 0 && field_name != null) {\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");
"int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.String.String.Ordinal);\n"
"if (fieldOrdinal >= 0) {\n"
" tag = _fieldTags[fieldOrdinal];\n"
"}\n"
"switch(tag) {\n");
printer->Indent();
printer->Print(
"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;"); // 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);
// TODO(jonskeet): Understand what this is trying to do
if (field->is_repeated()
&& (wt == internal::WireFormatLite::WIRETYPE_VARINT
|| wt == internal::WireFormatLite::WIRETYPE_FIXED32
......@@ -894,95 +426,14 @@ 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->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->Print("}\n"); // if
printer->Outdent();
printer->Print("}\n");
printer->Print("}\n"); // while
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) {
......
......@@ -43,7 +43,6 @@ namespace protobuf {
namespace compiler {
namespace csharp {
class Writer;
class FieldGeneratorBase;
class MessageGenerator : public SourceGeneratorBase {
......@@ -53,7 +52,6 @@ class MessageGenerator : public SourceGeneratorBase {
void GenerateStaticVariables(io::Printer* printer);
void GenerateStaticVariableInitializers(io::Printer* printer);
void GenerateExtensionRegistrationCode(io::Printer* printer);
void Generate(io::Printer* printer);
private:
......@@ -61,17 +59,8 @@ 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(
......@@ -95,4 +84,3 @@ class MessageGenerator : public SourceGeneratorBase {
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__
......@@ -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"] = property_name() + "_ != null";
variables_["has_not_property_check"] = property_name() + "_ == null";
}
MessageFieldGenerator::~MessageFieldGenerator() {
......@@ -60,125 +60,42 @@ 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"
" }\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"
" get { return $name$_; }\n"
" set { return $name$_ = value; }\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$.MergeWith(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"
"input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP...
}
void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
// TODO(jonskeet): Why are we using array access instead of a literal here?
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" output.Write$message_or_group$($number$, field_names[$field_ordinal$], $property_name$);\n"
" output.WriteMessage($number$, fieldNames[$field_ordinal$], $property_name$);\n"
"}\n");
}
......@@ -186,19 +103,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 += pb::CodedOutputStream.ComputeMessageSize($number$, $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 ^= $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_);
......@@ -218,118 +135,30 @@ 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"
" }\n"
" return this;\n"
" get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
" set { \n"
" $name$_ = value;"
" $oneof_name$Case_ = value == null ? $oneof_property_name$Case.None : $oneof_property_name$Case.$property_name$; }\n"
" } \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"
" 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");
"$type_name$ subBuilder = new type_name$();\n"
"if ($has_property_check$) {\n"
" subBuilder.MergeWith($property_name$);\n"
"}\n"
"input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP
"$oneof_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_,
......
......@@ -41,17 +41,13 @@ namespace protobuf {
namespace compiler {
namespace csharp {
class Writer;
class MessageFieldGenerator : public FieldGeneratorBase {
public:
MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
~MessageFieldGenerator();
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);
......@@ -70,8 +66,6 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator {
~MessageOneofFieldGenerator();
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);
......
......@@ -49,82 +49,37 @@ 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;
}
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"
" get { return $name$_; }\n"
"}\n");
}
void PrimitiveFieldGenerator::GenerateBuilderMembers(io::Printer* printer) {
AddDeprecatedFlag(printer);
if (SupportFieldPresence(descriptor_->file())) {
printer->Print(
variables_,
"public bool Has$property_name$ {\n"
" get { return result.has$property_name$; }\n"
"}\n");
}
AddPublicMemberAttributes(printer);
" get { return $name$_; }\n");
if (is_value_type) {
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())) {
" set { $name$_ = value; }\n");
} else {
printer->Print(
variables_,
" result.has$property_name$ = false;\n");
" set { $name$_ = value ?? $default_value$; }\n");
}
printer->Print(
variables_,
" result.$name$_ = $default_value$;\n"
" return this;\n"
"}\n");
printer->Print("}\n\n");
}
void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
......@@ -135,27 +90,17 @@ 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");
}
}
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.Write$capitalized_type_name$($number$, fieldNames[$field_ordinal$], $property_name$);\n"
"}\n");
}
......@@ -171,24 +116,18 @@ void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_property_check$) {\n"
" hash ^= $name$_.GetHashCode();\n"
" hash ^= $property_name$.GetHashCode();\n"
"}\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");
}
"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");
}
PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
......@@ -201,79 +140,43 @@ PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {
}
void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
// TODO(jonskeet): What should foo.OneofIntField = 0; do? Clear the oneof?
// Currently foo.OneOfStringField = null will clear the oneof, but foo.OneOfStringField = "" won't. Ick.
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"
" 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 {");
if (is_value_type) {
printer->Print(
variables_,
"public bool Has$property_name$ {\n"
" get { return result.$has_property_check$; }\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);
" $oneof_name$_ = value;\n"
" $oneof_name$Case_ = $oneof_property_name$Case.$property_name$;\n");
} else {
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);
" $oneof_name$_ = value ?? $default_value$;\n"
" $oneof_name$Case_ = value == null ? $oneof_property_name$Case.None : $oneof_property_name$Case.$property_name$;\n");
}
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) {
// TODO(jonskeet): What if the value we read is the default value for the type?
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"
" $oneof_name$_ = value;\n"
" $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
"}\n");
}
......
......@@ -41,17 +41,13 @@ namespace protobuf {
namespace compiler {
namespace csharp {
class Writer;
class PrimitiveFieldGenerator : public FieldGeneratorBase {
public:
PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
~PrimitiveFieldGenerator();
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 +56,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);
};
......@@ -70,8 +69,6 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
~PrimitiveOneofFieldGenerator();
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);
......
......@@ -56,141 +56,46 @@ 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.
"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"
"}\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);
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");
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"public Builder Clear$property_name$() {\n"
" PrepareBuilder();\n"
" result.$name$_.Clear();\n"
" return this;\n"
"public 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");
}
"input.ReadEnumArray<$type_name$>(tag, fieldName, result.$name$_);\n");
}
void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
printer->Print(variables_, "if ($name$_.Count > 0) {\n");
printer->Indent();
// TODO(jonskeet): Originally, this checked for Count > 0 first.
// The Write* call should make that cheap though - no need to generate it every time.
if (descriptor_->is_packed()) {
printer->Print(
variables_,
"output.WritePackedEnumArray($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n");
"output.WritePackedEnumArray($number$, fieldNames[$field_ordinal$], $name$_);\n");
} else {
printer->Print(variables_,
"output.WriteEnumArray($number$, field_names[$field_ordinal$], $name$_);\n");
"output.WriteEnumArray($number$, fieldNames[$field_ordinal$], $name$_);\n");
}
printer->Outdent();
printer->Print("}\n");
}
void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
printer->Print("{\n");
printer->Indent();
// TODO(jonskeet): Move all this code into CodedOutputStream? It's a lot to repeat everywhere...
printer->Print(
variables_,
"int dataSize = 0;\n"
......@@ -199,7 +104,7 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer
printer->Print(
variables_,
"foreach ($type_name$ element in $name$_) {\n"
" dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n"
" dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((long) element);\n"
"}\n"
"size += dataSize;\n");
int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
......@@ -215,11 +120,6 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer
}
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");
}
......@@ -227,16 +127,15 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer
void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) {
printer->Print(
variables_,
"foreach($type_name$ i in $name$_)\n"
" hash ^= i.GetHashCode();\n");
"foreach($type_name$ i in $name$_) {\n"
" hash ^= i.GetHashCode();\n"
"}\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) {
......
......@@ -41,17 +41,15 @@ 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 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);
......
......@@ -48,7 +48,6 @@ namespace csharp {
RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
const FieldDescriptor* descriptor, int fieldOrdinal)
: FieldGeneratorBase(descriptor, fieldOrdinal) {
variables_["message_or_group"] = message_or_group();
}
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
......@@ -58,11 +57,11 @@ RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n");
"private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n");
AddDeprecatedFlag(printer);
printer->Print(
variables_,
"public scg::IList<$type_name$> $property_name$List {\n"
"public pbc::RepeatedField<$type_name$> $property_name$ {\n"
" get { return $name$_; }\n"
"}\n");
......@@ -82,137 +81,46 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
"}\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);
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");
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"
"}\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");
"input.ReadMessageArray(tag, fieldName, $name$_);\n");
}
void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
// TODO(jonskeet): Originally, this checked for Count > 0 first.
// The Write* call should make that cheap though - no need to generate it every time.
printer->Print(
variables_,
"if ($name$_.Count > 0) {\n"
" output.Write$message_or_group$Array($number$, field_names[$field_ordinal$], $name$_);\n"
"}\n");
"output.WriteMessageArray($number$, fieldNames[$field_ordinal$], $name$_);\n");
}
void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
// TODO(jonskeet): Put this into CodedOutputStream.
printer->Print(
variables_,
"foreach ($type_name$ element in $property_name$List) {\n"
" size += pb::CodedOutputStream.Compute$message_or_group$Size($number$, element);\n"
"foreach ($type_name$ element in $property_name$) {\n"
" size += pb::CodedOutputStream.ComputeMessageSize($number$, element);\n"
"}\n");
}
void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) {
printer->Print(
variables_,
"foreach($type_name$ i in $name$_)\n"
" hash ^= i.GetHashCode();\n");
"foreach($type_name$ i in $name$_) {\n"
" hash ^= i.GetHashCode();\n"
"}\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_);
......
......@@ -41,17 +41,13 @@ namespace protobuf {
namespace compiler {
namespace csharp {
class Writer;
class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
public:
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
~RepeatedMessageFieldGenerator();
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);
......
......@@ -56,129 +56,43 @@ 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 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"
"}\n");
AddPublicMemberAttributes(printer);
printer->Print(
variables_,
"public $type_name$ Get$property_name$(int index) {\n"
" return $name$_[index];\n"
"}\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);
printer->Print(
variables_,
"public Builder Clear$property_name$() {\n"
" PrepareBuilder();\n"
" result.$name$_.Clear();\n"
" return this;\n"
"public pbc::RepeatedField<$type_name$> $property_name$ {\n"
" get { return $name$_; }\n"
"}\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
printer->Print(
variables_,
"if (other.$name$_.Count != 0) {\n"
" result.$name$_.Add(other.$name$_);\n"
"}\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateBuildingCode(io::Printer* printer) {
printer->Print(variables_, "$name$_.MakeReadOnly();\n");
"$name$_.Add(other.$name$_);\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(variables_,
"input.Read$capitalized_type_name$Array(tag, field_name, result.$name$_);\n");
"input.Read$capitalized_type_name$Array(tag, fieldName, $name$_);\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(
io::Printer* printer) {
printer->Print(variables_, "if ($name$_.Count > 0) {\n");
printer->Indent();
// TODO(jonskeet): Originally, this checked for Count > 0 first.
// The Write* call should make that cheap though - no need to generate it every time.
if (descriptor_->is_packed()) {
printer->Print(variables_,
"output.WritePacked$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n");
"output.WritePacked$capitalized_type_name$Array($number$, fieldNames[$field_ordinal$], $name$_);\n");
} else {
printer->Print(variables_,
"output.Write$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$_);\n");
"output.Write$capitalized_type_name$Array($number$, fieldNames[$field_ordinal$], $name$_);\n");
}
printer->Outdent();
printer->Print("}\n");
}
void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
io::Printer* printer) {
// TODO(jonskeet): Get rid of most of this - move it into the runtime.
printer->Print("{\n");
printer->Indent();
printer->Print("int dataSize = 0;\n");
......@@ -207,10 +121,6 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
"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");
}
......@@ -218,15 +128,14 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(
void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
printer->Print(
variables_,
"foreach($type_name$ i in $name$_)\n"
" hash ^= i.GetHashCode();\n");
"foreach($type_name$ i in $name$_)\n {"
" hash ^= i.GetHashCode();\n"
"}\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_,
......
......@@ -41,17 +41,13 @@ namespace protobuf {
namespace compiler {
namespace csharp {
class Writer;
class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
public:
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
~RepeatedPrimitiveFieldGenerator();
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);
......
......@@ -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() {
......
......@@ -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);
};
......
......@@ -39,7 +39,6 @@
#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>
......@@ -61,18 +60,6 @@ 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++) {
......@@ -80,11 +67,7 @@ void UmbrellaClassGenerator::Generate(io::Printer* printer) {
messageGenerator.GenerateStaticVariables(printer);
}
printer->Print("#endregion\n");
if (!use_lite_runtime()) {
WriteDescriptor(printer);
} else {
WriteLiteExtensions(printer);
}
// Close the class declaration.
printer->Outdent();
printer->Print("}\n");
......@@ -134,9 +117,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 pbd = global::Google.Protobuf.Descriptors;\n"
"using scg = global::System.Collections.Generic;\n",
"file_name", file_->name());
......@@ -165,24 +148,6 @@ 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"
......@@ -219,25 +184,7 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) {
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");
......@@ -258,33 +205,6 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) {
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);
}
for (int i = 0; i < file_->extension_count(); i++) {
ExtensionGenerator extensionGenerator(file_->extension(i));
extensionGenerator.GenerateStaticVariableInitializers(printer);
}
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;
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
......
......@@ -41,8 +41,6 @@ namespace protobuf {
namespace compiler {
namespace csharp {
class Writer;
class UmbrellaClassGenerator : public SourceGeneratorBase {
public:
UmbrellaClassGenerator(const FileDescriptor* file);
......@@ -58,11 +56,7 @@ 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();
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UmbrellaClassGenerator);
};
......@@ -73,4 +67,3 @@ class UmbrellaClassGenerator : public SourceGeneratorBase {
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_UMBRELLA_CLASS_H__
// 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
// 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.
#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__
#define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_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);
void WriteLine();
void WriteLine(const char* text);
void WriteLine(const char* text, const string& value0);
void WriteLine(const char* text, const string& value0, const string& value1);
void WriteLine(const char* text, const string& value0, const string& value1,
const string& value2);
void WriteLine(const char* text, const string& value0, const string& value1,
const string& value2, const string& value3);
private:
io::Printer* printer_;
const char* newline_;
};
} // namespace csharp
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__
......@@ -169,7 +169,6 @@
<File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_enum.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_enum_field.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_extension.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_field_base.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_generator.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_helpers.h"></File>
......@@ -181,7 +180,6 @@
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_repeated_primitive_field.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_source_generator_base.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_umbrella_class.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_writer.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\java\java_context.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\java\java_enum.h"></File>
<File RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.h"></File>
......@@ -269,7 +267,6 @@
<File RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_enum.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_enum_field.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_extension.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_field_base.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_generator.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_helpers.cc"></File>
......@@ -281,7 +278,6 @@
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_repeated_primitive_field.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_source_generator_base.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_umbrella_class.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\csharp\csharp_writer.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\java\java_context.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.cc"></File>
<File RelativePath="..\src\google\protobuf\compiler\java\java_enum.cc"></File>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment