aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google
diff options
context:
space:
mode:
authorGravatar Jon Skeet <jonskeet@google.com>2015-06-23 16:09:27 +0100
committerGravatar Jon Skeet <jonskeet@google.com>2015-06-24 17:56:22 +0100
commitbfee2dfe137b07e64ebd46baf71d932d58d01b1f (patch)
tree4bf6258a990369335cc82c8a8059eaaf1dc2dd06 /src/google
parent94071b54d24d2f2f1cb5933a692b5397a047057c (diff)
Implement freezing for messages and repeated fields.
Fixes issue #523.
Diffstat (limited to 'src/google')
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_field_base.cc5
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_field_base.h1
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.cc36
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message.h1
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message_field.cc13
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_message_field.h1
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_primitive_field.cc15
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc5
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h1
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc5
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h1
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc5
-rw-r--r--src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h1
13 files changed, 82 insertions, 8 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index 54f281ee..0bfbc70e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -107,6 +107,11 @@ FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
FieldGeneratorBase::~FieldGeneratorBase() {
}
+void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) {
+ // No-op: only message fields and repeated fields need
+ // special handling for freezing, so default to not generating any code.
+}
+
void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
if (descriptor_->options().deprecated())
{
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h
index 91ae3ba1..abf9254b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h
@@ -48,6 +48,7 @@ class FieldGeneratorBase : public SourceGeneratorBase {
~FieldGeneratorBase();
virtual void GenerateCloningCode(io::Printer* printer) = 0;
+ virtual void GenerateFreezingCode(io::Printer* printer);
virtual void GenerateMembers(io::Printer* printer) = 0;
virtual void GenerateMergingCode(io::Printer* printer) = 0;
virtual void GenerateParsingCode(io::Printer* printer) = 0;
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index 39938fa3..9580c167 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -211,7 +211,9 @@ void MessageGenerator::Generate(io::Printer* printer) {
"public pb::FieldAccess.FieldAccessorTable<$class_name$> Fields {\n"
" get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n"
"}\n"
- "\n");
+ "\n"
+ "private bool _frozen = false;\n"
+ "public bool IsFrozen { get { return _frozen; } }\n\n");
// Parameterless constructor
printer->Print(
@@ -219,6 +221,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
"public $class_name$() { }\n\n");
GenerateCloningCode(printer);
+ GenerateFreezingCode(printer);
// Fields/properties
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -260,6 +263,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
" get { return $name$Case_; }\n"
"}\n\n"
"public void Clear$property_name$() {\n"
+ " pb::Freezable.CheckMutable(this);\n"
" $name$Case_ = $property_name$OneofCase.None;\n"
" $name$_ = null;\n"
"}\n\n");
@@ -346,6 +350,36 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
"}\n\n");
}
+void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
+ map<string, string> vars;
+ vars["class_name"] = class_name();
+ printer->Print(
+ "public void Freeze() {\n"
+ " if (IsFrozen) {\n"
+ " return;\n"
+ " }\n"
+ " _frozen = true;\n");
+ printer->Indent();
+ // Freeze non-oneof fields first (only messages and repeated fields will actually generate any code)
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ scoped_ptr<FieldGeneratorBase> generator(
+ CreateFieldGeneratorInternal(descriptor_->field(i)));
+ generator->GenerateFreezingCode(printer);
+ }
+ }
+
+ // For each oneof, if the value is freezable, freeze it. We don't actually need to know which type it was.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+ vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
+ printer->Print(vars,
+ "if ($name$_ is IFreezable) ((IFreezable) $name$_).Freeze();\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
map<string, string> vars;
vars["class_name"] = class_name();
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h
index c3a37a0e..6c7153aa 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message.h
@@ -51,6 +51,7 @@ class MessageGenerator : public SourceGeneratorBase {
~MessageGenerator();
void GenerateCloningCode(io::Printer* printer);
+ void GenerateFreezingCode(io::Printer* printer);
void GenerateFrameworkMethods(io::Printer* printer);
void GenerateStaticVariables(io::Printer* printer);
void GenerateStaticVariableInitializers(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
index 82deef54..cbf182d2 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -66,7 +66,10 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) {
variables_,
"public $type_name$ $property_name$ {\n"
" get { return $name$_; }\n"
- " set { $name$_ = value; }\n"
+ " set {\n"
+ " pb::Freezable.CheckMutable(this);\n"
+ " $name$_ = value;\n"
+ " }\n"
"}\n");
}
@@ -116,7 +119,7 @@ void MessageFieldGenerator::WriteHash(io::Printer* printer) {
void MessageFieldGenerator::WriteEquals(io::Printer* printer) {
printer->Print(
variables_,
- "if (!object.Equals($property_name$, other.$property_name$)) return false;");
+ "if (!object.Equals($property_name$, other.$property_name$)) return false;\n");
}
void MessageFieldGenerator::WriteToString(io::Printer* printer) {
variables_["field_name"] = GetFieldName(descriptor_);
@@ -130,6 +133,11 @@ void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
"$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n");
}
+void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "if ($has_property_check$) $property_name$.Freeze();\n");
+}
+
MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
int fieldOrdinal)
: MessageFieldGenerator(descriptor, fieldOrdinal) {
@@ -147,6 +155,7 @@ void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
"public $type_name$ $property_name$ {\n"
" get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n"
" set {\n"
+ " pb::Freezable.CheckMutable(this);\n"
" $oneof_name$_ = value;\n"
" $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
" }\n"
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h
index f15e8e7e..3e17f92a 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h
@@ -47,6 +47,7 @@ class MessageFieldGenerator : public FieldGeneratorBase {
~MessageFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateFreezingCode(io::Printer* printer);
virtual void GenerateMembers(io::Printer* printer);
virtual void GenerateMergingCode(io::Printer* printer);
virtual void GenerateParsingCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index c426c37a..d5542f57 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -72,17 +72,21 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
printer->Print(
variables_,
"public $type_name$ $property_name$ {\n"
- " get { return $name$_; }\n");
+ " get { return $name$_; }\n"
+ " set {\n"
+ " pb::Freezable.CheckMutable(this);\n");
if (is_value_type) {
printer->Print(
variables_,
- " set { $name$_ = value; }\n");
+ " $name$_ = value;\n");
} else {
printer->Print(
variables_,
- " set { $name$_ = value ?? $default_value$; }\n");
+ " $name$_ = value ?? $default_value$;\n");
}
- printer->Print("}\n\n");
+ printer->Print(
+ " }\n"
+ "}\n");
}
void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@@ -166,7 +170,8 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
variables_,
"public $type_name$ $property_name$ {\n"
" get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
- " set {\n");
+ " set {\n"
+ " pb::Freezable.CheckMutable(this);\n");
if (is_value_type) {
printer->Print(
variables_,
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 ce526b37..d223273c 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -147,6 +147,11 @@ void RepeatedEnumFieldGenerator::GenerateCloningCode(io::Printer* printer) {
"$name$_ = other.$name$_.Clone();\n");
}
+void RepeatedEnumFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_.Freeze();\n");
+}
+
} // namespace csharp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
index c7846a61..ee50eef0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
@@ -49,6 +49,7 @@ class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
~RepeatedEnumFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateFreezingCode(io::Printer* printer);
virtual void GenerateMembers(io::Printer* printer);
virtual void GenerateMergingCode(io::Printer* printer);
virtual void GenerateParsingCode(io::Printer* printer);
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 edfb98b4..400f0e4f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -123,6 +123,11 @@ void RepeatedMessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
"$name$_ = other.$name$_.Clone();\n");
}
+void RepeatedMessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_.Freeze();\n");
+}
+
} // namespace csharp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
index 38006731..cf601c7e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
@@ -47,6 +47,7 @@ class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
~RepeatedMessageFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateFreezingCode(io::Printer* printer);
virtual void GenerateMembers(io::Printer* printer);
virtual void GenerateMergingCode(io::Printer* printer);
virtual void GenerateParsingCode(io::Printer* printer);
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 49a29c55..a78a74c0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -153,6 +153,11 @@ void RepeatedPrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer)
"$name$_ = other.$name$_.Clone();\n");
}
+void RepeatedPrimitiveFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+ printer->Print(variables_,
+ "$name$_.Freeze();\n");
+}
+
} // namespace csharp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
index 7f8f17a8..f1ceeb50 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
@@ -47,6 +47,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
~RepeatedPrimitiveFieldGenerator();
virtual void GenerateCloningCode(io::Printer* printer);
+ virtual void GenerateFreezingCode(io::Printer* printer);
virtual void GenerateMembers(io::Printer* printer);
virtual void GenerateMergingCode(io::Printer* printer);
virtual void GenerateParsingCode(io::Printer* printer);