Commit dc24b605 authored by csharptest's avatar csharptest Committed by rogerk

Generator changes to fix circular reference issues in static ctor

parent 8bd88ea8
...@@ -48,12 +48,12 @@ namespace Google.ProtocolBuffers.ProtoGen ...@@ -48,12 +48,12 @@ namespace Google.ProtocolBuffers.ProtoGen
public void GenerateMembers(TextGenerator writer) public void GenerateMembers(TextGenerator writer)
{ {
writer.WriteLine("private bool has{0};", PropertyName); writer.WriteLine("private bool has{0};", PropertyName);
writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue); writer.WriteLine("private {0} {1}_;", TypeName, Name);
writer.WriteLine("public bool Has{0} {{", PropertyName); writer.WriteLine("public bool Has{0} {{", PropertyName);
writer.WriteLine(" get {{ return has{0}; }}", PropertyName); writer.WriteLine(" get {{ return has{0}; }}", PropertyName);
writer.WriteLine("}"); writer.WriteLine("}");
writer.WriteLine("public {0} {1} {{", TypeName, PropertyName); writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
writer.WriteLine(" get {{ return {0}_; }}", Name); writer.WriteLine(" get {{ return {0}_ ?? {1}; }}", Name, DefaultValue);
writer.WriteLine("}"); writer.WriteLine("}");
} }
...@@ -96,7 +96,7 @@ namespace Google.ProtocolBuffers.ProtoGen ...@@ -96,7 +96,7 @@ namespace Google.ProtocolBuffers.ProtoGen
writer.WriteLine("public Builder Clear{0}() {{", PropertyName); writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
writer.WriteLine(" PrepareBuilder();"); writer.WriteLine(" PrepareBuilder();");
writer.WriteLine(" result.has{0} = false;", PropertyName); writer.WriteLine(" result.has{0} = false;", PropertyName);
writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue); writer.WriteLine(" result.{0}_ = null;", Name);
writer.WriteLine(" return this;"); writer.WriteLine(" return this;");
writer.WriteLine("}"); writer.WriteLine("}");
} }
......
...@@ -178,7 +178,7 @@ namespace Google.ProtocolBuffers.ProtoGen ...@@ -178,7 +178,7 @@ namespace Google.ProtocolBuffers.ProtoGen
RuntimeSuffix); RuntimeSuffix);
writer.Indent(); writer.Indent();
// Must call BuildPartial() to make sure all lists are made read-only // Must call BuildPartial() to make sure all lists are made read-only
writer.WriteLine("private static readonly {0} defaultInstance = new Builder().BuildPartial();", ClassName); writer.WriteLine("private static readonly {0} defaultInstance = new {0}().MakeReadOnly();", ClassName);
if (OptimizeSpeed) if (OptimizeSpeed)
{ {
...@@ -199,7 +199,7 @@ namespace Google.ProtocolBuffers.ProtoGen ...@@ -199,7 +199,7 @@ namespace Google.ProtocolBuffers.ProtoGen
writer.WriteLine("}"); writer.WriteLine("}");
writer.WriteLine(); writer.WriteLine();
writer.WriteLine("public override {0} DefaultInstanceForType {{", ClassName); writer.WriteLine("public override {0} DefaultInstanceForType {{", ClassName);
writer.WriteLine(" get { return defaultInstance; }"); writer.WriteLine(" get { return DefaultInstance; }");
writer.WriteLine("}"); writer.WriteLine("}");
writer.WriteLine(); writer.WriteLine();
writer.WriteLine("protected override {0} ThisMessage {{", ClassName); writer.WriteLine("protected override {0} ThisMessage {{", ClassName);
...@@ -547,6 +547,17 @@ namespace Google.ProtocolBuffers.ProtoGen ...@@ -547,6 +547,17 @@ namespace Google.ProtocolBuffers.ProtoGen
private void GenerateBuilder(TextGenerator writer) private void GenerateBuilder(TextGenerator writer)
{ {
writer.WriteLine("private {0} MakeReadOnly() {{", ClassName);
writer.Indent();
foreach (FieldDescriptor field in Descriptor.Fields)
{
CreateFieldGenerator(field).GenerateBuildingCode(writer);
}
writer.WriteLine("return this;");
writer.Outdent();
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public static Builder CreateBuilder() { return new Builder(); }"); writer.WriteLine("public static Builder CreateBuilder() { return new Builder(); }");
writer.WriteLine("public override Builder ToBuilder() { return CreateBuilder(this); }"); writer.WriteLine("public override Builder ToBuilder() { return CreateBuilder(this); }");
writer.WriteLine("public override Builder CreateBuilderForType() { return new Builder(); }"); writer.WriteLine("public override Builder CreateBuilderForType() { return new Builder(); }");
...@@ -585,23 +596,23 @@ namespace Google.ProtocolBuffers.ProtoGen ...@@ -585,23 +596,23 @@ namespace Google.ProtocolBuffers.ProtoGen
//default constructor //default constructor
writer.WriteLine("public Builder() {"); writer.WriteLine("public Builder() {");
//Durring static initialization of message, DefaultInstance is expected to return null. //Durring static initialization of message, DefaultInstance is expected to return null.
writer.WriteLine(" result = DefaultInstance ?? new {0}();", ClassName); writer.WriteLine(" result = DefaultInstance;");
writer.WriteLine(" builderIsReadOnly = result == DefaultInstance;"); writer.WriteLine(" resultIsReadOnly = true;");
writer.WriteLine("}"); writer.WriteLine("}");
//clone constructor //clone constructor
writer.WriteLine("internal Builder({0} cloneFrom) {{", ClassName); writer.WriteLine("internal Builder({0} cloneFrom) {{", ClassName);
writer.WriteLine(" result = cloneFrom;"); writer.WriteLine(" result = cloneFrom;");
writer.WriteLine(" builderIsReadOnly = true;"); writer.WriteLine(" resultIsReadOnly = true;");
writer.WriteLine("}"); writer.WriteLine("}");
writer.WriteLine(); writer.WriteLine();
writer.WriteLine("bool builderIsReadOnly;"); writer.WriteLine("private bool resultIsReadOnly;");
writer.WriteLine("{0} result;", ClassName); writer.WriteLine("private {0} result;", ClassName);
writer.WriteLine(); writer.WriteLine();
writer.WriteLine("private {0} PrepareBuilder() {{", ClassName); writer.WriteLine("private {0} PrepareBuilder() {{", ClassName);
writer.WriteLine(" if (builderIsReadOnly) {"); writer.WriteLine(" if (resultIsReadOnly) {");
writer.WriteLine(" {0} original = result;", ClassName); writer.WriteLine(" {0} original = result;", ClassName);
writer.WriteLine(" result = new {0}();", ClassName); writer.WriteLine(" result = new {0}();", ClassName);
writer.WriteLine(" builderIsReadOnly = false;"); writer.WriteLine(" resultIsReadOnly = false;");
writer.WriteLine(" MergeFrom(original);"); writer.WriteLine(" MergeFrom(original);");
writer.WriteLine(" }"); writer.WriteLine(" }");
writer.WriteLine(" return result;"); writer.WriteLine(" return result;");
...@@ -617,13 +628,13 @@ namespace Google.ProtocolBuffers.ProtoGen ...@@ -617,13 +628,13 @@ namespace Google.ProtocolBuffers.ProtoGen
writer.WriteLine(); writer.WriteLine();
//Not actually expecting that DefaultInstance would ever be null here; however, we will ensure it does not break //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("public override Builder Clear() {");
writer.WriteLine(" result = DefaultInstance ?? new {0}();", ClassName); writer.WriteLine(" result = DefaultInstance;", ClassName);
writer.WriteLine(" builderIsReadOnly = true;"); writer.WriteLine(" resultIsReadOnly = true;");
writer.WriteLine(" return this;"); writer.WriteLine(" return this;");
writer.WriteLine("}"); writer.WriteLine("}");
writer.WriteLine(); writer.WriteLine();
writer.WriteLine("public override Builder Clone() {"); writer.WriteLine("public override Builder Clone() {");
writer.WriteLine(" if (builderIsReadOnly) {"); writer.WriteLine(" if (resultIsReadOnly) {");
writer.WriteLine(" return new Builder(result);"); writer.WriteLine(" return new Builder(result);");
writer.WriteLine(" } else {"); writer.WriteLine(" } else {");
writer.WriteLine(" return new Builder().MergeFrom(result);"); writer.WriteLine(" return new Builder().MergeFrom(result);");
...@@ -644,15 +655,11 @@ namespace Google.ProtocolBuffers.ProtoGen ...@@ -644,15 +655,11 @@ namespace Google.ProtocolBuffers.ProtoGen
writer.WriteLine("public override {0} BuildPartial() {{", ClassName); writer.WriteLine("public override {0} BuildPartial() {{", ClassName);
writer.Indent(); writer.Indent();
writer.WriteLine("if (builderIsReadOnly) {"); writer.WriteLine("if (resultIsReadOnly) {");
writer.WriteLine(" return result;"); writer.WriteLine(" return result;");
writer.WriteLine("}"); writer.WriteLine("}");
foreach (FieldDescriptor field in Descriptor.Fields) writer.WriteLine("resultIsReadOnly = true;");
{ writer.WriteLine("return result.MakeReadOnly();");
CreateFieldGenerator(field).GenerateBuildingCode(writer);
}
writer.WriteLine("builderIsReadOnly = true;");
writer.WriteLine("return result;");
writer.Outdent(); writer.Outdent();
writer.WriteLine("}"); writer.WriteLine("}");
writer.WriteLine(); writer.WriteLine();
......
...@@ -110,7 +110,7 @@ namespace Google.ProtocolBuffers.ProtoGen ...@@ -110,7 +110,7 @@ namespace Google.ProtocolBuffers.ProtoGen
public void GenerateBuildingCode(TextGenerator writer) public void GenerateBuildingCode(TextGenerator writer)
{ {
writer.WriteLine("result.{0}_.MakeReadOnly();", Name); writer.WriteLine("{0}_.MakeReadOnly();", Name);
} }
public void GenerateParsingCode(TextGenerator writer) public void GenerateParsingCode(TextGenerator writer)
......
...@@ -122,7 +122,7 @@ namespace Google.ProtocolBuffers.ProtoGen ...@@ -122,7 +122,7 @@ namespace Google.ProtocolBuffers.ProtoGen
public void GenerateBuildingCode(TextGenerator writer) public void GenerateBuildingCode(TextGenerator writer)
{ {
writer.WriteLine("result.{0}_.MakeReadOnly();", Name); writer.WriteLine("{0}_.MakeReadOnly();", Name);
} }
public void GenerateParsingCode(TextGenerator writer) public void GenerateParsingCode(TextGenerator writer)
......
...@@ -119,7 +119,7 @@ namespace Google.ProtocolBuffers.ProtoGen ...@@ -119,7 +119,7 @@ namespace Google.ProtocolBuffers.ProtoGen
public void GenerateBuildingCode(TextGenerator writer) public void GenerateBuildingCode(TextGenerator writer)
{ {
writer.WriteLine("result.{0}_.MakeReadOnly();", Name); writer.WriteLine("{0}_.MakeReadOnly();", Name);
} }
public void GenerateParsingCode(TextGenerator writer) public void GenerateParsingCode(TextGenerator writer)
......
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