aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSydney Acksman <ObsidianMinor@users.noreply.github.com>2018-09-24 15:42:24 -0500
committerJie Luo <anandolee@gmail.com>2018-09-24 13:42:24 -0700
commit54176b26a9be6c9903b375596b778f51f5947921 (patch)
treea441d2831ecdb3db5e1f867b8fabc94ed523de13 /src
parentfb0a74b66076d6c55022a9bccabf6cdb08dbab83 (diff)
downloadprotobuf-54176b26a9be6c9903b375596b778f51f5947921.tar.gz
protobuf-54176b26a9be6c9903b375596b778f51f5947921.tar.bz2
protobuf-54176b26a9be6c9903b375596b778f51f5947921.zip
C# Proto2 feature : Field presence and default values (#4642)
* Compiler changes * Generated code changes * Library changes * Compiler style changes * Generated style changes * Fix Windows build errors * Implement changes from review * Reintroduce proto2 check * Compiler changes (required handling review) * Generated code changes (required handling review) * Library changes (required handling review * Field presence rewrite (compiler changes) * Field presence rewrite (generated code changes) * Compiler comment * IFieldAccessor.HasValue library implementation * Remove Clear methods and default values from proto3 code (Compiler) * Remove Clear methods and default values from proto3 code (Generated) * Remove Clear methods and default values from proto3 code (Library) * Fix distcheck error * Rewrite default string values to use base64 and convert * Library changes (IMessage2) * Compiler changes (IMessage2) * Generated changes (IMessage2) * Rebased and regenerated * Compiler changes (initialized extension) * Generated changes (initialized extension) * Library changes (initialized extension) * Refactor MessageExtensions.IsRequired * Move string default value creator and bytes default value creator back to seperate methods * Dead code cleanup * Fixed segmentation fault Removed unused header method declarations
Diffstat (limited to 'src')
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum_field.cc10
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_enum_field.h4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_field_base.cc105
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_field_base.h9
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_generator.cc6
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_helpers.cc61
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_helpers.h8
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_map_field.cc4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_map_field.h2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.cc58
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.h7
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message_field.cc66
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message_field.h4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_primitive_field.cc120
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_primitive_field.h4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc8
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc4
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h2
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc52
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_wrapper_field.h4
23 files changed, 384 insertions, 162 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
index 9ceffa8c..df599614 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
@@ -47,8 +47,8 @@ namespace compiler {
namespace csharp {
EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal, const Options *options)
- : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
+ int presenceIndex, const Options *options)
+ : PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
}
EnumFieldGenerator::~EnumFieldGenerator() {
@@ -56,7 +56,7 @@ EnumFieldGenerator::~EnumFieldGenerator() {
void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(variables_,
- "$name$_ = ($type_name$) input.ReadEnum();\n");
+ "$property_name$ = ($type_name$) input.ReadEnum();\n");
}
void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
@@ -82,8 +82,8 @@ void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) {
}
EnumOneofFieldGenerator::EnumOneofFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
- : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options) {
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options) {
}
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
index 631632bc..bfb9bc81 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
@@ -44,7 +44,7 @@ namespace csharp {
class EnumFieldGenerator : public PrimitiveFieldGenerator {
public:
EnumFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options);
~EnumFieldGenerator();
@@ -60,7 +60,7 @@ class EnumFieldGenerator : public PrimitiveFieldGenerator {
class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
public:
EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options);
~EnumOneofFieldGenerator();
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index 7e737e47..f8808264 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -57,6 +57,9 @@ void FieldGeneratorBase::SetCommonFieldVariables(
// repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
// never effects the tag size.
int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
+ if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ tag_size /= 2;
+ }
uint tag = internal::WireFormat::MakeTag(descriptor_);
uint8 tag_array[5];
io::CodedOutputStream::WriteTagToArray(tag, tag_array);
@@ -75,34 +78,52 @@ void FieldGeneratorBase::SetCommonFieldVariables(
(*variables)["name"] = name();
(*variables)["descriptor_name"] = descriptor_->name();
(*variables)["default_value"] = default_value();
- if (has_default_value()) {
+ (*variables)["capitalized_type_name"] = capitalized_type_name();
+ (*variables)["number"] = number();
+ if (has_default_value() && !IsProto2(descriptor_->file())) {
(*variables)["name_def_message"] =
(*variables)["name"] + "_ = " + (*variables)["default_value"];
} else {
(*variables)["name_def_message"] = (*variables)["name"] + "_";
}
- (*variables)["capitalized_type_name"] = capitalized_type_name();
- (*variables)["number"] = number();
- (*variables)["has_property_check"] =
- (*variables)["property_name"] + " != " + (*variables)["default_value"];
- (*variables)["other_has_property_check"] = "other." +
- (*variables)["property_name"] + " != " + (*variables)["default_value"];
+ if (IsProto2(descriptor_->file())) {
+ (*variables)["has_property_check"] = "Has" + (*variables)["property_name"];
+ (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"];
+ (*variables)["has_not_property_check"] = "!" + (*variables)["has_property_check"];
+ (*variables)["other_has_not_property_check"] = "!" + (*variables)["other_has_property_check"];
+ if (presenceIndex_ != -1) {
+ string hasBitsNumber = SimpleItoa(presenceIndex_ / 32);
+ string hasBitsMask = SimpleItoa(1 << (presenceIndex_ % 32));
+ (*variables)["has_field_check"] = "(_hasBits" + hasBitsNumber + " & " + hasBitsMask + ") != 0";
+ (*variables)["set_has_field"] = "_hasBits" + hasBitsNumber + " |= " + hasBitsMask;
+ (*variables)["clear_has_field"] = "_hasBits" + hasBitsNumber + " &= ~" + hasBitsMask;
+ }
+ } else {
+ (*variables)["has_property_check"] =
+ (*variables)["property_name"] + " != " + (*variables)["default_value"];
+ (*variables)["other_has_property_check"] = "other." +
+ (*variables)["property_name"] + " != " + (*variables)["default_value"];
+ }
}
void FieldGeneratorBase::SetCommonOneofFieldVariables(
std::map<string, string>* variables) {
(*variables)["oneof_name"] = oneof_name();
- (*variables)["has_property_check"] =
- oneof_name() + "Case_ == " + oneof_property_name() +
- "OneofCase." + property_name();
+ if (IsProto2(descriptor_->file())) {
+ (*variables)["has_property_check"] = "Has" + property_name();
+ } else {
+ (*variables)["has_property_check"] =
+ oneof_name() + "Case_ == " + oneof_property_name() +
+ "OneofCase." + property_name();
+ }
(*variables)["oneof_property_name"] = oneof_property_name();
}
FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
- int fieldOrdinal, const Options* options)
+ int presenceIndex, const Options* options)
: SourceGeneratorBase(descriptor->file(), options),
descriptor_(descriptor),
- fieldOrdinal_(fieldOrdinal) {
+ presenceIndex_(presenceIndex) {
SetCommonFieldVariables(&variables_);
}
@@ -251,36 +272,6 @@ bool FieldGeneratorBase::has_default_value() {
}
}
-bool FieldGeneratorBase::is_nullable_type() {
- switch (descriptor_->type()) {
- case FieldDescriptor::TYPE_ENUM:
- case FieldDescriptor::TYPE_DOUBLE:
- case FieldDescriptor::TYPE_FLOAT:
- case FieldDescriptor::TYPE_INT64:
- case FieldDescriptor::TYPE_UINT64:
- case FieldDescriptor::TYPE_INT32:
- case FieldDescriptor::TYPE_FIXED64:
- case FieldDescriptor::TYPE_FIXED32:
- case FieldDescriptor::TYPE_BOOL:
- case FieldDescriptor::TYPE_UINT32:
- case FieldDescriptor::TYPE_SFIXED32:
- case FieldDescriptor::TYPE_SFIXED64:
- case FieldDescriptor::TYPE_SINT32:
- case FieldDescriptor::TYPE_SINT64:
- return false;
-
- case FieldDescriptor::TYPE_MESSAGE:
- case FieldDescriptor::TYPE_GROUP:
- case FieldDescriptor::TYPE_STRING:
- case FieldDescriptor::TYPE_BYTES:
- return true;
-
- default:
- GOOGLE_LOG(FATAL)<< "Unknown field type.";
- return true;
- }
-}
-
bool AllPrintableAscii(const std::string& text) {
for(int i = 0; i < text.size(); i++) {
if (text[i] < 0x20 || text[i] > 0x7e) {
@@ -290,14 +281,18 @@ bool AllPrintableAscii(const std::string& text) {
return true;
}
-std::string FieldGeneratorBase::GetStringDefaultValueInternal() {
- // No other default values needed for proto3...
- return "\"\"";
+std::string FieldGeneratorBase::GetStringDefaultValueInternal(const FieldDescriptor* descriptor) {
+ if (descriptor->default_value_string().empty())
+ return "\"\"";
+ else
+ return "global::System.Encoding.UTF8.GetString(global::System.Convert.FromBase64String(\" +" + StringToBase64(descriptor->default_value_string()) + " +\"))";
}
-std::string FieldGeneratorBase::GetBytesDefaultValueInternal() {
- // No other default values needed for proto3...
- return "pb::ByteString.Empty";
+std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) {
+ if (descriptor->default_value_string().empty())
+ return "pb::ByteString.Empty";
+ else
+ return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor->default_value_string()) + "\")";
}
std::string FieldGeneratorBase::default_value() {
@@ -307,9 +302,13 @@ std::string FieldGeneratorBase::default_value() {
std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_ENUM:
- // All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to
- // any C# enum. This means we don't need to work out what we actually mapped the enum value name to.
- return "0";
+ if (IsProto2(descriptor_->file())) {
+ return GetClassName(descriptor->default_value_enum()->type()) + "." +
+ GetEnumValueName(descriptor->default_value_enum()->type()->name(), descriptor->default_value_enum()->name());
+ }
+ else {
+ return "0";
+ }
case FieldDescriptor::TYPE_MESSAGE:
case FieldDescriptor::TYPE_GROUP:
if (IsWrapperType(descriptor)) {
@@ -357,9 +356,9 @@ std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor)
return "false";
}
case FieldDescriptor::TYPE_STRING:
- return GetStringDefaultValueInternal();
+ return GetStringDefaultValueInternal(descriptor);
case FieldDescriptor::TYPE_BYTES:
- return GetBytesDefaultValueInternal();
+ return GetBytesDefaultValueInternal(descriptor);
case FieldDescriptor::TYPE_UINT32:
return SimpleItoa(descriptor->default_value_uint32());
case FieldDescriptor::TYPE_SFIXED32:
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h
index 62c25517..7eee6bf1 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h
@@ -47,7 +47,7 @@ namespace csharp {
class FieldGeneratorBase : public SourceGeneratorBase {
public:
FieldGeneratorBase(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options* options);
~FieldGeneratorBase();
@@ -67,7 +67,7 @@ class FieldGeneratorBase : public SourceGeneratorBase {
protected:
const FieldDescriptor* descriptor_;
- const int fieldOrdinal_;
+ const int presenceIndex_;
std::map<string, string> variables_;
void AddDeprecatedFlag(io::Printer* printer);
@@ -84,7 +84,6 @@ class FieldGeneratorBase : public SourceGeneratorBase {
std::string type_name();
std::string type_name(const FieldDescriptor* descriptor);
bool has_default_value();
- bool is_nullable_type();
std::string default_value();
std::string default_value(const FieldDescriptor* descriptor);
std::string number();
@@ -92,8 +91,8 @@ class FieldGeneratorBase : public SourceGeneratorBase {
private:
void SetCommonFieldVariables(std::map<string, string>* variables);
- std::string GetStringDefaultValueInternal();
- std::string GetBytesDefaultValueInternal();
+ std::string GetStringDefaultValueInternal(const FieldDescriptor* descriptor);
+ std::string GetBytesDefaultValueInternal(const FieldDescriptor* descriptor);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorBase);
};
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
index 0c93fc29..c0597fe4 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -65,11 +65,11 @@ bool Generator::Generate(
std::vector<std::pair<string, string> > options;
ParseGeneratorParameter(parameter, &options);
- // We only support proto3 - but we make an exception for descriptor.proto.
+ // We only support proto3 - but we make an exception for descriptor.proto.
if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) {
- *error = "C# code generation only supports proto3 syntax";
+ *error = "C# code generation only supports proto3 syntax";
return false;
- }
+ }
struct Options cli_options;
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
index 04b61074..dace4100 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -36,6 +36,7 @@
#include <google/protobuf/stubs/hash.h>
#include <limits>
#include <vector>
+#include <sstream>
#include <google/protobuf/compiler/csharp/csharp_helpers.h>
#include <google/protobuf/compiler/csharp/csharp_names.h>
@@ -452,55 +453,89 @@ std::string FileDescriptorToBase64(const FileDescriptor* descriptor) {
}
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options* options) {
switch (descriptor->type()) {
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
if (descriptor->is_repeated()) {
if (descriptor->is_map()) {
- return new MapFieldGenerator(descriptor, fieldOrdinal, options);
+ return new MapFieldGenerator(descriptor, presenceIndex, options);
} else {
- return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal, options);
+ return new RepeatedMessageFieldGenerator(descriptor, presenceIndex, options);
}
} else {
if (IsWrapperType(descriptor)) {
if (descriptor->containing_oneof()) {
- return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal, options);
+ return new WrapperOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
- return new WrapperFieldGenerator(descriptor, fieldOrdinal, options);
+ return new WrapperFieldGenerator(descriptor, presenceIndex, options);
}
} else {
if (descriptor->containing_oneof()) {
- return new MessageOneofFieldGenerator(descriptor, fieldOrdinal, options);
+ return new MessageOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
- return new MessageFieldGenerator(descriptor, fieldOrdinal, options);
+ return new MessageFieldGenerator(descriptor, presenceIndex, options);
}
}
}
case FieldDescriptor::TYPE_ENUM:
if (descriptor->is_repeated()) {
- return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal, options);
+ return new RepeatedEnumFieldGenerator(descriptor, presenceIndex, options);
} else {
if (descriptor->containing_oneof()) {
- return new EnumOneofFieldGenerator(descriptor, fieldOrdinal, options);
+ return new EnumOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
- return new EnumFieldGenerator(descriptor, fieldOrdinal, options);
+ return new EnumFieldGenerator(descriptor, presenceIndex, options);
}
}
default:
if (descriptor->is_repeated()) {
- return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
+ return new RepeatedPrimitiveFieldGenerator(descriptor, presenceIndex, options);
} else {
if (descriptor->containing_oneof()) {
- return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options);
+ return new PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options);
} else {
- return new PrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
+ return new PrimitiveFieldGenerator(descriptor, presenceIndex, options);
}
}
}
}
+bool IsNullable(const FieldDescriptor* descriptor) {
+ if (descriptor->is_repeated()) {
+ return true;
+ }
+
+ switch (descriptor->type()) {
+ case FieldDescriptor::TYPE_ENUM:
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_FLOAT:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_BOOL:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_SFIXED64:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_SINT64:
+ return false;
+
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES:
+ return true;
+
+ default:
+ GOOGLE_LOG(FATAL) << "Unknown field type.";
+ return true;
+ }
+}
+
} // namespace csharp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
index ec0b1c77..5b9f90e0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -107,9 +107,11 @@ std::string StringToBase64(const std::string& input);
std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options* options);
+bool IsNullable(const FieldDescriptor* descriptor);
+
// Determines whether the given message is a map entry message,
// i.e. one implicitly created by protoc due to a map<key, value> field.
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
@@ -144,6 +146,10 @@ inline bool IsWrapperType(const FieldDescriptor* descriptor) {
descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
}
+inline bool IsProto2(const FileDescriptor* descriptor) {
+ return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
+}
+
} // namespace csharp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
index d58514ce..125bdf1d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -48,9 +48,9 @@ namespace compiler {
namespace csharp {
MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options* options)
- : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
}
MapFieldGenerator::~MapFieldGenerator() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h
index 84a33a03..91c99bd0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h
@@ -44,7 +44,7 @@ namespace csharp {
class MapFieldGenerator : public FieldGeneratorBase {
public:
MapFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options* options);
~MapFieldGenerator();
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index 8a4307f1..1daae6f5 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -61,20 +61,27 @@ bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
const Options* options)
: SourceGeneratorBase(descriptor->file(), options),
- descriptor_(descriptor) {
-
- // sorted field names
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_names_.push_back(descriptor_->field(i)->name());
- }
- std::sort(field_names_.begin(), field_names_.end());
-
+ descriptor_(descriptor),
+ has_bit_field_count_(0) {
// fields by number
for (int i = 0; i < descriptor_->field_count(); i++) {
fields_by_number_.push_back(descriptor_->field(i));
}
std::sort(fields_by_number_.begin(), fields_by_number_.end(),
CompareFieldNumbers);
+
+ if (IsProto2(descriptor_->file())) {
+ int primitiveCount = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (!IsNullable(field)) {
+ primitiveCount++;
+ if (has_bit_field_count_ == 0 || (primitiveCount % 32) == 0) {
+ has_bit_field_count_++;
+ }
+ }
+ }
+ }
}
MessageGenerator::~MessageGenerator() {
@@ -88,10 +95,6 @@ std::string MessageGenerator::full_class_name() {
return GetClassName(descriptor_);
}
-const std::vector<std::string>& MessageGenerator::field_names() {
- return field_names_;
-}
-
const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
return fields_by_number_;
}
@@ -123,6 +126,12 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Print(
"private pb::UnknownFieldSet _unknownFields;\n");
+ for (int i = 0; i < has_bit_field_count_; i++) {
+ // don't use arrays since all arrays are heap allocated, saving allocations
+ // use ints instead of bytes since bytes lack bitwise operators, saving casts
+ printer->Print("private int _hasBits$i$;\n", "i", SimpleItoa(i));
+ }
+
WriteGeneratedCodeAttributes(printer);
printer->Print(
@@ -288,6 +297,9 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
vars,
"public $class_name$($class_name$ other) : this() {\n");
printer->Indent();
+ for (int i = 0; i < has_bit_field_count_; i++) {
+ printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", SimpleItoa(i));
+ }
// Clone non-oneof fields first
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->containing_oneof()) {
@@ -559,19 +571,29 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
printer->Print("}\n\n"); // method
}
-int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
- for (int i = 0; i < field_names().size(); i++) {
- if (field_names()[i] == descriptor->name()) {
- return i;
+// it's a waste of space to track presence for all values, so we only track them if they're not nullable
+int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) {
+ if (IsNullable(descriptor) || !IsProto2(descriptor_->file())) {
+ return -1;
+ }
+
+ int index = 0;
+ for (int i = 0; i < fields_by_number().size(); i++) {
+ const FieldDescriptor* field = fields_by_number()[i];
+ if (field == descriptor) {
+ return index;
+ }
+ if (!IsNullable(field)) {
+ index++;
}
}
- GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name();
+ GOOGLE_LOG(DFATAL)<< "Could not find presence index for field " << descriptor->name();
return -1;
}
FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
const FieldDescriptor* descriptor) {
- return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options());
+ return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), this->options());
}
} // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h
index e7f3b4d0..b20bec3d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message.h
@@ -57,13 +57,13 @@ class MessageGenerator : public SourceGeneratorBase {
private:
const Descriptor* descriptor_;
- std::vector<std::string> field_names_;
std::vector<const FieldDescriptor*> fields_by_number_;
+ int has_bit_field_count_;
void GenerateMessageSerializationMethods(io::Printer* printer);
void GenerateMergingMethods(io::Printer* printer);
- int GetFieldOrdinal(const FieldDescriptor* descriptor);
+ int GetPresenceIndex(const FieldDescriptor* descriptor);
FieldGeneratorBase* CreateFieldGeneratorInternal(
const FieldDescriptor* descriptor);
@@ -74,9 +74,6 @@ class MessageGenerator : public SourceGeneratorBase {
std::string class_name();
std::string full_class_name();
- // field names sorted alphabetically
- const std::vector<std::string>& field_names();
-
// field descriptors sorted by number
const std::vector<const FieldDescriptor*>& fields_by_number();
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
index cf1b4dbf..16714603 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -49,11 +49,13 @@ namespace compiler {
namespace csharp {
MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options)
- : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
- variables_["has_property_check"] = name() + "_ != null";
- variables_["has_not_property_check"] = name() + "_ == null";
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
+ if (!IsProto2(descriptor_->file())) {
+ variables_["has_property_check"] = name() + "_ != null";
+ variables_["has_not_property_check"] = name() + "_ == null";
+ }
}
MessageFieldGenerator::~MessageFieldGenerator() {
@@ -74,6 +76,26 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
" $name$_ = value;\n"
" }\n"
"}\n");
+ if (IsProto2(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return $name$_ != null; }\n"
+ "}\n");
+ printer->Print(
+ variables_,
+ "/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n"
+ " $name$_ = null;\n"
+ "}\n");
+ }
}
void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@@ -81,7 +103,7 @@ void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
variables_,
"if (other.$has_property_check$) {\n"
" if ($has_not_property_check$) {\n"
- " $name$_ = new $type_name$();\n"
+ " $property_name$ = new $type_name$();\n"
" }\n"
" $property_name$.MergeFrom(other.$property_name$);\n"
"}\n");
@@ -91,10 +113,9 @@ void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) {
printer->Print(
variables_,
"if ($has_not_property_check$) {\n"
- " $name$_ = new $type_name$();\n"
+ " $property_name$ = new $type_name$();\n"
"}\n"
- // TODO(jonskeet): Do we really need merging behaviour like this?
- "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP...
+ "input.ReadMessage($property_name$);\n");
}
void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
@@ -130,7 +151,6 @@ void MessageFieldGenerator::WriteToString(io::Printer* printer) {
variables_,
"PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
}
-
void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
printer->Print(variables_,
"$name$_ = other.$has_property_check$ ? other.$name$_.Clone() : null;\n");
@@ -147,9 +167,9 @@ void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
MessageOneofFieldGenerator::MessageOneofFieldGenerator(
const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options)
- : MessageFieldGenerator(descriptor, fieldOrdinal, options) {
+ : MessageFieldGenerator(descriptor, presenceIndex, options) {
SetCommonOneofFieldVariables(&variables_);
}
@@ -169,6 +189,28 @@ void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
" $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
" }\n"
"}\n");
+ if (IsProto2(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
+ "}\n");
+ printer->Print(
+ variables_,
+ "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n"
+ " if ($has_property_check$) {\n"
+ " Clear$oneof_property_name$();\n"
+ " }\n"
+ "}\n");
+ }
}
void MessageOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@@ -187,7 +229,7 @@ void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
"if ($has_property_check$) {\n"
" subBuilder.MergeFrom($property_name$);\n"
"}\n"
- "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP
+ "input.ReadMessage(subBuilder);\n"
"$property_name$ = subBuilder;\n");
}
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h
index c41ee88a..104fb027 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h
@@ -44,7 +44,7 @@ namespace csharp {
class MessageFieldGenerator : public FieldGeneratorBase {
public:
MessageFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options);
~MessageFieldGenerator();
@@ -68,7 +68,7 @@ class MessageFieldGenerator : public FieldGeneratorBase {
class MessageOneofFieldGenerator : public MessageFieldGenerator {
public:
MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options);
~MessageOneofFieldGenerator();
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index c3003e3d..b83468d3 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -49,12 +49,12 @@ namespace compiler {
namespace csharp {
PrimitiveFieldGenerator::PrimitiveFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
- : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
// TODO(jonskeet): Make this cleaner...
is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
&& descriptor->type() != FieldDescriptor::TYPE_BYTES;
- if (!is_value_type) {
+ if (!is_value_type && !IsProto2(descriptor_->file())) {
variables_["has_property_check"] = variables_["property_name"] + ".Length != 0";
variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0";
}
@@ -67,16 +67,44 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
// 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?)
+ if (IsProto2(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "private readonly static $type_name$ $property_name$DefaultValue = $default_value$;\n\n");
+ }
+
printer->Print(
variables_,
"private $type_name$ $name_def_message$;\n");
+
WritePropertyDocComment(printer, descriptor_);
AddPublicMemberAttributes(printer);
- printer->Print(
- variables_,
- "$access_level$ $type_name$ $property_name$ {\n"
- " get { return $name$_; }\n"
- " set {\n");
+ if (IsProto2(descriptor_->file())) {
+ if (presenceIndex_ == -1) {
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $name$_ ?? $property_name$DefaultValue; }\n"
+ " set {\n");
+ } else {
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { if ($has_field_check$) { return $name$_; } else { return $property_name$DefaultValue; } }\n"
+ " set {\n");
+ }
+ } else {
+ printer->Print(
+ variables_,
+ "$access_level$ $type_name$ $property_name$ {\n"
+ " get { return $name$_; }\n"
+ " set {\n");
+ }
+ if (presenceIndex_ != -1) {
+ printer->Print(
+ variables_,
+ " $set_has_field$;\n");
+ }
if (is_value_type) {
printer->Print(
variables_,
@@ -89,6 +117,36 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
" }\n"
"}\n");
+ if (IsProto2(descriptor_->file())) {
+ printer->Print(variables_, "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return ");
+ if (IsNullable(descriptor_)) {
+ printer->Print(
+ variables_,
+ "$name$_ != null; }\n}\n");
+ } else {
+ printer->Print(
+ variables_,
+ "$has_field_check$; }\n}\n");
+ }
+ }
+ if (IsProto2(descriptor_->file())) {
+ printer->Print(variables_, "/// <summary>Clears the value of the \"$descriptor_name$\" field</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n");
+ if (IsNullable(descriptor_)) {
+ printer->Print(variables_, " $name$_ = null;\n");
+ } else {
+ printer->Print(variables_, " $clear_has_field$;\n");
+ }
+ printer->Print("}\n");
+ }
}
void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@@ -172,8 +230,8 @@ void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) {
}
PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
- : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
SetCommonOneofFieldVariables(&variables_);
}
@@ -188,20 +246,42 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
"$access_level$ $type_name$ $property_name$ {\n"
" get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
" set {\n");
- if (is_value_type) {
- printer->Print(
- variables_,
- " $oneof_name$_ = value;\n");
- } else {
- printer->Print(
- variables_,
- " $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
- }
+ if (is_value_type) {
printer->Print(
variables_,
- " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
+ " $oneof_name$_ = value;\n");
+ } else {
+ printer->Print(
+ variables_,
+ " $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
+ }
+ printer->Print(
+ variables_,
+ " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
+ " }\n"
+ "}\n");
+ if (IsProto2(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
+ "}\n");
+ printer->Print(
+ variables_,
+ "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n"
+ " if ($has_property_check$) {\n"
+ " Clear$oneof_property_name$();\n"
" }\n"
"}\n");
+ }
}
void PrimitiveOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
index ca7b8b3d..010ceb21 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
@@ -46,7 +46,7 @@ struct Options;
class PrimitiveFieldGenerator : public FieldGeneratorBase {
public:
PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options);
~PrimitiveFieldGenerator();
@@ -72,7 +72,7 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase {
class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
public:
PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options);
~PrimitiveOneofFieldGenerator();
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
index 683c4b0b..a69e97b2 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -48,8 +48,8 @@ namespace compiler {
namespace csharp {
RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
- : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
index 819b5832..58252225 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
@@ -46,7 +46,7 @@ namespace csharp {
class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
public:
RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options);
~RepeatedEnumFieldGenerator();
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
index 90af569c..d4216597 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -49,8 +49,8 @@ namespace compiler {
namespace csharp {
RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
- : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
}
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
@@ -67,11 +67,11 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) {
// function, but it doesn't seem worth it for just this.
if (IsWrapperType(descriptor_)) {
std::unique_ptr<FieldGeneratorBase> single_generator(
- new WrapperFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
+ new WrapperFieldGenerator(descriptor_, presenceIndex_, this->options()));
single_generator->GenerateCodecCode(printer);
} else {
std::unique_ptr<FieldGeneratorBase> single_generator(
- new MessageFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
+ new MessageFieldGenerator(descriptor_, presenceIndex_, this->options()));
single_generator->GenerateCodecCode(printer);
}
printer->Print(";\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
index 6e33648b..ebc760fa 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
@@ -46,7 +46,7 @@ struct Options;
class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
public:
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options);
~RepeatedMessageFieldGenerator();
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
index cd91506f..bc25627f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -48,8 +48,8 @@ namespace compiler {
namespace csharp {
RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
- : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
}
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
index a59348a9..340688eb 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
@@ -43,7 +43,7 @@ namespace csharp {
class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
public:
- RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options);
+ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int presenceIndex, const Options *options);
~RepeatedPrimitiveFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
index 047edf73..1dcbf97b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
@@ -48,8 +48,8 @@ namespace compiler {
namespace csharp {
WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal, const Options *options)
- : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+ int presenceIndex, const Options *options)
+ : FieldGeneratorBase(descriptor, presenceIndex, options) {
variables_["has_property_check"] = name() + "_ != null";
variables_["has_not_property_check"] = name() + "_ == null";
const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
@@ -81,7 +81,27 @@ void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) {
" set {\n"
" $name$_ = value;\n"
" }\n"
- "}\n");
+ "}\n\n");
+ if (IsProto2(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return $name$_ != null; }\n"
+ "}\n\n");
+ printer->Print(
+ variables_,
+ "/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n"
+ " $name$_ = null;\n"
+ "}\n");
+ }
}
void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@@ -163,8 +183,8 @@ void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) {
}
WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(
- const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
- : WrapperFieldGenerator(descriptor, fieldOrdinal, options) {
+ const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+ : WrapperFieldGenerator(descriptor, presenceIndex, options) {
SetCommonOneofFieldVariables(&variables_);
}
@@ -189,6 +209,28 @@ void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
" $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
" }\n"
"}\n");
+ if (IsProto2(descriptor_->file())) {
+ printer->Print(
+ variables_,
+ "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ bool Has$property_name$ {\n"
+ " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
+ "}\n");
+ printer->Print(
+ variables_,
+ "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
+ AddPublicMemberAttributes(printer);
+ printer->Print(
+ variables_,
+ "$access_level$ void Clear$property_name$() {\n"
+ " if ($has_property_check$) {\n"
+ " Clear$oneof_property_name$();\n"
+ " }\n"
+ "}\n");
+ }
}
void WrapperOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
index 452531fb..08cae548 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
@@ -46,7 +46,7 @@ struct Options;
class WrapperFieldGenerator : public FieldGeneratorBase {
public:
WrapperFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options);
~WrapperFieldGenerator();
@@ -70,7 +70,7 @@ class WrapperFieldGenerator : public FieldGeneratorBase {
class WrapperOneofFieldGenerator : public WrapperFieldGenerator {
public:
WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
- int fieldOrdinal,
+ int presenceIndex,
const Options *options);
~WrapperOneofFieldGenerator();