Commit 541b442b authored by Jon Skeet's avatar Jon Skeet

Don't create nested types (or field accessors) for map types.

I'm sure I've implemented this before, but somehow it's been lost in a maze of twisty little branches, all alike.
parent f8281604
......@@ -16,7 +16,6 @@ namespace Google.Protobuf.WellKnownTypes {
#region Static variables
internal static pbr::FieldAccessorTable internal__static_google_protobuf_Struct__FieldAccessorTable;
internal static pbr::FieldAccessorTable internal__static_google_protobuf_Struct_FieldsEntry__FieldAccessorTable;
internal static pbr::FieldAccessorTable internal__static_google_protobuf_Value__FieldAccessorTable;
internal static pbr::FieldAccessorTable internal__static_google_protobuf_ListValue__FieldAccessorTable;
#endregion
......@@ -49,9 +48,6 @@ namespace Google.Protobuf.WellKnownTypes {
internal__static_google_protobuf_Struct__FieldAccessorTable =
new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Struct), descriptor.MessageTypes[0],
new string[] { "Fields", }, new string[] { });
internal__static_google_protobuf_Struct_FieldsEntry__FieldAccessorTable =
new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Struct.Types.FieldsEntry), descriptor.MessageTypes[0].NestedTypes[0],
new string[] { "Key", "Value", }, new string[] { });
internal__static_google_protobuf_Value__FieldAccessorTable =
new pbr::FieldAccessorTable(typeof(global::Google.Protobuf.WellKnownTypes.Value), descriptor.MessageTypes[1],
new string[] { "NullValue", "NumberValue", "StringValue", "BoolValue", "StructValue", "ListValue", }, new string[] { "Kind", });
......@@ -180,165 +176,6 @@ namespace Google.Protobuf.WellKnownTypes {
}
}
#region Nested types
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static partial class Types {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class FieldsEntry : pb::IMessage<FieldsEntry> {
private static readonly pb::MessageParser<FieldsEntry> _parser = new pb::MessageParser<FieldsEntry>(() => new FieldsEntry());
public static pb::MessageParser<FieldsEntry> Parser { get { return _parser; } }
private static readonly string[] _fieldNames = new string[] { "key", "value" };
private static readonly uint[] _fieldTags = new uint[] { 10, 18 };
public static pbr::MessageDescriptor Descriptor {
get { return global::Google.Protobuf.WellKnownTypes.Struct.Descriptor.NestedTypes[0]; }
}
pbr::FieldAccessorTable pb::IReflectedMessage.Fields {
get { return global::Google.Protobuf.WellKnownTypes.Proto.Struct.internal__static_google_protobuf_Struct_FieldsEntry__FieldAccessorTable; }
}
private bool _frozen = false;
public bool IsFrozen { get { return _frozen; } }
public FieldsEntry() {
OnConstruction();
}
partial void OnConstruction();
public FieldsEntry(FieldsEntry other) : this() {
key_ = other.key_;
Value = other.value_ != null ? other.Value.Clone() : null;
}
public FieldsEntry Clone() {
return new FieldsEntry(this);
}
public void Freeze() {
if (IsFrozen) {
return;
}
_frozen = true;
if (value_ != null) Value.Freeze();
}
public const int KeyFieldNumber = 1;
private string key_ = "";
public string Key {
get { return key_; }
set {
pb::Freezable.CheckMutable(this);
key_ = value ?? "";
}
}
public const int ValueFieldNumber = 2;
private global::Google.Protobuf.WellKnownTypes.Value value_;
public global::Google.Protobuf.WellKnownTypes.Value Value {
get { return value_; }
set {
pb::Freezable.CheckMutable(this);
value_ = value;
}
}
public override bool Equals(object other) {
return Equals(other as FieldsEntry);
}
public bool Equals(FieldsEntry other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Key != other.Key) return false;
if (!object.Equals(Value, other.Value)) return false;
return true;
}
public override int GetHashCode() {
int hash = 1;
if (Key.Length != 0) hash ^= Key.GetHashCode();
if (value_ != null) hash ^= Value.GetHashCode();
return hash;
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
}
public void WriteTo(pb::CodedOutputStream output) {
if (Key.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Key);
}
if (value_ != null) {
output.WriteRawTag(18);
output.WriteMessage(Value);
}
}
public int CalculateSize() {
int size = 0;
if (Key.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Key);
}
if (value_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value);
}
return size;
}
public void MergeFrom(FieldsEntry other) {
if (other == null) {
return;
}
if (other.Key.Length != 0) {
Key = other.Key;
}
if (other.value_ != null) {
if (value_ == null) {
value_ = new global::Google.Protobuf.WellKnownTypes.Value();
}
Value.MergeFrom(other.Value);
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while (input.ReadTag(out tag)) {
switch(tag) {
case 0:
throw pb::InvalidProtocolBufferException.InvalidTag();
default:
if (pb::WireFormat.IsEndGroupTag(tag)) {
return;
}
break;
case 10: {
Key = input.ReadString();
break;
}
case 18: {
if (value_ == null) {
value_ = new global::Google.Protobuf.WellKnownTypes.Value();
}
input.ReadMessage(value_);
break;
}
}
}
}
}
}
#endregion
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
......
......@@ -105,6 +105,12 @@ uint FixedMakeTag(const FieldDescriptor* descriptor);
FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
// Determines whether the given message is a map entry message, i.e. one implicitly created
// by protoc due to a map<key, value> field.
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
return descriptor->options().map_entry();
}
// Determines whether we're generating code for the proto representation of descriptors etc,
// for use in the runtime. This is the only type which is allowed to use proto2 syntax,
// and it generates internal classes.
......
......@@ -121,6 +121,9 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
"full_class_name", full_class_name());
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// Don't generate accessor table fields for maps...
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
MessageGenerator messageGenerator(descriptor_->nested_type(i));
messageGenerator.GenerateStaticVariables(printer);
}
......@@ -159,8 +162,10 @@ void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer)
}
printer->Print("});\n");
// Generate static member initializers for all nested types.
// Generate static member initializers for all non-map-entry nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
MessageGenerator messageGenerator(descriptor_->nested_type(i));
messageGenerator.GenerateStaticVariableInitializers(printer);
}
......@@ -285,7 +290,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
GenerateMergingMethods(printer);
// Nested messages and enums
if (descriptor_->enum_type_count() + descriptor_->nested_type_count() > 0) {
if (HasNestedGeneratedTypes()) {
printer->Print("#region Nested types\n"
"[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n");
WriteGeneratedCodeAttributes(printer);
......@@ -296,6 +301,9 @@ void MessageGenerator::Generate(io::Printer* printer) {
enumGenerator.Generate(printer);
}
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// Don't generate nested types for maps...
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
MessageGenerator messageGenerator(descriptor_->nested_type(i));
messageGenerator.Generate(printer);
}
......@@ -310,6 +318,21 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Print("\n");
}
// Helper to work out whether we need to generate a class to hold nested types/enums.
// Only tricky because we don't want to generate map entry types.
bool MessageGenerator::HasNestedGeneratedTypes()
{
if (descriptor_->enum_type_count() > 0) {
return true;
}
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
return true;
}
}
return false;
}
void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
map<string, string> vars;
vars["class_name"] = class_name();
......
......@@ -69,6 +69,8 @@ class MessageGenerator : public SourceGeneratorBase {
FieldGeneratorBase* CreateFieldGeneratorInternal(
const FieldDescriptor* descriptor);
bool HasNestedGeneratedTypes();
std::string class_name();
std::string full_class_name();
......
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