浏览代码

Generator changes to fix circular reference issues in static ctor

csharptest 14 年之前
父节点
当前提交
dc24b605e3

+ 3 - 3
src/ProtoGen/MessageFieldGenerator.cs

@@ -48,12 +48,12 @@ namespace Google.ProtocolBuffers.ProtoGen
         public void GenerateMembers(TextGenerator writer)
         {
             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("  get {{ return has{0}; }}", PropertyName);
             writer.WriteLine("}");
             writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
-            writer.WriteLine("  get {{ return {0}_; }}", Name);
+            writer.WriteLine("  get {{ return {0}_ ?? {1}; }}", Name, DefaultValue);
             writer.WriteLine("}");
         }
 
@@ -96,7 +96,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             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("  result.{0}_ = null;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
         }

+ 26 - 19
src/ProtoGen/MessageGenerator.cs

@@ -178,7 +178,7 @@ namespace Google.ProtocolBuffers.ProtoGen
                              RuntimeSuffix);
             writer.Indent();
             // 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)
             {
@@ -199,7 +199,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("}");
             writer.WriteLine();
             writer.WriteLine("public override {0} DefaultInstanceForType {{", ClassName);
-            writer.WriteLine("  get { return defaultInstance; }");
+            writer.WriteLine("  get { return DefaultInstance; }");
             writer.WriteLine("}");
             writer.WriteLine();
             writer.WriteLine("protected override {0} ThisMessage {{", ClassName);
@@ -547,6 +547,17 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         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 override Builder ToBuilder() { return CreateBuilder(this); }");
             writer.WriteLine("public override Builder CreateBuilderForType() { return new Builder(); }");
@@ -585,23 +596,23 @@ namespace Google.ProtocolBuffers.ProtoGen
             //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("  result = DefaultInstance;");
+            writer.WriteLine("  resultIsReadOnly = true;");
             writer.WriteLine("}");
             //clone constructor
             writer.WriteLine("internal Builder({0} cloneFrom) {{", ClassName);
             writer.WriteLine("  result = cloneFrom;");
-            writer.WriteLine("  builderIsReadOnly = true;");
+            writer.WriteLine("  resultIsReadOnly = true;");
             writer.WriteLine("}");
             writer.WriteLine();
-            writer.WriteLine("bool builderIsReadOnly;");
-            writer.WriteLine("{0} result;", ClassName);
+            writer.WriteLine("private bool resultIsReadOnly;");
+            writer.WriteLine("private {0} result;", ClassName);
             writer.WriteLine();
             writer.WriteLine("private {0} PrepareBuilder() {{", ClassName);
-            writer.WriteLine("  if (builderIsReadOnly) {");
+            writer.WriteLine("  if (resultIsReadOnly) {");
             writer.WriteLine("    {0} original = result;", ClassName);
             writer.WriteLine("    result = new {0}();", ClassName);
-            writer.WriteLine("    builderIsReadOnly = false;");
+            writer.WriteLine("    resultIsReadOnly = false;");
             writer.WriteLine("    MergeFrom(original);");
             writer.WriteLine("  }");
             writer.WriteLine("  return result;");
@@ -617,13 +628,13 @@ namespace Google.ProtocolBuffers.ProtoGen
             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 = DefaultInstance ?? new {0}();", ClassName);
-            writer.WriteLine("  builderIsReadOnly = true;");
+            writer.WriteLine("  result = DefaultInstance;", ClassName);
+            writer.WriteLine("  resultIsReadOnly = true;");
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             writer.WriteLine();
             writer.WriteLine("public override Builder Clone() {");
-            writer.WriteLine("  if (builderIsReadOnly) {");
+            writer.WriteLine("  if (resultIsReadOnly) {");
             writer.WriteLine("    return new Builder(result);");
             writer.WriteLine("  } else {");
             writer.WriteLine("    return new Builder().MergeFrom(result);");
@@ -644,15 +655,11 @@ namespace Google.ProtocolBuffers.ProtoGen
 
             writer.WriteLine("public override {0} BuildPartial() {{", ClassName);
             writer.Indent();
-            writer.WriteLine("if (builderIsReadOnly) {");
+            writer.WriteLine("if (resultIsReadOnly) {");
             writer.WriteLine("  return result;");
             writer.WriteLine("}");
-            foreach (FieldDescriptor field in Descriptor.Fields)
-            {
-                CreateFieldGenerator(field).GenerateBuildingCode(writer);
-            }
-            writer.WriteLine("builderIsReadOnly = true;");
-            writer.WriteLine("return result;");
+            writer.WriteLine("resultIsReadOnly = true;");
+            writer.WriteLine("return result.MakeReadOnly();");
             writer.Outdent();
             writer.WriteLine("}");
             writer.WriteLine();

+ 1 - 1
src/ProtoGen/RepeatedEnumFieldGenerator.cs

@@ -110,7 +110,7 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         public void GenerateBuildingCode(TextGenerator writer)
         {
-            writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
+            writer.WriteLine("{0}_.MakeReadOnly();", Name);
         }
 
         public void GenerateParsingCode(TextGenerator writer)

+ 1 - 1
src/ProtoGen/RepeatedMessageFieldGenerator.cs

@@ -122,7 +122,7 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         public void GenerateBuildingCode(TextGenerator writer)
         {
-            writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
+            writer.WriteLine("{0}_.MakeReadOnly();", Name);
         }
 
         public void GenerateParsingCode(TextGenerator writer)

+ 1 - 1
src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs

@@ -119,7 +119,7 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         public void GenerateBuildingCode(TextGenerator writer)
         {
-            writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
+            writer.WriteLine("{0}_.MakeReadOnly();", Name);
         }
 
         public void GenerateParsingCode(TextGenerator writer)