aboutsummaryrefslogtreecommitdiff
path: root/src/ProtoGen
diff options
context:
space:
mode:
authorcsharptest <roger@csharptest.net>2011-09-28 11:31:27 -0500
committerrogerk <devnull@localhost>2011-09-28 11:31:27 -0500
commit8c2b8d11de91ae7869d19a94e48e993e97455470 (patch)
treec6056349009e6b0f0c523835ada884522cb67ed8 /src/ProtoGen
parent7f20cc9084d929d2506ed9f2dccff09c51165d1f (diff)
parent3b625064e8e40f37ec510cc4f25035a9c1554c73 (diff)
downloadprotobuf-8c2b8d11de91ae7869d19a94e48e993e97455470.tar.gz
protobuf-8c2b8d11de91ae7869d19a94e48e993e97455470.tar.bz2
protobuf-8c2b8d11de91ae7869d19a94e48e993e97455470.zip
merged issue-22
Diffstat (limited to 'src/ProtoGen')
-rw-r--r--src/ProtoGen/EnumFieldGenerator.cs2
-rw-r--r--src/ProtoGen/MessageFieldGenerator.cs4
-rw-r--r--src/ProtoGen/MessageGenerator.cs55
-rw-r--r--src/ProtoGen/PrimitiveFieldGenerator.cs2
-rw-r--r--src/ProtoGen/RepeatedEnumFieldGenerator.cs6
-rw-r--r--src/ProtoGen/RepeatedMessageFieldGenerator.cs8
-rw-r--r--src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs6
7 files changed, 68 insertions, 15 deletions
diff --git a/src/ProtoGen/EnumFieldGenerator.cs b/src/ProtoGen/EnumFieldGenerator.cs
index 78384fdd..8d70bc67 100644
--- a/src/ProtoGen/EnumFieldGenerator.cs
+++ b/src/ProtoGen/EnumFieldGenerator.cs
@@ -72,12 +72,14 @@ namespace Google.ProtocolBuffers.ProtoGen
writer.WriteLine("}");
AddPublicMemberAttributes(writer);
writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.has{0} = true;", PropertyName);
writer.WriteLine(" result.{0}_ = value;", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.has{0} = false;", PropertyName);
writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
writer.WriteLine(" return this;");
diff --git a/src/ProtoGen/MessageFieldGenerator.cs b/src/ProtoGen/MessageFieldGenerator.cs
index 8e4bef5b..8e2691ee 100644
--- a/src/ProtoGen/MessageFieldGenerator.cs
+++ b/src/ProtoGen/MessageFieldGenerator.cs
@@ -73,6 +73,7 @@ namespace Google.ProtocolBuffers.ProtoGen
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
AddNullCheck(writer);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.has{0} = true;", PropertyName);
writer.WriteLine(" result.{0}_ = value;", Name);
writer.WriteLine(" return this;");
@@ -80,6 +81,7 @@ namespace Google.ProtocolBuffers.ProtoGen
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Set{0}({1}.Builder builderForValue) {{", PropertyName, TypeName);
AddNullCheck(writer, "builderForValue");
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.has{0} = true;", PropertyName);
writer.WriteLine(" result.{0}_ = builderForValue.Build();", Name);
writer.WriteLine(" return this;");
@@ -87,6 +89,7 @@ namespace Google.ProtocolBuffers.ProtoGen
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Merge{0}({1} value) {{", PropertyName, TypeName);
AddNullCheck(writer);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" if (result.has{0} &&", PropertyName);
writer.WriteLine(" result.{0}_ != {1}) {{", Name, DefaultValue);
writer.WriteLine(" result.{0}_ = {1}.CreateBuilder(result.{0}_).MergeFrom(value).BuildPartial();", Name,
@@ -99,6 +102,7 @@ namespace Google.ProtocolBuffers.ProtoGen
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.has{0} = false;", PropertyName);
writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
writer.WriteLine(" return this;");
diff --git a/src/ProtoGen/MessageGenerator.cs b/src/ProtoGen/MessageGenerator.cs
index c8b2087f..89c4aaec 100644
--- a/src/ProtoGen/MessageGenerator.cs
+++ b/src/ProtoGen/MessageGenerator.cs
@@ -556,7 +556,7 @@ namespace Google.ProtocolBuffers.ProtoGen
writer.WriteLine("public override Builder ToBuilder() { return CreateBuilder(this); }");
writer.WriteLine("public override Builder CreateBuilderForType() { return new Builder(); }");
writer.WriteLine("public static Builder CreateBuilder({0} prototype) {{", ClassName);
- writer.WriteLine(" return (Builder) new Builder().MergeFrom(prototype);");
+ writer.WriteLine(" return new Builder(prototype);");
writer.WriteLine("}");
writer.WriteLine();
if (Descriptor.File.CSharpOptions.AddSerializable)
@@ -591,21 +591,52 @@ namespace Google.ProtocolBuffers.ProtoGen
private void GenerateCommonBuilderMethods(TextGenerator writer)
{
- writer.WriteLine("public Builder() {{}}", ClassAccessLevel);
+ //default constructor
+ writer.WriteLine("public Builder() {");
+ //Durring static initialization of message, DefaultInstance is expected to return null.
+ writer.WriteLine(" result = DefaultInstance ?? new {0}();", ClassName);
+ writer.WriteLine(" builderIsReadOnly = result == DefaultInstance;");
+ writer.WriteLine("}");
+ //clone constructor
+ writer.WriteLine("internal Builder({0} cloneFrom) {{", ClassName);
+ writer.WriteLine(" result = cloneFrom;");
+ writer.WriteLine(" builderIsReadOnly = true;");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine("bool builderIsReadOnly;");
+ writer.WriteLine("{0} result;", ClassName);
+ writer.WriteLine();
+ writer.WriteLine("private {0} PrepareBuilder() {{", ClassName);
+ writer.WriteLine(" if (builderIsReadOnly) {");
+ writer.WriteLine(" {0} original = result;", ClassName);
+ writer.WriteLine(" result = new {0}();", ClassName);
+ writer.WriteLine(" builderIsReadOnly = false;");
+ writer.WriteLine(" MergeFrom(original);");
+ writer.WriteLine(" }");
+ writer.WriteLine(" return result;");
+ writer.WriteLine("}");
writer.WriteLine();
- writer.WriteLine("{0} result = new {0}();", ClassName);
+ writer.WriteLine("public override bool IsInitialized {");
+ writer.WriteLine(" get { return result.IsInitialized; }");
+ writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("protected override {0} MessageBeingBuilt {{", ClassName);
- writer.WriteLine(" get { return result; }");
+ writer.WriteLine(" get { return PrepareBuilder(); }");
writer.WriteLine("}");
writer.WriteLine();
+ //Not actually expecting that DefaultInstance would ever be null here; however, we will ensure it does not break
writer.WriteLine("public override Builder Clear() {");
- writer.WriteLine(" result = new {0}();", ClassName);
+ writer.WriteLine(" result = DefaultInstance ?? new {0}();", ClassName);
+ writer.WriteLine(" builderIsReadOnly = true;");
writer.WriteLine(" return this;");
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public override Builder Clone() {");
- writer.WriteLine(" return new Builder().MergeFrom(result);");
+ writer.WriteLine(" if (builderIsReadOnly) {");
+ writer.WriteLine(" return new Builder(result);");
+ writer.WriteLine(" } else {");
+ writer.WriteLine(" return new Builder().MergeFrom(result);");
+ writer.WriteLine(" }");
writer.WriteLine("}");
writer.WriteLine();
if (!UseLiteRuntime)
@@ -622,17 +653,15 @@ namespace Google.ProtocolBuffers.ProtoGen
writer.WriteLine("public override {0} BuildPartial() {{", ClassName);
writer.Indent();
- writer.WriteLine("if (result == null) {");
- writer.WriteLine(
- " throw new global::System.InvalidOperationException(\"build() has already been called on this Builder\");");
+ writer.WriteLine("if (builderIsReadOnly) {");
+ writer.WriteLine(" return result;");
writer.WriteLine("}");
foreach (FieldDescriptor field in Descriptor.Fields)
{
CreateFieldGenerator(field).GenerateBuildingCode(writer);
}
- writer.WriteLine("{0} returnMe = result;", ClassName);
- writer.WriteLine("result = null;");
- writer.WriteLine("return returnMe;");
+ writer.WriteLine("builderIsReadOnly = true;");
+ writer.WriteLine("return result;");
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
@@ -653,6 +682,7 @@ namespace Google.ProtocolBuffers.ProtoGen
// fields are set so we can skip the merge.
writer.Indent();
writer.WriteLine("if (other == {0}.DefaultInstance) return this;", FullClassName);
+ writer.WriteLine("PrepareBuilder();");
foreach (FieldDescriptor field in Descriptor.Fields)
{
CreateFieldGenerator(field).GenerateMergingCode(writer);
@@ -685,6 +715,7 @@ namespace Google.ProtocolBuffers.ProtoGen
writer.WriteLine(
"public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {");
writer.Indent();
+ writer.WriteLine("PrepareBuilder();");
if (!UseLiteRuntime)
{
writer.WriteLine("pb::UnknownFieldSet.Builder unknownFields = null;");
diff --git a/src/ProtoGen/PrimitiveFieldGenerator.cs b/src/ProtoGen/PrimitiveFieldGenerator.cs
index 0904ce22..69e0d4d9 100644
--- a/src/ProtoGen/PrimitiveFieldGenerator.cs
+++ b/src/ProtoGen/PrimitiveFieldGenerator.cs
@@ -74,12 +74,14 @@ namespace Google.ProtocolBuffers.ProtoGen
AddPublicMemberAttributes(writer);
writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
AddNullCheck(writer);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.has{0} = true;", PropertyName);
writer.WriteLine(" result.{0}_ = value;", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.has{0} = false;", PropertyName);
writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
writer.WriteLine(" return this;");
diff --git a/src/ProtoGen/RepeatedEnumFieldGenerator.cs b/src/ProtoGen/RepeatedEnumFieldGenerator.cs
index fcda6564..aacee937 100644
--- a/src/ProtoGen/RepeatedEnumFieldGenerator.cs
+++ b/src/ProtoGen/RepeatedEnumFieldGenerator.cs
@@ -75,7 +75,7 @@ namespace Google.ProtocolBuffers.ProtoGen
// We return it via IPopsicleList so that collection initializers work more pleasantly.
AddDeprecatedFlag(writer);
writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return result.{0}_; }}", Name);
+ writer.WriteLine(" get {{ return PrepareBuilder().{0}_; }}", Name);
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public int {0}Count {{", PropertyName);
@@ -87,21 +87,25 @@ namespace Google.ProtocolBuffers.ProtoGen
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_[index] = value;", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
writer.WriteLine(" return this;");
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_.Add(values);", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_.Clear();", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
diff --git a/src/ProtoGen/RepeatedMessageFieldGenerator.cs b/src/ProtoGen/RepeatedMessageFieldGenerator.cs
index d8f0a8eb..6cc1e631 100644
--- a/src/ProtoGen/RepeatedMessageFieldGenerator.cs
+++ b/src/ProtoGen/RepeatedMessageFieldGenerator.cs
@@ -71,7 +71,7 @@ namespace Google.ProtocolBuffers.ProtoGen
// We return it via IPopsicleList so that collection initializers work more pleasantly.
AddDeprecatedFlag(writer);
writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return result.{0}_; }}", Name);
+ writer.WriteLine(" get {{ return PrepareBuilder().{0}_; }}", Name);
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public int {0}Count {{", PropertyName);
@@ -84,6 +84,7 @@ namespace Google.ProtocolBuffers.ProtoGen
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
AddNullCheck(writer);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_[index] = value;", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
@@ -91,12 +92,14 @@ namespace Google.ProtocolBuffers.ProtoGen
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Set{0}(int index, {1}.Builder builderForValue) {{", PropertyName, TypeName);
AddNullCheck(writer, "builderForValue");
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_[index] = builderForValue.Build();", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
AddNullCheck(writer);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
writer.WriteLine(" return this;");
writer.WriteLine("}");
@@ -104,16 +107,19 @@ namespace Google.ProtocolBuffers.ProtoGen
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Add{0}({1}.Builder builderForValue) {{", PropertyName, TypeName);
AddNullCheck(writer, "builderForValue");
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_.Add(builderForValue.Build());", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_.Add(values);", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_.Clear();", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
diff --git a/src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs b/src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs
index 33f0fa2b..645dce5c 100644
--- a/src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs
+++ b/src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs
@@ -75,7 +75,7 @@ namespace Google.ProtocolBuffers.ProtoGen
// We return it via IPopsicleList so that collection initializers work more pleasantly.
AddPublicMemberAttributes(writer);
writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return result.{0}_; }}", Name);
+ writer.WriteLine(" get {{ return PrepareBuilder().{0}_; }}", Name);
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public int {0}Count {{", PropertyName);
@@ -88,22 +88,26 @@ namespace Google.ProtocolBuffers.ProtoGen
AddPublicMemberAttributes(writer);
writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
AddNullCheck(writer);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_[index] = value;", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
AddPublicMemberAttributes(writer);
writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
AddNullCheck(writer);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
writer.WriteLine(" return this;");
writer.WriteLine("}");
AddPublicMemberAttributes(writer);
writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_.Add(values);", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");
AddDeprecatedFlag(writer);
writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.{0}_.Clear();", Name);
writer.WriteLine(" return this;");
writer.WriteLine("}");