aboutsummaryrefslogtreecommitdiff
path: root/src/ProtoGen
diff options
context:
space:
mode:
authorcsharptest <roger@csharptest.net>2011-05-20 15:15:34 -0500
committerrogerk <devnull@localhost>2011-05-20 15:15:34 -0500
commit71f662c33e9938951eec3da97140aed25aa815d7 (patch)
treec322e13686cad5c8bff9e54d7585fc8e4adf6537 /src/ProtoGen
parentd965c666ecf405f4e997ab251e72551508a14678 (diff)
downloadprotobuf-71f662c33e9938951eec3da97140aed25aa815d7.tar.gz
protobuf-71f662c33e9938951eec3da97140aed25aa815d7.tar.bz2
protobuf-71f662c33e9938951eec3da97140aed25aa815d7.zip
reformatted all code to .NET standard formatting
Diffstat (limited to 'src/ProtoGen')
-rw-r--r--src/ProtoGen/DependencyResolutionException.cs104
-rw-r--r--src/ProtoGen/DescriptorUtil.cs192
-rw-r--r--src/ProtoGen/EnumFieldGenerator.cs269
-rw-r--r--src/ProtoGen/EnumGenerator.cs115
-rw-r--r--src/ProtoGen/ExtensionGenerator.cs312
-rw-r--r--src/ProtoGen/FieldGeneratorBase.cs584
-rw-r--r--src/ProtoGen/Generator.cs455
-rw-r--r--src/ProtoGen/GeneratorOptions.cs613
-rw-r--r--src/ProtoGen/Helpers.cs87
-rw-r--r--src/ProtoGen/IFieldSourceGenerator.cs102
-rw-r--r--src/ProtoGen/ISourceGenerator.cs82
-rw-r--r--src/ProtoGen/InvalidOptionsException.cs147
-rw-r--r--src/ProtoGen/MessageFieldGenerator.cs303
-rw-r--r--src/ProtoGen/MessageGenerator.cs1349
-rw-r--r--src/ProtoGen/PrimitiveFieldGenerator.cs253
-rw-r--r--src/ProtoGen/Program.cs148
-rw-r--r--src/ProtoGen/ProgramPreprocess.cs339
-rw-r--r--src/ProtoGen/Properties/AssemblyInfo.cs77
-rw-r--r--src/ProtoGen/RepeatedEnumFieldGenerator.cs413
-rw-r--r--src/ProtoGen/RepeatedMessageFieldGenerator.cs323
-rw-r--r--src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs403
-rw-r--r--src/ProtoGen/ServiceGenerator.cs352
-rw-r--r--src/ProtoGen/ServiceInterfaceGenerator.cs436
-rw-r--r--src/ProtoGen/SourceGeneratorBase.cs287
-rw-r--r--src/ProtoGen/SourceGenerators.cs231
-rw-r--r--src/ProtoGen/UmbrellaClassGenerator.cs526
-rw-r--r--src/ProtoGen/app.config8
27 files changed, 4607 insertions, 3903 deletions
diff --git a/src/ProtoGen/DependencyResolutionException.cs b/src/ProtoGen/DependencyResolutionException.cs
index b41149b6..aef192e0 100644
--- a/src/ProtoGen/DependencyResolutionException.cs
+++ b/src/ProtoGen/DependencyResolutionException.cs
@@ -1,49 +1,55 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- /// <summary>
- /// Exception thrown when dependencies within a descriptor set can't be resolved.
- /// </summary>
- public sealed class DependencyResolutionException : Exception {
- public DependencyResolutionException(string message) : base(message) {
- }
-
- public DependencyResolutionException(string format, params object[] args)
- : base(string.Format(format, args)) {
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ /// <summary>
+ /// Exception thrown when dependencies within a descriptor set can't be resolved.
+ /// </summary>
+ public sealed class DependencyResolutionException : Exception
+ {
+ public DependencyResolutionException(string message) : base(message)
+ {
+ }
+
+ public DependencyResolutionException(string format, params object[] args)
+ : base(string.Format(format, args))
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/DescriptorUtil.cs b/src/ProtoGen/DescriptorUtil.cs
index af5a2f9a..0666bb93 100644
--- a/src/ProtoGen/DescriptorUtil.cs
+++ b/src/ProtoGen/DescriptorUtil.cs
@@ -1,86 +1,106 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System;
-using Google.ProtocolBuffers.DescriptorProtos;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- /// <summary>
- /// Utility class for determining namespaces etc.
- /// </summary>
- internal static class DescriptorUtil {
-
- internal static string GetFullUmbrellaClassName(IDescriptor descriptor) {
- CSharpFileOptions options = descriptor.File.CSharpOptions;
- string result = options.Namespace;
- if (result != "") {
- result += '.';
- }
- result += GetQualifiedUmbrellaClassName(options);
- return "global::" + result;
- }
-
- /// <summary>
- /// Evaluates the options and returns the qualified name of the umbrella class
- /// relative to the descriptor type's namespace. Basically concatenates the
- /// UmbrellaNamespace + UmbrellaClassname fields.
- /// </summary>
- internal static string GetQualifiedUmbrellaClassName(CSharpFileOptions options) {
- string fullName = options.UmbrellaClassname;
- if (!options.NestClasses && options.UmbrellaNamespace != "") {
- fullName = String.Format("{0}.{1}", options.UmbrellaNamespace, options.UmbrellaClassname);
- }
- return fullName;
- }
-
- internal static string GetMappedTypeName(MappedType type) {
- switch(type) {
- case MappedType.Int32: return "int";
- case MappedType.Int64: return "long";
- case MappedType.UInt32: return "uint";
- case MappedType.UInt64: return "ulong";
- case MappedType.Single: return "float";
- case MappedType.Double: return "double";
- case MappedType.Boolean: return "bool";
- case MappedType.String: return "string";
- case MappedType.ByteString: return "pb::ByteString";
- case MappedType.Enum: return null;
- case MappedType.Message: return null;
- default:
- throw new ArgumentOutOfRangeException("Unknown mapped type " + type);
- }
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using Google.ProtocolBuffers.DescriptorProtos;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ /// <summary>
+ /// Utility class for determining namespaces etc.
+ /// </summary>
+ internal static class DescriptorUtil
+ {
+ internal static string GetFullUmbrellaClassName(IDescriptor descriptor)
+ {
+ CSharpFileOptions options = descriptor.File.CSharpOptions;
+ string result = options.Namespace;
+ if (result != "")
+ {
+ result += '.';
+ }
+ result += GetQualifiedUmbrellaClassName(options);
+ return "global::" + result;
+ }
+
+ /// <summary>
+ /// Evaluates the options and returns the qualified name of the umbrella class
+ /// relative to the descriptor type's namespace. Basically concatenates the
+ /// UmbrellaNamespace + UmbrellaClassname fields.
+ /// </summary>
+ internal static string GetQualifiedUmbrellaClassName(CSharpFileOptions options)
+ {
+ string fullName = options.UmbrellaClassname;
+ if (!options.NestClasses && options.UmbrellaNamespace != "")
+ {
+ fullName = String.Format("{0}.{1}", options.UmbrellaNamespace, options.UmbrellaClassname);
+ }
+ return fullName;
+ }
+
+ internal static string GetMappedTypeName(MappedType type)
+ {
+ switch (type)
+ {
+ case MappedType.Int32:
+ return "int";
+ case MappedType.Int64:
+ return "long";
+ case MappedType.UInt32:
+ return "uint";
+ case MappedType.UInt64:
+ return "ulong";
+ case MappedType.Single:
+ return "float";
+ case MappedType.Double:
+ return "double";
+ case MappedType.Boolean:
+ return "bool";
+ case MappedType.String:
+ return "string";
+ case MappedType.ByteString:
+ return "pb::ByteString";
+ case MappedType.Enum:
+ return null;
+ case MappedType.Message:
+ return null;
+ default:
+ throw new ArgumentOutOfRangeException("Unknown mapped type " + type);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/EnumFieldGenerator.cs b/src/ProtoGen/EnumFieldGenerator.cs
index 6cd59869..fe0d3bab 100644
--- a/src/ProtoGen/EnumFieldGenerator.cs
+++ b/src/ProtoGen/EnumFieldGenerator.cs
@@ -1,126 +1,143 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal class EnumFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
- internal EnumFieldGenerator(FieldDescriptor descriptor)
- : base(descriptor) {
- }
-
- public void GenerateMembers(TextGenerator writer) {
- writer.WriteLine("private bool has{0};", PropertyName);
- writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue);
- writer.WriteLine("public bool Has{0} {{", PropertyName);
- writer.WriteLine(" get {{ return has{0}; }}", PropertyName);
- writer.WriteLine("}");
- AddClsComplianceCheck(writer);
- writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return {0}_; }}", Name);
- writer.WriteLine("}");
- }
-
- public void GenerateBuilderMembers(TextGenerator writer) {
- writer.WriteLine("public bool Has{0} {{", PropertyName);
- writer.WriteLine(" get {{ return result.Has{0}; }}", PropertyName);
- writer.WriteLine("}");
- AddClsComplianceCheck(writer);
- writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return result.{0}; }}", PropertyName);
- writer.WriteLine(" set {{ Set{0}(value); }}", PropertyName);
- writer.WriteLine("}");
- AddClsComplianceCheck(writer);
- writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
- writer.WriteLine(" result.has{0} = true;", PropertyName);
- writer.WriteLine(" result.{0}_ = value;", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
- writer.WriteLine(" result.has{0} = false;", PropertyName);
- writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- }
-
- public void GenerateMergingCode(TextGenerator writer) {
- writer.WriteLine("if (other.Has{0}) {{", PropertyName);
- writer.WriteLine(" {0} = other.{0};", PropertyName);
- writer.WriteLine("}");
- }
-
- public void GenerateBuildingCode(TextGenerator writer) {
- // Nothing to do here for enum types
- }
-
- public void GenerateParsingCode(TextGenerator writer) {
- // TODO(jonskeet): Make a more efficient way of doing this
- writer.WriteLine("int rawValue = input.ReadEnum();");
- writer.WriteLine("if (!global::System.Enum.IsDefined(typeof({0}), rawValue)) {{", TypeName);
- if (!UseLiteRuntime) {
- writer.WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now
- writer.WriteLine(" unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
- writer.WriteLine(" }");
- writer.WriteLine(" unknownFields.MergeVarintField({0}, (ulong) rawValue);", Number);
- }
- writer.WriteLine("} else {");
- writer.WriteLine(" {0} = ({1}) rawValue;", PropertyName, TypeName);
- writer.WriteLine("}");
- }
-
- public void GenerateSerializationCode(TextGenerator writer) {
- writer.WriteLine("if (Has{0}) {{", PropertyName);
- writer.WriteLine(" output.WriteEnum({0}, (int) {1});", Number, PropertyName);
- writer.WriteLine("}");
- }
-
- public void GenerateSerializedSizeCode(TextGenerator writer) {
- writer.WriteLine("if (Has{0}) {{", PropertyName);
- writer.WriteLine(" size += pb::CodedOutputStream.ComputeEnumSize({0}, (int) {1});", Number, PropertyName);
- writer.WriteLine("}");
- }
-
- public override void WriteHash(TextGenerator writer) {
- writer.WriteLine("if (has{0}) hash ^= {1}_.GetHashCode();", PropertyName, Name);
- }
-
- public override void WriteEquals(TextGenerator writer) {
- writer.WriteLine("if (has{0} != other.has{0} || (has{0} && !{1}_.Equals(other.{1}_))) return false;", PropertyName, Name);
- }
-
- public override void WriteToString(TextGenerator writer) {
- writer.WriteLine("PrintField(\"{0}\", has{1}, {2}_, writer);", Descriptor.Name, PropertyName, Name);
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal class EnumFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator
+ {
+ internal EnumFieldGenerator(FieldDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
+
+ public void GenerateMembers(TextGenerator writer)
+ {
+ writer.WriteLine("private bool has{0};", PropertyName);
+ writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue);
+ writer.WriteLine("public bool Has{0} {{", PropertyName);
+ writer.WriteLine(" get {{ return has{0}; }}", PropertyName);
+ writer.WriteLine("}");
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
+ writer.WriteLine(" get {{ return {0}_; }}", Name);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateBuilderMembers(TextGenerator writer)
+ {
+ writer.WriteLine("public bool Has{0} {{", PropertyName);
+ writer.WriteLine(" get {{ return result.Has{0}; }}", PropertyName);
+ writer.WriteLine("}");
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
+ writer.WriteLine(" get {{ return result.{0}; }}", PropertyName);
+ writer.WriteLine(" set {{ Set{0}(value); }}", PropertyName);
+ writer.WriteLine("}");
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
+ writer.WriteLine(" result.has{0} = true;", PropertyName);
+ writer.WriteLine(" result.{0}_ = value;", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" result.has{0} = false;", PropertyName);
+ writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ }
+
+ public void GenerateMergingCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (other.Has{0}) {{", PropertyName);
+ writer.WriteLine(" {0} = other.{0};", PropertyName);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateBuildingCode(TextGenerator writer)
+ {
+ // Nothing to do here for enum types
+ }
+
+ public void GenerateParsingCode(TextGenerator writer)
+ {
+ // TODO(jonskeet): Make a more efficient way of doing this
+ writer.WriteLine("int rawValue = input.ReadEnum();");
+ writer.WriteLine("if (!global::System.Enum.IsDefined(typeof({0}), rawValue)) {{", TypeName);
+ if (!UseLiteRuntime)
+ {
+ writer.WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now
+ writer.WriteLine(" unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
+ writer.WriteLine(" }");
+ writer.WriteLine(" unknownFields.MergeVarintField({0}, (ulong) rawValue);", Number);
+ }
+ writer.WriteLine("} else {");
+ writer.WriteLine(" {0} = ({1}) rawValue;", PropertyName, TypeName);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateSerializationCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (Has{0}) {{", PropertyName);
+ writer.WriteLine(" output.WriteEnum({0}, (int) {1});", Number, PropertyName);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateSerializedSizeCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (Has{0}) {{", PropertyName);
+ writer.WriteLine(" size += pb::CodedOutputStream.ComputeEnumSize({0}, (int) {1});", Number, PropertyName);
+ writer.WriteLine("}");
+ }
+
+ public override void WriteHash(TextGenerator writer)
+ {
+ writer.WriteLine("if (has{0}) hash ^= {1}_.GetHashCode();", PropertyName, Name);
+ }
+
+ public override void WriteEquals(TextGenerator writer)
+ {
+ writer.WriteLine("if (has{0} != other.has{0} || (has{0} && !{1}_.Equals(other.{1}_))) return false;",
+ PropertyName, Name);
+ }
+
+ public override void WriteToString(TextGenerator writer)
+ {
+ writer.WriteLine("PrintField(\"{0}\", has{1}, {2}_, writer);", Descriptor.Name, PropertyName, Name);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/EnumGenerator.cs b/src/ProtoGen/EnumGenerator.cs
index bc07e219..c1013345 100644
--- a/src/ProtoGen/EnumGenerator.cs
+++ b/src/ProtoGen/EnumGenerator.cs
@@ -1,54 +1,61 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal class EnumGenerator : SourceGeneratorBase<EnumDescriptor>, ISourceGenerator {
- internal EnumGenerator(EnumDescriptor descriptor) : base(descriptor) {
- }
-
- // TODO(jonskeet): Write out enum descriptors? Can be retrieved from file...
- public void Generate(TextGenerator writer) {
- writer.WriteLine("{0} enum {1} {{", ClassAccessLevel, Descriptor.Name);
- writer.Indent();
- foreach (EnumValueDescriptor value in Descriptor.Values) {
- writer.WriteLine("{0} = {1},", value.Name, value.Number);
- }
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal class EnumGenerator : SourceGeneratorBase<EnumDescriptor>, ISourceGenerator
+ {
+ internal EnumGenerator(EnumDescriptor descriptor) : base(descriptor)
+ {
+ }
+
+ // TODO(jonskeet): Write out enum descriptors? Can be retrieved from file...
+ public void Generate(TextGenerator writer)
+ {
+ writer.WriteLine("{0} enum {1} {{", ClassAccessLevel, Descriptor.Name);
+ writer.Indent();
+ foreach (EnumValueDescriptor value in Descriptor.Values)
+ {
+ writer.WriteLine("{0} = {1},", value.Name, value.Number);
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/ExtensionGenerator.cs b/src/ProtoGen/ExtensionGenerator.cs
index 57713bf7..ce37b2de 100644
--- a/src/ProtoGen/ExtensionGenerator.cs
+++ b/src/ProtoGen/ExtensionGenerator.cs
@@ -1,135 +1,177 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System;
-using System.Globalization;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal class ExtensionGenerator : FieldGeneratorBase, ISourceGenerator {
-
- private readonly string extends;
- private readonly string scope;
- private readonly string type;
- private readonly string name;
-
- internal ExtensionGenerator(FieldDescriptor descriptor)
- : base(descriptor) {
- if (Descriptor.ExtensionScope != null) {
- scope = GetClassName(Descriptor.ExtensionScope);
- } else {
- scope = DescriptorUtil.GetFullUmbrellaClassName(Descriptor.File);
- }
- switch (Descriptor.MappedType) {
- case MappedType.Message:
- type = GetClassName(Descriptor.MessageType);
- break;
- case MappedType.Enum:
- type = GetClassName(Descriptor.EnumType);
- break;
- default:
- type = DescriptorUtil.GetMappedTypeName(Descriptor.MappedType);
- break;
- }
- extends = GetClassName(Descriptor.ContainingType);
- name = Descriptor.CSharpOptions.PropertyName;
- }
-
- public void Generate(TextGenerator writer) {
- writer.WriteLine("public const int {0} = {1};", GetFieldConstantName(Descriptor), Descriptor.FieldNumber);
-
- if (UseLiteRuntime) {
- if (Descriptor.MappedType == MappedType.Message && Descriptor.MessageType.Options.MessageSetWireFormat) {
- throw new ArgumentException("option message_set_wire_format = true; is not supported in Lite runtime extensions.");
- }
- if (!Descriptor.IsCLSCompliant && Descriptor.File.CSharpOptions.ClsCompliance) {
- writer.WriteLine("[global::System.CLSCompliant(false)]");
- }
- writer.WriteLine("{0} static pb::{4}<{1}, {2}> {3};", ClassAccessLevel, extends, type, name,
- Descriptor.IsRepeated ? "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite");
- } else if (Descriptor.IsRepeated) {
- if (!Descriptor.IsCLSCompliant && Descriptor.File.CSharpOptions.ClsCompliance) {
- writer.WriteLine("[global::System.CLSCompliant(false)]");
- }
- writer.WriteLine("{0} static pb::GeneratedExtensionBase<scg::IList<{1}>> {2};", ClassAccessLevel, type, name);
- } else {
- if (!Descriptor.IsCLSCompliant && Descriptor.File.CSharpOptions.ClsCompliance) {
- writer.WriteLine("[global::System.CLSCompliant(false)]");
- }
- writer.WriteLine("{0} static pb::GeneratedExtensionBase<{1}> {2};", ClassAccessLevel, type, name);
- }
- }
-
- internal void GenerateStaticVariableInitializers(TextGenerator writer) {
- if (UseLiteRuntime) {
- writer.WriteLine("{0}.{1} = ", scope, name);
- writer.Indent();
- writer.WriteLine("new pb::{0}<{1}, {2}>(", Descriptor.IsRepeated ? "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite", extends, type);
- writer.Indent();
- writer.WriteLine("\"{0}\",", Descriptor.FullName);
- writer.WriteLine("{0}.DefaultInstance,", extends);
- if(!Descriptor.IsRepeated)
- writer.WriteLine("{0},", Descriptor.HasDefaultValue ? DefaultValue : IsNullableType ? "null" : "default(" + type + ")");
- writer.WriteLine("{0},", (Descriptor.MappedType == MappedType.Message) ? type + ".DefaultInstance" : "null");
- writer.WriteLine("{0},", (Descriptor.MappedType == MappedType.Enum) ? "new EnumLiteMap<" + type + ">()" : "null");
- writer.WriteLine("{0}.{1}FieldNumber,", scope, name);
- writer.Write("pbd::FieldType.{0}", Descriptor.FieldType);
- if (Descriptor.IsRepeated) {
- writer.WriteLine(",");
- writer.Write(Descriptor.IsPacked ? "true" : "false");
- }
- writer.Outdent();
- writer.WriteLine(");");
- writer.Outdent();
- } else if (Descriptor.IsRepeated) {
- writer.WriteLine("{0}.{1} = pb::GeneratedRepeatExtension<{2}>.CreateInstance({0}.Descriptor.Extensions[{3}]);", scope, name, type, Descriptor.Index);
- } else {
- writer.WriteLine("{0}.{1} = pb::GeneratedSingleExtension<{2}>.CreateInstance({0}.Descriptor.Extensions[{3}]);", scope, name, type, Descriptor.Index);
- }
- }
-
- internal void GenerateExtensionRegistrationCode(TextGenerator writer) {
- writer.WriteLine("registry.Add({0}.{1});", scope, name);
- }
-
- public override void WriteHash(TextGenerator writer) {
- }
-
- public override void WriteEquals(TextGenerator writer) {
- }
-
- public override void WriteToString(TextGenerator writer) {
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Globalization;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal class ExtensionGenerator : FieldGeneratorBase, ISourceGenerator
+ {
+ private readonly string extends;
+ private readonly string scope;
+ private readonly string type;
+ private readonly string name;
+
+ internal ExtensionGenerator(FieldDescriptor descriptor)
+ : base(descriptor)
+ {
+ if (Descriptor.ExtensionScope != null)
+ {
+ scope = GetClassName(Descriptor.ExtensionScope);
+ }
+ else
+ {
+ scope = DescriptorUtil.GetFullUmbrellaClassName(Descriptor.File);
+ }
+ switch (Descriptor.MappedType)
+ {
+ case MappedType.Message:
+ type = GetClassName(Descriptor.MessageType);
+ break;
+ case MappedType.Enum:
+ type = GetClassName(Descriptor.EnumType);
+ break;
+ default:
+ type = DescriptorUtil.GetMappedTypeName(Descriptor.MappedType);
+ break;
+ }
+ extends = GetClassName(Descriptor.ContainingType);
+ name = Descriptor.CSharpOptions.PropertyName;
+ }
+
+ public void Generate(TextGenerator writer)
+ {
+ writer.WriteLine("public const int {0} = {1};", GetFieldConstantName(Descriptor), Descriptor.FieldNumber);
+
+ if (UseLiteRuntime)
+ {
+ if (Descriptor.MappedType == MappedType.Message && Descriptor.MessageType.Options.MessageSetWireFormat)
+ {
+ throw new ArgumentException(
+ "option message_set_wire_format = true; is not supported in Lite runtime extensions.");
+ }
+ if (!Descriptor.IsCLSCompliant && Descriptor.File.CSharpOptions.ClsCompliance)
+ {
+ writer.WriteLine("[global::System.CLSCompliant(false)]");
+ }
+ writer.WriteLine("{0} static pb::{4}<{1}, {2}> {3};", ClassAccessLevel, extends, type, name,
+ Descriptor.IsRepeated ? "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite");
+ }
+ else if (Descriptor.IsRepeated)
+ {
+ if (!Descriptor.IsCLSCompliant && Descriptor.File.CSharpOptions.ClsCompliance)
+ {
+ writer.WriteLine("[global::System.CLSCompliant(false)]");
+ }
+ writer.WriteLine("{0} static pb::GeneratedExtensionBase<scg::IList<{1}>> {2};", ClassAccessLevel, type,
+ name);
+ }
+ else
+ {
+ if (!Descriptor.IsCLSCompliant && Descriptor.File.CSharpOptions.ClsCompliance)
+ {
+ writer.WriteLine("[global::System.CLSCompliant(false)]");
+ }
+ writer.WriteLine("{0} static pb::GeneratedExtensionBase<{1}> {2};", ClassAccessLevel, type, name);
+ }
+ }
+
+ internal void GenerateStaticVariableInitializers(TextGenerator writer)
+ {
+ if (UseLiteRuntime)
+ {
+ writer.WriteLine("{0}.{1} = ", scope, name);
+ writer.Indent();
+ writer.WriteLine("new pb::{0}<{1}, {2}>(",
+ Descriptor.IsRepeated ? "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite",
+ extends, type);
+ writer.Indent();
+ writer.WriteLine("\"{0}\",", Descriptor.FullName);
+ writer.WriteLine("{0}.DefaultInstance,", extends);
+ if (!Descriptor.IsRepeated)
+ writer.WriteLine("{0},",
+ Descriptor.HasDefaultValue
+ ? DefaultValue
+ : IsNullableType ? "null" : "default(" + type + ")");
+ writer.WriteLine("{0},",
+ (Descriptor.MappedType == MappedType.Message) ? type + ".DefaultInstance" : "null");
+ writer.WriteLine("{0},",
+ (Descriptor.MappedType == MappedType.Enum) ? "new EnumLiteMap<" + type + ">()" : "null");
+ writer.WriteLine("{0}.{1}FieldNumber,", scope, name);
+ writer.Write("pbd::FieldType.{0}", Descriptor.FieldType);
+ if (Descriptor.IsRepeated)
+ {
+ writer.WriteLine(",");
+ writer.Write(Descriptor.IsPacked ? "true" : "false");
+ }
+ writer.Outdent();
+ writer.WriteLine(");");
+ writer.Outdent();
+ }
+ else if (Descriptor.IsRepeated)
+ {
+ writer.WriteLine(
+ "{0}.{1} = pb::GeneratedRepeatExtension<{2}>.CreateInstance({0}.Descriptor.Extensions[{3}]);", scope,
+ name, type, Descriptor.Index);
+ }
+ else
+ {
+ writer.WriteLine(
+ "{0}.{1} = pb::GeneratedSingleExtension<{2}>.CreateInstance({0}.Descriptor.Extensions[{3}]);", scope,
+ name, type, Descriptor.Index);
+ }
+ }
+
+ internal void GenerateExtensionRegistrationCode(TextGenerator writer)
+ {
+ writer.WriteLine("registry.Add({0}.{1});", scope, name);
+ }
+
+ public override void WriteHash(TextGenerator writer)
+ {
+ }
+
+ public override void WriteEquals(TextGenerator writer)
+ {
+ }
+
+ public override void WriteToString(TextGenerator writer)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/FieldGeneratorBase.cs b/src/ProtoGen/FieldGeneratorBase.cs
index 45a096a0..c4f5dbf4 100644
--- a/src/ProtoGen/FieldGeneratorBase.cs
+++ b/src/ProtoGen/FieldGeneratorBase.cs
@@ -1,268 +1,316 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System;
-using System.Globalization;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal abstract class FieldGeneratorBase : SourceGeneratorBase<FieldDescriptor> {
- protected FieldGeneratorBase(FieldDescriptor descriptor)
- : base(descriptor) {
- }
-
- public abstract void WriteHash(TextGenerator writer);
- public abstract void WriteEquals(TextGenerator writer);
- public abstract void WriteToString(TextGenerator writer);
-
- private static bool AllPrintableAscii(string text) {
- foreach (char c in text) {
- if (c < 0x20 || c > 0x7e) {
- return false;
- }
- }
- return true;
- }
-
- /// <remarks>Copy exists in ExtensionGenerator.cs</remarks>
- protected string DefaultValue {
- get {
- string suffix = "";
- switch (Descriptor.FieldType) {
- case FieldType.Float: suffix = "F"; break;
- case FieldType.Double: suffix = "D"; break;
- case FieldType.Int64: suffix = "L"; break;
- case FieldType.UInt64: suffix = "UL"; break;
- }
- switch (Descriptor.FieldType) {
- case FieldType.Float:
- case FieldType.Double:
- case FieldType.Int32:
- case FieldType.Int64:
- case FieldType.SInt32:
- case FieldType.SInt64:
- case FieldType.SFixed32:
- case FieldType.SFixed64:
- case FieldType.UInt32:
- case FieldType.UInt64:
- case FieldType.Fixed32:
- case FieldType.Fixed64:
- {
- // The simple Object.ToString converts using the current culture.
- // We want to always use the invariant culture so it's predictable.
- IConvertible value = (IConvertible) Descriptor.DefaultValue;
- //a few things that must be handled explicitly
- if (Descriptor.FieldType == FieldType.Double && value is double) {
- if (double.IsNaN((double) value))
- return "double.NaN";
- if (double.IsPositiveInfinity((double) value))
- return "double.PositiveInfinity";
- if (double.IsNegativeInfinity((double) value))
- return "double.NegativeInfinity";
- }
- else if (Descriptor.FieldType == FieldType.Float && value is float) {
- if (float.IsNaN((float)value))
- return "float.NaN";
- if (float.IsPositiveInfinity((float)value))
- return "float.PositiveInfinity";
- if (float.IsNegativeInfinity((float)value))
- return "float.NegativeInfinity";
- }
- return value.ToString(CultureInfo.InvariantCulture) + suffix;
- }
- case FieldType.Bool:
- return (bool) Descriptor.DefaultValue ? "true" : "false";
-
- case FieldType.Bytes:
- if (!Descriptor.HasDefaultValue) {
- return "pb::ByteString.Empty";
- }
- if (UseLiteRuntime && Descriptor.DefaultValue is ByteString) {
- string temp = Convert.ToBase64String(((ByteString)Descriptor.DefaultValue).ToByteArray());
- return String.Format("ByteString.FromBase64(\"{0}\")", temp);
- }
- return string.Format("(pb::ByteString) {0}.Descriptor.Fields[{1}].DefaultValue", GetClassName(Descriptor.ContainingType), Descriptor.Index);
- case FieldType.String:
- if (AllPrintableAscii(Descriptor.Proto.DefaultValue)) {
- // All chars are ASCII and printable. In this case we only
- // need to escape quotes and backslashes.
- return "\"" + Descriptor.Proto.DefaultValue
- .Replace("\\", "\\\\")
- .Replace("'", "\\'")
- .Replace("\"", "\\\"")
- + "\"";
- }
- if (UseLiteRuntime && Descriptor.DefaultValue is String) {
- string temp = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes((String)Descriptor.DefaultValue));
- return String.Format("ByteString.FromBase64(\"{0}\").ToStringUtf8()", temp);
- }
- return string.Format("(string) {0}.Descriptor.Fields[{1}].DefaultValue", GetClassName(Descriptor.ContainingType), Descriptor.Index);
- case FieldType.Enum:
- return TypeName + "." + ((EnumValueDescriptor) Descriptor.DefaultValue).Name;
- case FieldType.Message:
- case FieldType.Group:
- return TypeName + ".DefaultInstance";
- default:
- throw new InvalidOperationException("Invalid field descriptor type");
- }
- }
- }
-
- protected string PropertyName {
- get {
- return Descriptor.CSharpOptions.PropertyName;
- }
- }
-
- protected string Name {
- get { return NameHelpers.UnderscoresToCamelCase(GetFieldName(Descriptor)); }
- }
-
- protected int Number {
- get { return Descriptor.FieldNumber; }
- }
-
- protected void AddNullCheck(TextGenerator writer) {
- AddNullCheck(writer, "value");
- }
-
- protected void AddNullCheck(TextGenerator writer, string name) {
- if (IsNullableType) {
- writer.WriteLine(" pb::ThrowHelper.ThrowIfNull({0}, \"{0}\");", name);
- }
- }
-
- protected void AddClsComplianceCheck(TextGenerator writer) {
- if (!Descriptor.IsCLSCompliant && Descriptor.File.CSharpOptions.ClsCompliance) {
- writer.WriteLine("[global::System.CLSCompliant(false)]");
- }
- }
-
- /// <summary>
- /// For encodings with fixed sizes, returns that size in bytes. Otherwise
- /// returns -1. TODO(jonskeet): Make this less ugly.
- /// </summary>
- protected int FixedSize {
- get {
- switch (Descriptor.FieldType) {
- case FieldType.UInt32:
- case FieldType.UInt64:
- case FieldType.Int32:
- case FieldType.Int64:
- case FieldType.SInt32:
- case FieldType.SInt64:
- case FieldType.Enum:
- case FieldType.Bytes:
- case FieldType.String:
- case FieldType.Message:
- case FieldType.Group:
- return -1;
- case FieldType.Float:
- return WireFormat.FloatSize;
- case FieldType.SFixed32:
- return WireFormat.SFixed32Size;
- case FieldType.Fixed32:
- return WireFormat.Fixed32Size;
- case FieldType.Double:
- return WireFormat.DoubleSize;
- case FieldType.SFixed64:
- return WireFormat.SFixed64Size;
- case FieldType.Fixed64:
- return WireFormat.Fixed64Size;
- case FieldType.Bool:
- return WireFormat.BoolSize;
- default:
- throw new InvalidOperationException("Invalid field descriptor type");
- }
- }
- }
-
- protected bool IsNullableType {
- get {
- switch (Descriptor.FieldType) {
- case FieldType.Float:
- case FieldType.Double:
- case FieldType.Int32:
- case FieldType.Int64:
- case FieldType.SInt32:
- case FieldType.SInt64:
- case FieldType.SFixed32:
- case FieldType.SFixed64:
- case FieldType.UInt32:
- case FieldType.UInt64:
- case FieldType.Fixed32:
- case FieldType.Fixed64:
- case FieldType.Bool:
- case FieldType.Enum:
- return false;
- case FieldType.Bytes:
- case FieldType.String:
- case FieldType.Message:
- case FieldType.Group:
- return true;
- default:
- throw new InvalidOperationException("Invalid field descriptor type");
- }
- }
- }
-
- protected string TypeName {
- get {
- switch (Descriptor.FieldType) {
- case FieldType.Enum:
- return GetClassName(Descriptor.EnumType);
- case FieldType.Message:
- case FieldType.Group:
- return GetClassName(Descriptor.MessageType);
- default:
- return DescriptorUtil.GetMappedTypeName(Descriptor.MappedType);
- }
- }
- }
-
- protected string MessageOrGroup {
- get { return Descriptor.FieldType == FieldType.Group ? "Group" : "Message"; }
- }
-
- /// <summary>
- /// Returns the type name as used in CodedInputStream method names: SFixed32, UInt32 etc.
- /// </summary>
- protected string CapitalizedTypeName {
- get {
- // Our enum names match perfectly. How serendipitous.
- return Descriptor.FieldType.ToString();
- }
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Globalization;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal abstract class FieldGeneratorBase : SourceGeneratorBase<FieldDescriptor>
+ {
+ protected FieldGeneratorBase(FieldDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
+
+ public abstract void WriteHash(TextGenerator writer);
+ public abstract void WriteEquals(TextGenerator writer);
+ public abstract void WriteToString(TextGenerator writer);
+
+ private static bool AllPrintableAscii(string text)
+ {
+ foreach (char c in text)
+ {
+ if (c < 0x20 || c > 0x7e)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// <remarks>Copy exists in ExtensionGenerator.cs</remarks>
+ protected string DefaultValue
+ {
+ get
+ {
+ string suffix = "";
+ switch (Descriptor.FieldType)
+ {
+ case FieldType.Float:
+ suffix = "F";
+ break;
+ case FieldType.Double:
+ suffix = "D";
+ break;
+ case FieldType.Int64:
+ suffix = "L";
+ break;
+ case FieldType.UInt64:
+ suffix = "UL";
+ break;
+ }
+ switch (Descriptor.FieldType)
+ {
+ case FieldType.Float:
+ case FieldType.Double:
+ case FieldType.Int32:
+ case FieldType.Int64:
+ case FieldType.SInt32:
+ case FieldType.SInt64:
+ case FieldType.SFixed32:
+ case FieldType.SFixed64:
+ case FieldType.UInt32:
+ case FieldType.UInt64:
+ case FieldType.Fixed32:
+ case FieldType.Fixed64:
+ {
+ // The simple Object.ToString converts using the current culture.
+ // We want to always use the invariant culture so it's predictable.
+ IConvertible value = (IConvertible) Descriptor.DefaultValue;
+ //a few things that must be handled explicitly
+ if (Descriptor.FieldType == FieldType.Double && value is double)
+ {
+ if (double.IsNaN((double) value))
+ return "double.NaN";
+ if (double.IsPositiveInfinity((double) value))
+ return "double.PositiveInfinity";
+ if (double.IsNegativeInfinity((double) value))
+ return "double.NegativeInfinity";
+ }
+ else if (Descriptor.FieldType == FieldType.Float && value is float)
+ {
+ if (float.IsNaN((float) value))
+ return "float.NaN";
+ if (float.IsPositiveInfinity((float) value))
+ return "float.PositiveInfinity";
+ if (float.IsNegativeInfinity((float) value))
+ return "float.NegativeInfinity";
+ }
+ return value.ToString(CultureInfo.InvariantCulture) + suffix;
+ }
+ case FieldType.Bool:
+ return (bool) Descriptor.DefaultValue ? "true" : "false";
+
+ case FieldType.Bytes:
+ if (!Descriptor.HasDefaultValue)
+ {
+ return "pb::ByteString.Empty";
+ }
+ if (UseLiteRuntime && Descriptor.DefaultValue is ByteString)
+ {
+ string temp = Convert.ToBase64String(((ByteString) Descriptor.DefaultValue).ToByteArray());
+ return String.Format("ByteString.FromBase64(\"{0}\")", temp);
+ }
+ return string.Format("(pb::ByteString) {0}.Descriptor.Fields[{1}].DefaultValue",
+ GetClassName(Descriptor.ContainingType), Descriptor.Index);
+ case FieldType.String:
+ if (AllPrintableAscii(Descriptor.Proto.DefaultValue))
+ {
+ // All chars are ASCII and printable. In this case we only
+ // need to escape quotes and backslashes.
+ return "\"" + Descriptor.Proto.DefaultValue
+ .Replace("\\", "\\\\")
+ .Replace("'", "\\'")
+ .Replace("\"", "\\\"")
+ + "\"";
+ }
+ if (UseLiteRuntime && Descriptor.DefaultValue is String)
+ {
+ string temp =
+ Convert.ToBase64String(
+ System.Text.Encoding.UTF8.GetBytes((String) Descriptor.DefaultValue));
+ return String.Format("ByteString.FromBase64(\"{0}\").ToStringUtf8()", temp);
+ }
+ return string.Format("(string) {0}.Descriptor.Fields[{1}].DefaultValue",
+ GetClassName(Descriptor.ContainingType), Descriptor.Index);
+ case FieldType.Enum:
+ return TypeName + "." + ((EnumValueDescriptor) Descriptor.DefaultValue).Name;
+ case FieldType.Message:
+ case FieldType.Group:
+ return TypeName + ".DefaultInstance";
+ default:
+ throw new InvalidOperationException("Invalid field descriptor type");
+ }
+ }
+ }
+
+ protected string PropertyName
+ {
+ get { return Descriptor.CSharpOptions.PropertyName; }
+ }
+
+ protected string Name
+ {
+ get { return NameHelpers.UnderscoresToCamelCase(GetFieldName(Descriptor)); }
+ }
+
+ protected int Number
+ {
+ get { return Descriptor.FieldNumber; }
+ }
+
+ protected void AddNullCheck(TextGenerator writer)
+ {
+ AddNullCheck(writer, "value");
+ }
+
+ protected void AddNullCheck(TextGenerator writer, string name)
+ {
+ if (IsNullableType)
+ {
+ writer.WriteLine(" pb::ThrowHelper.ThrowIfNull({0}, \"{0}\");", name);
+ }
+ }
+
+ protected void AddClsComplianceCheck(TextGenerator writer)
+ {
+ if (!Descriptor.IsCLSCompliant && Descriptor.File.CSharpOptions.ClsCompliance)
+ {
+ writer.WriteLine("[global::System.CLSCompliant(false)]");
+ }
+ }
+
+ /// <summary>
+ /// For encodings with fixed sizes, returns that size in bytes. Otherwise
+ /// returns -1. TODO(jonskeet): Make this less ugly.
+ /// </summary>
+ protected int FixedSize
+ {
+ get
+ {
+ switch (Descriptor.FieldType)
+ {
+ case FieldType.UInt32:
+ case FieldType.UInt64:
+ case FieldType.Int32:
+ case FieldType.Int64:
+ case FieldType.SInt32:
+ case FieldType.SInt64:
+ case FieldType.Enum:
+ case FieldType.Bytes:
+ case FieldType.String:
+ case FieldType.Message:
+ case FieldType.Group:
+ return -1;
+ case FieldType.Float:
+ return WireFormat.FloatSize;
+ case FieldType.SFixed32:
+ return WireFormat.SFixed32Size;
+ case FieldType.Fixed32:
+ return WireFormat.Fixed32Size;
+ case FieldType.Double:
+ return WireFormat.DoubleSize;
+ case FieldType.SFixed64:
+ return WireFormat.SFixed64Size;
+ case FieldType.Fixed64:
+ return WireFormat.Fixed64Size;
+ case FieldType.Bool:
+ return WireFormat.BoolSize;
+ default:
+ throw new InvalidOperationException("Invalid field descriptor type");
+ }
+ }
+ }
+
+ protected bool IsNullableType
+ {
+ get
+ {
+ switch (Descriptor.FieldType)
+ {
+ case FieldType.Float:
+ case FieldType.Double:
+ case FieldType.Int32:
+ case FieldType.Int64:
+ case FieldType.SInt32:
+ case FieldType.SInt64:
+ case FieldType.SFixed32:
+ case FieldType.SFixed64:
+ case FieldType.UInt32:
+ case FieldType.UInt64:
+ case FieldType.Fixed32:
+ case FieldType.Fixed64:
+ case FieldType.Bool:
+ case FieldType.Enum:
+ return false;
+ case FieldType.Bytes:
+ case FieldType.String:
+ case FieldType.Message:
+ case FieldType.Group:
+ return true;
+ default:
+ throw new InvalidOperationException("Invalid field descriptor type");
+ }
+ }
+ }
+
+ protected string TypeName
+ {
+ get
+ {
+ switch (Descriptor.FieldType)
+ {
+ case FieldType.Enum:
+ return GetClassName(Descriptor.EnumType);
+ case FieldType.Message:
+ case FieldType.Group:
+ return GetClassName(Descriptor.MessageType);
+ default:
+ return DescriptorUtil.GetMappedTypeName(Descriptor.MappedType);
+ }
+ }
+ }
+
+ protected string MessageOrGroup
+ {
+ get { return Descriptor.FieldType == FieldType.Group ? "Group" : "Message"; }
+ }
+
+ /// <summary>
+ /// Returns the type name as used in CodedInputStream method names: SFixed32, UInt32 etc.
+ /// </summary>
+ protected string CapitalizedTypeName
+ {
+ get
+ {
+ // Our enum names match perfectly. How serendipitous.
+ return Descriptor.FieldType.ToString();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/Generator.cs b/src/ProtoGen/Generator.cs
index 13797487..a3c6a504 100644
--- a/src/ProtoGen/Generator.cs
+++ b/src/ProtoGen/Generator.cs
@@ -1,209 +1,246 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System.Collections.Generic;
-using System.Text;
-using Google.ProtocolBuffers.DescriptorProtos;
-using System.IO;
-using Google.ProtocolBuffers.Descriptors;
-using Google.ProtocolBuffers.Collections;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- /// <summary>
- /// Code generator for protocol buffers. Only C# is supported at the moment.
- /// </summary>
- public sealed class Generator {
-
- private readonly GeneratorOptions options;
-
- private Generator(GeneratorOptions options) {
- options.Validate();
- this.options = options;
- }
-
- /// <summary>
- /// Returns a generator configured with the specified options.
- /// </summary>
- public static Generator CreateGenerator(GeneratorOptions options) {
- return new Generator(options);
- }
-
- public void Generate() {
- List<FileDescriptorSet> descriptorProtos = new List<FileDescriptorSet>();
- foreach (string inputFile in options.InputFiles) {
- ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
- CSharpOptions.RegisterAllExtensions(extensionRegistry);
- using (Stream inputStream = File.OpenRead(inputFile)) {
- descriptorProtos.Add(FileDescriptorSet.ParseFrom(inputStream, extensionRegistry));
- }
- }
-
- IList<FileDescriptor> descriptors = ConvertDescriptors(options.FileOptions, descriptorProtos.ToArray());
-
- // Combine with options from command line
- foreach (FileDescriptor descriptor in descriptors) {
- descriptor.ConfigureWithDefaultOptions(options.FileOptions);
- }
-
- foreach (FileDescriptor descriptor in descriptors) {
- // Optionally exclude descriptors in google.protobuf
- if (descriptor.CSharpOptions.IgnoreGoogleProtobuf && descriptor.Package == "google.protobuf") {
- continue;
- }
- Generate(descriptor);
- }
- }
-
- /// <summary>
- /// Generates code for a particular file. All dependencies must
- /// already have been resolved.
- /// </summary>
- private void Generate(FileDescriptor descriptor) {
- UmbrellaClassGenerator ucg = new UmbrellaClassGenerator(descriptor);
- using (TextWriter textWriter = File.CreateText(GetOutputFile(descriptor))) {
- TextGenerator writer = new TextGenerator(textWriter, options.LineBreak);
- ucg.Generate(writer);
- }
- }
-
- private string GetOutputFile(FileDescriptor descriptor) {
- CSharpFileOptions fileOptions = descriptor.CSharpOptions;
-
- string filename = descriptor.CSharpOptions.UmbrellaClassname + descriptor.CSharpOptions.FileExtension;
-
- string outputDirectory = descriptor.CSharpOptions.OutputDirectory;
- if (fileOptions.ExpandNamespaceDirectories) {
- string package = fileOptions.Namespace;
- if (!string.IsNullOrEmpty(package)) {
- string[] bits = package.Split('.');
- foreach (string bit in bits) {
- outputDirectory = Path.Combine(outputDirectory, bit);
- }
- }
- }
-
- // As the directory can be explicitly specified in options, we need to make sure it exists
- Directory.CreateDirectory(outputDirectory);
- return Path.Combine(outputDirectory, filename);
- }
-
- /// <summary>
- /// Resolves any dependencies and converts FileDescriptorProtos into FileDescriptors.
- /// The list returned is in the same order as the protos are listed in the descriptor set.
- /// Note: this method is internal rather than private to allow testing.
- /// </summary>
- /// <exception cref="DependencyResolutionException">Not all dependencies could be resolved.</exception>
- public static IList<FileDescriptor> ConvertDescriptors(CSharpFileOptions options, params FileDescriptorSet[] descriptorProtos) {
- // Simple strategy: Keep going through the list of protos to convert, only doing ones where
- // we've already converted all the dependencies, until we get to a stalemate
- List<FileDescriptorProto> fileList = new List<FileDescriptorProto>();
- foreach (FileDescriptorSet set in descriptorProtos)
- fileList.AddRange(set.FileList);
-
- FileDescriptor[] converted = new FileDescriptor[fileList.Count];
-
- Dictionary<string, FileDescriptor> convertedMap = new Dictionary<string, FileDescriptor>();
-
- int totalConverted = 0;
-
- bool madeProgress = true;
- while (madeProgress && totalConverted < converted.Length) {
- madeProgress = false;
- for (int i = 0; i < converted.Length; i++) {
- if (converted[i] != null) {
- // Already done this one
- continue;
- }
- FileDescriptorProto candidate = fileList[i];
- FileDescriptor[] dependencies = new FileDescriptor[candidate.DependencyList.Count];
-
-
- CSharpFileOptions.Builder builder = options.ToBuilder();
- if (candidate.Options.HasExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions)) {
- builder.MergeFrom(candidate.Options.GetExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions));
- }
- CSharpFileOptions localOptions = builder.Build();
-
- bool foundAllDependencies = true;
- for (int j = 0; j < dependencies.Length; j++) {
- if (!convertedMap.TryGetValue(candidate.DependencyList[j], out dependencies[j])) {
- // We can auto-magically resolve these since we already have their description
- // This way if the file is only referencing options it does not need to be built with the
- // --include_imports definition.
- if (localOptions.IgnoreGoogleProtobuf && (candidate.DependencyList[j] == "google/protobuf/csharp_options.proto")) {
- dependencies[j] = CSharpOptions.Descriptor;
- continue;
- }
- if (localOptions.IgnoreGoogleProtobuf && (candidate.DependencyList[j] == "google/protobuf/descriptor.proto")) {
- dependencies[j] = DescriptorProtoFile.Descriptor;
- continue;
- }
- foundAllDependencies = false;
- break;
- }
- }
- if (!foundAllDependencies) {
- continue;
- }
- madeProgress = true;
- totalConverted++;
- converted[i] = FileDescriptor.BuildFrom(candidate, dependencies);
- convertedMap[candidate.Name] = converted[i];
- }
- }
- if (!madeProgress) {
- StringBuilder remaining = new StringBuilder();
- for (int i = 0; i < converted.Length; i++) {
- if (converted[i] == null) {
- if (remaining.Length != 0) {
- remaining.Append(", ");
- }
- FileDescriptorProto failure = fileList[i];
- remaining.Append(failure.Name);
- remaining.Append(":");
- foreach (string dependency in failure.DependencyList) {
- if (!convertedMap.ContainsKey(dependency)) {
- remaining.Append(" ");
- remaining.Append(dependency);
- }
- }
- remaining.Append(";");
- }
- }
- throw new DependencyResolutionException("Unable to resolve all dependencies: " + remaining);
- }
- return Lists.AsReadOnly(converted);
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System.Collections.Generic;
+using System.Text;
+using Google.ProtocolBuffers.DescriptorProtos;
+using System.IO;
+using Google.ProtocolBuffers.Descriptors;
+using Google.ProtocolBuffers.Collections;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ /// <summary>
+ /// Code generator for protocol buffers. Only C# is supported at the moment.
+ /// </summary>
+ public sealed class Generator
+ {
+ private readonly GeneratorOptions options;
+
+ private Generator(GeneratorOptions options)
+ {
+ options.Validate();
+ this.options = options;
+ }
+
+ /// <summary>
+ /// Returns a generator configured with the specified options.
+ /// </summary>
+ public static Generator CreateGenerator(GeneratorOptions options)
+ {
+ return new Generator(options);
+ }
+
+ public void Generate()
+ {
+ List<FileDescriptorSet> descriptorProtos = new List<FileDescriptorSet>();
+ foreach (string inputFile in options.InputFiles)
+ {
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
+ CSharpOptions.RegisterAllExtensions(extensionRegistry);
+ using (Stream inputStream = File.OpenRead(inputFile))
+ {
+ descriptorProtos.Add(FileDescriptorSet.ParseFrom(inputStream, extensionRegistry));
+ }
+ }
+
+ IList<FileDescriptor> descriptors = ConvertDescriptors(options.FileOptions, descriptorProtos.ToArray());
+
+ // Combine with options from command line
+ foreach (FileDescriptor descriptor in descriptors)
+ {
+ descriptor.ConfigureWithDefaultOptions(options.FileOptions);
+ }
+
+ foreach (FileDescriptor descriptor in descriptors)
+ {
+ // Optionally exclude descriptors in google.protobuf
+ if (descriptor.CSharpOptions.IgnoreGoogleProtobuf && descriptor.Package == "google.protobuf")
+ {
+ continue;
+ }
+ Generate(descriptor);
+ }
+ }
+
+ /// <summary>
+ /// Generates code for a particular file. All dependencies must
+ /// already have been resolved.
+ /// </summary>
+ private void Generate(FileDescriptor descriptor)
+ {
+ UmbrellaClassGenerator ucg = new UmbrellaClassGenerator(descriptor);
+ using (TextWriter textWriter = File.CreateText(GetOutputFile(descriptor)))
+ {
+ TextGenerator writer = new TextGenerator(textWriter, options.LineBreak);
+ ucg.Generate(writer);
+ }
+ }
+
+ private string GetOutputFile(FileDescriptor descriptor)
+ {
+ CSharpFileOptions fileOptions = descriptor.CSharpOptions;
+
+ string filename = descriptor.CSharpOptions.UmbrellaClassname + descriptor.CSharpOptions.FileExtension;
+
+ string outputDirectory = descriptor.CSharpOptions.OutputDirectory;
+ if (fileOptions.ExpandNamespaceDirectories)
+ {
+ string package = fileOptions.Namespace;
+ if (!string.IsNullOrEmpty(package))
+ {
+ string[] bits = package.Split('.');
+ foreach (string bit in bits)
+ {
+ outputDirectory = Path.Combine(outputDirectory, bit);
+ }
+ }
+ }
+
+ // As the directory can be explicitly specified in options, we need to make sure it exists
+ Directory.CreateDirectory(outputDirectory);
+ return Path.Combine(outputDirectory, filename);
+ }
+
+ /// <summary>
+ /// Resolves any dependencies and converts FileDescriptorProtos into FileDescriptors.
+ /// The list returned is in the same order as the protos are listed in the descriptor set.
+ /// Note: this method is internal rather than private to allow testing.
+ /// </summary>
+ /// <exception cref="DependencyResolutionException">Not all dependencies could be resolved.</exception>
+ public static IList<FileDescriptor> ConvertDescriptors(CSharpFileOptions options,
+ params FileDescriptorSet[] descriptorProtos)
+ {
+ // Simple strategy: Keep going through the list of protos to convert, only doing ones where
+ // we've already converted all the dependencies, until we get to a stalemate
+ List<FileDescriptorProto> fileList = new List<FileDescriptorProto>();
+ foreach (FileDescriptorSet set in descriptorProtos)
+ fileList.AddRange(set.FileList);
+
+ FileDescriptor[] converted = new FileDescriptor[fileList.Count];
+
+ Dictionary<string, FileDescriptor> convertedMap = new Dictionary<string, FileDescriptor>();
+
+ int totalConverted = 0;
+
+ bool madeProgress = true;
+ while (madeProgress && totalConverted < converted.Length)
+ {
+ madeProgress = false;
+ for (int i = 0; i < converted.Length; i++)
+ {
+ if (converted[i] != null)
+ {
+ // Already done this one
+ continue;
+ }
+ FileDescriptorProto candidate = fileList[i];
+ FileDescriptor[] dependencies = new FileDescriptor[candidate.DependencyList.Count];
+
+
+ CSharpFileOptions.Builder builder = options.ToBuilder();
+ if (candidate.Options.HasExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions))
+ {
+ builder.MergeFrom(
+ candidate.Options.GetExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions));
+ }
+ CSharpFileOptions localOptions = builder.Build();
+
+ bool foundAllDependencies = true;
+ for (int j = 0; j < dependencies.Length; j++)
+ {
+ if (!convertedMap.TryGetValue(candidate.DependencyList[j], out dependencies[j]))
+ {
+ // We can auto-magically resolve these since we already have their description
+ // This way if the file is only referencing options it does not need to be built with the
+ // --include_imports definition.
+ if (localOptions.IgnoreGoogleProtobuf &&
+ (candidate.DependencyList[j] == "google/protobuf/csharp_options.proto"))
+ {
+ dependencies[j] = CSharpOptions.Descriptor;
+ continue;
+ }
+ if (localOptions.IgnoreGoogleProtobuf &&
+ (candidate.DependencyList[j] == "google/protobuf/descriptor.proto"))
+ {
+ dependencies[j] = DescriptorProtoFile.Descriptor;
+ continue;
+ }
+ foundAllDependencies = false;
+ break;
+ }
+ }
+ if (!foundAllDependencies)
+ {
+ continue;
+ }
+ madeProgress = true;
+ totalConverted++;
+ converted[i] = FileDescriptor.BuildFrom(candidate, dependencies);
+ convertedMap[candidate.Name] = converted[i];
+ }
+ }
+ if (!madeProgress)
+ {
+ StringBuilder remaining = new StringBuilder();
+ for (int i = 0; i < converted.Length; i++)
+ {
+ if (converted[i] == null)
+ {
+ if (remaining.Length != 0)
+ {
+ remaining.Append(", ");
+ }
+ FileDescriptorProto failure = fileList[i];
+ remaining.Append(failure.Name);
+ remaining.Append(":");
+ foreach (string dependency in failure.DependencyList)
+ {
+ if (!convertedMap.ContainsKey(dependency))
+ {
+ remaining.Append(" ");
+ remaining.Append(dependency);
+ }
+ }
+ remaining.Append(";");
+ }
+ }
+ throw new DependencyResolutionException("Unable to resolve all dependencies: " + remaining);
+ }
+ return Lists.AsReadOnly(converted);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/GeneratorOptions.cs b/src/ProtoGen/GeneratorOptions.cs
index 05317724..ec500d82 100644
--- a/src/ProtoGen/GeneratorOptions.cs
+++ b/src/ProtoGen/GeneratorOptions.cs
@@ -1,285 +1,330 @@
-#region Copyright notice and license
-
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text.RegularExpressions;
-using Google.ProtocolBuffers.DescriptorProtos;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- /// <summary>
- /// All the configuration required for the generator - where to generate
- /// output files, the location of input files etc. While this isn't immutable
- /// in practice, the contents shouldn't be changed after being passed to
- /// the generator.
- /// </summary>
- public sealed class GeneratorOptions {
-
- private static Dictionary<string, string> LineBreaks = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) {
- { "Windows", "\r\n" },
- { "Unix", "\n" },
- { "Default", Environment.NewLine }
- };
-
- public IList<string> InputFiles { get; set; }
-
- public GeneratorOptions() {
- LineBreak = Environment.NewLine;
- }
-
- /// <summary>
- /// Attempts to validate the options, but doesn't throw an exception if they're invalid.
- /// Instead, when this method returns false, the output variable will contain a collection
- /// of reasons for the validation failure.
- /// </summary>
- /// <param name="reasons">Variable to receive a list of reasons in case of validation failure.</param>
- /// <returns>true if the options are valid; false otherwise</returns>
- public bool TryValidate(out IList<string> reasons) {
- List<string> tmpReasons = new List<string>();
-
- ParseArguments(tmpReasons);
-
- // Output directory validation
- if (string.IsNullOrEmpty(FileOptions.OutputDirectory)) {
- tmpReasons.Add("No output directory specified");
- }
- else {
- if (!Directory.Exists(FileOptions.OutputDirectory)) {
- tmpReasons.Add("Specified output directory (" + FileOptions.OutputDirectory + " doesn't exist.");
- }
- }
-
- // Input file validation (just in terms of presence)
- if (InputFiles == null || InputFiles.Count == 0) {
- tmpReasons.Add("No input files specified");
- }
- else {
- foreach (string input in InputFiles) {
- FileInfo fi = new FileInfo(input);
- if (!fi.Exists) {
- tmpReasons.Add("Input file " + input + " doesn't exist.");
- }
- }
- }
-
- if (tmpReasons.Count != 0) {
- reasons = tmpReasons;
- return false;
- }
-
- reasons = null;
- return true;
- }
-
- /// <summary>
- /// Validates that all the options have been set and are valid,
- /// throwing an exception if they haven't.
- /// </summary>
- /// <exception cref="InvalidOptionsException">The options are invalid.</exception>
- public void Validate() {
- IList<string> reasons;
- if (!TryValidate(out reasons)) {
- throw new InvalidOptionsException(reasons);
- }
- }
-
- // Raw arguments, used to provide defaults for proto file options
- public IList<string> Arguments { get; set; }
-
- [Obsolete("Please use GeneratorOptions.FileOptions.OutputDirectory instead")]
- public string OutputDirectory {
- get { return FileOptions.OutputDirectory; }
- set {
- CSharpFileOptions.Builder bld = FileOptions.ToBuilder();
- bld.OutputDirectory = value;
- FileOptions = bld.Build();
- }
- }
-
- private static readonly Regex ArgMatch = new Regex(@"^[-/](?<name>[\w_]+?)[:=](?<value>.*)$");
- private CSharpFileOptions fileOptions;
-
- public CSharpFileOptions FileOptions {
- get { return fileOptions ?? (fileOptions = CSharpFileOptions.DefaultInstance); }
- set { fileOptions = value; }
- }
-
- public string LineBreak { get; set; }
-
- private void ParseArguments(IList<string> tmpReasons) {
- bool doHelp = Arguments.Count == 0;
-
- InputFiles = new List<string>();
- CSharpFileOptions.Builder builder = FileOptions.ToBuilder();
- Dictionary<string, FieldDescriptor> fields =
- new Dictionary<string, FieldDescriptor>(StringComparer.OrdinalIgnoreCase);
- foreach (FieldDescriptor fld in builder.DescriptorForType.Fields) {
- fields.Add(fld.Name, fld);
- }
-
- foreach (string argument in Arguments) {
- if (StringComparer.OrdinalIgnoreCase.Equals("-help", argument) ||
- StringComparer.OrdinalIgnoreCase.Equals("/help", argument) ||
- StringComparer.OrdinalIgnoreCase.Equals("-?", argument) ||
- StringComparer.OrdinalIgnoreCase.Equals("/?", argument)) {
- doHelp = true;
- break;
- }
-
- Match m = ArgMatch.Match(argument);
- if (m.Success) {
- FieldDescriptor fld;
- string name = m.Groups["name"].Value;
- string value = m.Groups["value"].Value;
-
- if (fields.TryGetValue(name, out fld)) {
- object obj;
- if (TryCoerceType(value, fld, out obj, tmpReasons)) {
- builder[fld] = obj;
- }
- } else if (name == "line_break") {
- string tmp;
- if (LineBreaks.TryGetValue(value, out tmp)) {
- LineBreak = tmp;
- } else {
- tmpReasons.Add("Invalid value for 'line_break': " + value + ".");
- }
- } else if (!File.Exists(argument)) {
- doHelp = true;
- tmpReasons.Add("Unknown argument '" + name + "'.");
- } else {
- InputFiles.Add(argument);
- }
- }
- else {
- InputFiles.Add(argument);
- }
- }
-
- if (doHelp || InputFiles.Count == 0) {
- tmpReasons.Add("Arguments:");
- foreach (KeyValuePair<string, FieldDescriptor> field in fields) {
- tmpReasons.Add(String.Format("-{0}=[{1}]", field.Key, field.Value.FieldType));
- }
- tmpReasons.Add("-line_break=[" + string.Join("|", new List<string>(LineBreaks.Keys).ToArray()) + "]");
- tmpReasons.Add("followed by one or more file paths.");
- }
- else {
- FileOptions = builder.Build();
- }
- }
-
- private static bool TryCoerceType(string text, FieldDescriptor field, out object value, IList<string> tmpReasons) {
- value = null;
-
- switch (field.FieldType) {
- case FieldType.Int32:
- case FieldType.SInt32:
- case FieldType.SFixed32:
- value = Int32.Parse(text);
- break;
-
- case FieldType.Int64:
- case FieldType.SInt64:
- case FieldType.SFixed64:
- value = Int64.Parse(text);
- break;
-
- case FieldType.UInt32:
- case FieldType.Fixed32:
- value = UInt32.Parse(text);
- break;
-
- case FieldType.UInt64:
- case FieldType.Fixed64:
- value = UInt64.Parse(text);
- break;
-
- case FieldType.Float:
- value = float.Parse(text);
- break;
-
- case FieldType.Double:
- value = Double.Parse(text);
- break;
-
- case FieldType.Bool:
- value = Boolean.Parse(text);
- break;
-
- case FieldType.String:
- value = text;
- break;
-
- case FieldType.Enum: {
- EnumDescriptor enumType = field.EnumType;
-
- int number;
- if (int.TryParse(text, out number)) {
- value = enumType.FindValueByNumber(number);
- if (value == null) {
- tmpReasons.Add(
- "Enum type \"" + enumType.FullName +
- "\" has no value with number " + number + ".");
- return false;
- }
- }
- else {
- value = enumType.FindValueByName(text);
- if (value == null) {
- tmpReasons.Add(
- "Enum type \"" + enumType.FullName +
- "\" has no value named \"" + text + "\".");
- return false;
- }
- }
-
- break;
- }
-
- case FieldType.Bytes:
- case FieldType.Message:
- case FieldType.Group:
- tmpReasons.Add("Unhandled field type " + field.FieldType.ToString() + ".");
- return false;
- }
-
- return true;
- }
- }
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text.RegularExpressions;
+using Google.ProtocolBuffers.DescriptorProtos;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ /// <summary>
+ /// All the configuration required for the generator - where to generate
+ /// output files, the location of input files etc. While this isn't immutable
+ /// in practice, the contents shouldn't be changed after being passed to
+ /// the generator.
+ /// </summary>
+ public sealed class GeneratorOptions
+ {
+ private static Dictionary<string, string> LineBreaks =
+ new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
+ {
+ {"Windows", "\r\n"},
+ {"Unix", "\n"},
+ {"Default", Environment.NewLine}
+ };
+
+ public IList<string> InputFiles { get; set; }
+
+ public GeneratorOptions()
+ {
+ LineBreak = Environment.NewLine;
+ }
+
+ /// <summary>
+ /// Attempts to validate the options, but doesn't throw an exception if they're invalid.
+ /// Instead, when this method returns false, the output variable will contain a collection
+ /// of reasons for the validation failure.
+ /// </summary>
+ /// <param name="reasons">Variable to receive a list of reasons in case of validation failure.</param>
+ /// <returns>true if the options are valid; false otherwise</returns>
+ public bool TryValidate(out IList<string> reasons)
+ {
+ List<string> tmpReasons = new List<string>();
+
+ ParseArguments(tmpReasons);
+
+ // Output directory validation
+ if (string.IsNullOrEmpty(FileOptions.OutputDirectory))
+ {
+ tmpReasons.Add("No output directory specified");
+ }
+ else
+ {
+ if (!Directory.Exists(FileOptions.OutputDirectory))
+ {
+ tmpReasons.Add("Specified output directory (" + FileOptions.OutputDirectory + " doesn't exist.");
+ }
+ }
+
+ // Input file validation (just in terms of presence)
+ if (InputFiles == null || InputFiles.Count == 0)
+ {
+ tmpReasons.Add("No input files specified");
+ }
+ else
+ {
+ foreach (string input in InputFiles)
+ {
+ FileInfo fi = new FileInfo(input);
+ if (!fi.Exists)
+ {
+ tmpReasons.Add("Input file " + input + " doesn't exist.");
+ }
+ }
+ }
+
+ if (tmpReasons.Count != 0)
+ {
+ reasons = tmpReasons;
+ return false;
+ }
+
+ reasons = null;
+ return true;
+ }
+
+ /// <summary>
+ /// Validates that all the options have been set and are valid,
+ /// throwing an exception if they haven't.
+ /// </summary>
+ /// <exception cref="InvalidOptionsException">The options are invalid.</exception>
+ public void Validate()
+ {
+ IList<string> reasons;
+ if (!TryValidate(out reasons))
+ {
+ throw new InvalidOptionsException(reasons);
+ }
+ }
+
+ // Raw arguments, used to provide defaults for proto file options
+ public IList<string> Arguments { get; set; }
+
+ [Obsolete("Please use GeneratorOptions.FileOptions.OutputDirectory instead")]
+ public string OutputDirectory
+ {
+ get { return FileOptions.OutputDirectory; }
+ set
+ {
+ CSharpFileOptions.Builder bld = FileOptions.ToBuilder();
+ bld.OutputDirectory = value;
+ FileOptions = bld.Build();
+ }
+ }
+
+ private static readonly Regex ArgMatch = new Regex(@"^[-/](?<name>[\w_]+?)[:=](?<value>.*)$");
+ private CSharpFileOptions fileOptions;
+
+ public CSharpFileOptions FileOptions
+ {
+ get { return fileOptions ?? (fileOptions = CSharpFileOptions.DefaultInstance); }
+ set { fileOptions = value; }
+ }
+
+ public string LineBreak { get; set; }
+
+ private void ParseArguments(IList<string> tmpReasons)
+ {
+ bool doHelp = Arguments.Count == 0;
+
+ InputFiles = new List<string>();
+ CSharpFileOptions.Builder builder = FileOptions.ToBuilder();
+ Dictionary<string, FieldDescriptor> fields =
+ new Dictionary<string, FieldDescriptor>(StringComparer.OrdinalIgnoreCase);
+ foreach (FieldDescriptor fld in builder.DescriptorForType.Fields)
+ {
+ fields.Add(fld.Name, fld);
+ }
+
+ foreach (string argument in Arguments)
+ {
+ if (StringComparer.OrdinalIgnoreCase.Equals("-help", argument) ||
+ StringComparer.OrdinalIgnoreCase.Equals("/help", argument) ||
+ StringComparer.OrdinalIgnoreCase.Equals("-?", argument) ||
+ StringComparer.OrdinalIgnoreCase.Equals("/?", argument))
+ {
+ doHelp = true;
+ break;
+ }
+
+ Match m = ArgMatch.Match(argument);
+ if (m.Success)
+ {
+ FieldDescriptor fld;
+ string name = m.Groups["name"].Value;
+ string value = m.Groups["value"].Value;
+
+ if (fields.TryGetValue(name, out fld))
+ {
+ object obj;
+ if (TryCoerceType(value, fld, out obj, tmpReasons))
+ {
+ builder[fld] = obj;
+ }
+ }
+ else if (name == "line_break")
+ {
+ string tmp;
+ if (LineBreaks.TryGetValue(value, out tmp))
+ {
+ LineBreak = tmp;
+ }
+ else
+ {
+ tmpReasons.Add("Invalid value for 'line_break': " + value + ".");
+ }
+ }
+ else if (!File.Exists(argument))
+ {
+ doHelp = true;
+ tmpReasons.Add("Unknown argument '" + name + "'.");
+ }
+ else
+ {
+ InputFiles.Add(argument);
+ }
+ }
+ else
+ {
+ InputFiles.Add(argument);
+ }
+ }
+
+ if (doHelp || InputFiles.Count == 0)
+ {
+ tmpReasons.Add("Arguments:");
+ foreach (KeyValuePair<string, FieldDescriptor> field in fields)
+ {
+ tmpReasons.Add(String.Format("-{0}=[{1}]", field.Key, field.Value.FieldType));
+ }
+ tmpReasons.Add("-line_break=[" + string.Join("|", new List<string>(LineBreaks.Keys).ToArray()) + "]");
+ tmpReasons.Add("followed by one or more file paths.");
+ }
+ else
+ {
+ FileOptions = builder.Build();
+ }
+ }
+
+ private static bool TryCoerceType(string text, FieldDescriptor field, out object value, IList<string> tmpReasons)
+ {
+ value = null;
+
+ switch (field.FieldType)
+ {
+ case FieldType.Int32:
+ case FieldType.SInt32:
+ case FieldType.SFixed32:
+ value = Int32.Parse(text);
+ break;
+
+ case FieldType.Int64:
+ case FieldType.SInt64:
+ case FieldType.SFixed64:
+ value = Int64.Parse(text);
+ break;
+
+ case FieldType.UInt32:
+ case FieldType.Fixed32:
+ value = UInt32.Parse(text);
+ break;
+
+ case FieldType.UInt64:
+ case FieldType.Fixed64:
+ value = UInt64.Parse(text);
+ break;
+
+ case FieldType.Float:
+ value = float.Parse(text);
+ break;
+
+ case FieldType.Double:
+ value = Double.Parse(text);
+ break;
+
+ case FieldType.Bool:
+ value = Boolean.Parse(text);
+ break;
+
+ case FieldType.String:
+ value = text;
+ break;
+
+ case FieldType.Enum:
+ {
+ EnumDescriptor enumType = field.EnumType;
+
+ int number;
+ if (int.TryParse(text, out number))
+ {
+ value = enumType.FindValueByNumber(number);
+ if (value == null)
+ {
+ tmpReasons.Add(
+ "Enum type \"" + enumType.FullName +
+ "\" has no value with number " + number + ".");
+ return false;
+ }
+ }
+ else
+ {
+ value = enumType.FindValueByName(text);
+ if (value == null)
+ {
+ tmpReasons.Add(
+ "Enum type \"" + enumType.FullName +
+ "\" has no value named \"" + text + "\".");
+ return false;
+ }
+ }
+
+ break;
+ }
+
+ case FieldType.Bytes:
+ case FieldType.Message:
+ case FieldType.Group:
+ tmpReasons.Add("Unhandled field type " + field.FieldType.ToString() + ".");
+ return false;
+ }
+
+ return true;
+ }
+ }
} \ No newline at end of file
diff --git a/src/ProtoGen/Helpers.cs b/src/ProtoGen/Helpers.cs
index 6b6e3163..3c001150 100644
--- a/src/ProtoGen/Helpers.cs
+++ b/src/ProtoGen/Helpers.cs
@@ -1,42 +1,45 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-namespace Google.ProtocolBuffers.ProtoGen {
-
- /// <summary>
- /// Helpers to resolve class names etc.
- /// </summary>
- internal static class Helpers {
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ /// <summary>
+ /// Helpers to resolve class names etc.
+ /// </summary>
+ internal static class Helpers
+ {
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/IFieldSourceGenerator.cs b/src/ProtoGen/IFieldSourceGenerator.cs
index 9c71a579..f53ae5e4 100644
--- a/src/ProtoGen/IFieldSourceGenerator.cs
+++ b/src/ProtoGen/IFieldSourceGenerator.cs
@@ -1,49 +1,53 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal interface IFieldSourceGenerator {
- void GenerateMembers(TextGenerator writer);
- void GenerateBuilderMembers(TextGenerator writer);
- void GenerateMergingCode(TextGenerator writer);
- void GenerateBuildingCode(TextGenerator writer);
- void GenerateParsingCode(TextGenerator writer);
- void GenerateSerializationCode(TextGenerator writer);
- void GenerateSerializedSizeCode(TextGenerator writer);
-
- void WriteHash(TextGenerator writer);
- void WriteEquals(TextGenerator writer);
- void WriteToString(TextGenerator writer);
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal interface IFieldSourceGenerator
+ {
+ void GenerateMembers(TextGenerator writer);
+ void GenerateBuilderMembers(TextGenerator writer);
+ void GenerateMergingCode(TextGenerator writer);
+ void GenerateBuildingCode(TextGenerator writer);
+ void GenerateParsingCode(TextGenerator writer);
+ void GenerateSerializationCode(TextGenerator writer);
+ void GenerateSerializedSizeCode(TextGenerator writer);
+
+ void WriteHash(TextGenerator writer);
+ void WriteEquals(TextGenerator writer);
+ void WriteToString(TextGenerator writer);
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/ISourceGenerator.cs b/src/ProtoGen/ISourceGenerator.cs
index c2d172e7..452d854a 100644
--- a/src/ProtoGen/ISourceGenerator.cs
+++ b/src/ProtoGen/ISourceGenerator.cs
@@ -1,39 +1,43 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal interface ISourceGenerator {
- void Generate(TextGenerator writer);
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal interface ISourceGenerator
+ {
+ void Generate(TextGenerator writer);
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/InvalidOptionsException.cs b/src/ProtoGen/InvalidOptionsException.cs
index c1fcdd6a..fb698495 100644
--- a/src/ProtoGen/InvalidOptionsException.cs
+++ b/src/ProtoGen/InvalidOptionsException.cs
@@ -1,70 +1,77 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using Google.ProtocolBuffers.Collections;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- /// <summary>
- /// Exception thrown to indicate that the options passed were invalid.
- /// </summary>
- public sealed class InvalidOptionsException : Exception {
-
- private readonly IList<string> reasons;
-
- /// <summary>
- /// An immutable list of reasons why the options were invalid.
- /// </summary>
- public IList<string> Reasons {
- get { return reasons; }
- }
-
- public InvalidOptionsException(IList<string> reasons)
- : base(BuildMessage(reasons)) {
- this.reasons = Lists.AsReadOnly(reasons);
- }
-
- private static string BuildMessage(IEnumerable<string> reasons) {
- StringBuilder builder = new StringBuilder("Invalid options:");
- builder.AppendLine();
- foreach (string reason in reasons) {
- builder.Append(" ");
- builder.AppendLine(reason);
- }
- return builder.ToString();
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Google.ProtocolBuffers.Collections;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ /// <summary>
+ /// Exception thrown to indicate that the options passed were invalid.
+ /// </summary>
+ public sealed class InvalidOptionsException : Exception
+ {
+ private readonly IList<string> reasons;
+
+ /// <summary>
+ /// An immutable list of reasons why the options were invalid.
+ /// </summary>
+ public IList<string> Reasons
+ {
+ get { return reasons; }
+ }
+
+ public InvalidOptionsException(IList<string> reasons)
+ : base(BuildMessage(reasons))
+ {
+ this.reasons = Lists.AsReadOnly(reasons);
+ }
+
+ private static string BuildMessage(IEnumerable<string> reasons)
+ {
+ StringBuilder builder = new StringBuilder("Invalid options:");
+ builder.AppendLine();
+ foreach (string reason in reasons)
+ {
+ builder.Append(" ");
+ builder.AppendLine(reason);
+ }
+ return builder.ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/MessageFieldGenerator.cs b/src/ProtoGen/MessageFieldGenerator.cs
index d952984a..495a461d 100644
--- a/src/ProtoGen/MessageFieldGenerator.cs
+++ b/src/ProtoGen/MessageFieldGenerator.cs
@@ -1,142 +1,161 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal class MessageFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
-
- internal MessageFieldGenerator(FieldDescriptor descriptor)
- : base(descriptor) {
- }
-
- public void GenerateMembers(TextGenerator writer) {
- writer.WriteLine("private bool has{0};", PropertyName);
- writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue);
- 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("}");
- }
-
- public void GenerateBuilderMembers(TextGenerator writer) {
- writer.WriteLine("public bool Has{0} {{", PropertyName);
- writer.WriteLine(" get {{ return result.Has{0}; }}", PropertyName);
- writer.WriteLine("}");
- writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return result.{0}; }}", PropertyName);
- writer.WriteLine(" set {{ Set{0}(value); }}", PropertyName);
- writer.WriteLine("}");
- writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
- AddNullCheck(writer);
- writer.WriteLine(" result.has{0} = true;", PropertyName);
- writer.WriteLine(" result.{0}_ = value;", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder Set{0}({1}.Builder builderForValue) {{", PropertyName, TypeName);
- AddNullCheck(writer, "builderForValue");
- writer.WriteLine(" result.has{0} = true;", PropertyName);
- writer.WriteLine(" result.{0}_ = builderForValue.Build();", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder Merge{0}({1} value) {{", PropertyName, TypeName);
- AddNullCheck(writer);
- 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, TypeName);
- writer.WriteLine(" } else {");
- writer.WriteLine(" result.{0}_ = value;", Name);
- writer.WriteLine(" }");
- writer.WriteLine(" result.has{0} = true;", PropertyName);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
- writer.WriteLine(" result.has{0} = false;", PropertyName);
- writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- }
-
- public void GenerateMergingCode(TextGenerator writer) {
- writer.WriteLine("if (other.Has{0}) {{", PropertyName);
- writer.WriteLine(" Merge{0}(other.{0});", PropertyName);
- writer.WriteLine("}");
- }
-
- public void GenerateBuildingCode(TextGenerator writer) {
- // Nothing to do for singular fields
- }
-
- public void GenerateParsingCode(TextGenerator writer) {
- writer.WriteLine("{0}.Builder subBuilder = {0}.CreateBuilder();", TypeName);
- writer.WriteLine("if (Has{0}) {{", PropertyName);
- writer.WriteLine(" subBuilder.MergeFrom({0});", PropertyName);
- writer.WriteLine("}");
- if (Descriptor.FieldType == FieldType.Group) {
- writer.WriteLine("input.ReadGroup({0}, subBuilder, extensionRegistry);", Number);
- } else {
- writer.WriteLine("input.ReadMessage(subBuilder, extensionRegistry);");
- }
- writer.WriteLine("{0} = subBuilder.BuildPartial();", PropertyName);
- }
-
- public void GenerateSerializationCode(TextGenerator writer) {
- writer.WriteLine("if (Has{0}) {{", PropertyName);
- writer.WriteLine(" output.Write{0}({1}, {2});", MessageOrGroup, Number, PropertyName);
- writer.WriteLine("}");
- }
-
- public void GenerateSerializedSizeCode(TextGenerator writer) {
- writer.WriteLine("if (Has{0}) {{", PropertyName);
- writer.WriteLine(" size += pb::CodedOutputStream.Compute{0}Size({1}, {2});",
- MessageOrGroup, Number, PropertyName);
- writer.WriteLine("}");
- }
-
- public override void WriteHash(TextGenerator writer) {
- writer.WriteLine("if (has{0}) hash ^= {1}_.GetHashCode();", PropertyName, Name);
- }
-
- public override void WriteEquals(TextGenerator writer) {
- writer.WriteLine("if (has{0} != other.has{0} || (has{0} && !{1}_.Equals(other.{1}_))) return false;", PropertyName, Name);
- }
-
- public override void WriteToString(TextGenerator writer) {
- writer.WriteLine("PrintField(\"{2}\", has{0}, {1}_, writer);", PropertyName, Name,
- Descriptor.FieldType == FieldType.Group ? Descriptor.MessageType.Name : Descriptor.Name);
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal class MessageFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator
+ {
+ internal MessageFieldGenerator(FieldDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
+
+ public void GenerateMembers(TextGenerator writer)
+ {
+ writer.WriteLine("private bool has{0};", PropertyName);
+ writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue);
+ 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("}");
+ }
+
+ public void GenerateBuilderMembers(TextGenerator writer)
+ {
+ writer.WriteLine("public bool Has{0} {{", PropertyName);
+ writer.WriteLine(" get {{ return result.Has{0}; }}", PropertyName);
+ writer.WriteLine("}");
+ writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
+ writer.WriteLine(" get {{ return result.{0}; }}", PropertyName);
+ writer.WriteLine(" set {{ Set{0}(value); }}", PropertyName);
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
+ AddNullCheck(writer);
+ writer.WriteLine(" result.has{0} = true;", PropertyName);
+ writer.WriteLine(" result.{0}_ = value;", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Set{0}({1}.Builder builderForValue) {{", PropertyName, TypeName);
+ AddNullCheck(writer, "builderForValue");
+ writer.WriteLine(" result.has{0} = true;", PropertyName);
+ writer.WriteLine(" result.{0}_ = builderForValue.Build();", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Merge{0}({1} value) {{", PropertyName, TypeName);
+ AddNullCheck(writer);
+ 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,
+ TypeName);
+ writer.WriteLine(" } else {");
+ writer.WriteLine(" result.{0}_ = value;", Name);
+ writer.WriteLine(" }");
+ writer.WriteLine(" result.has{0} = true;", PropertyName);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" result.has{0} = false;", PropertyName);
+ writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ }
+
+ public void GenerateMergingCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (other.Has{0}) {{", PropertyName);
+ writer.WriteLine(" Merge{0}(other.{0});", PropertyName);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateBuildingCode(TextGenerator writer)
+ {
+ // Nothing to do for singular fields
+ }
+
+ public void GenerateParsingCode(TextGenerator writer)
+ {
+ writer.WriteLine("{0}.Builder subBuilder = {0}.CreateBuilder();", TypeName);
+ writer.WriteLine("if (Has{0}) {{", PropertyName);
+ writer.WriteLine(" subBuilder.MergeFrom({0});", PropertyName);
+ writer.WriteLine("}");
+ if (Descriptor.FieldType == FieldType.Group)
+ {
+ writer.WriteLine("input.ReadGroup({0}, subBuilder, extensionRegistry);", Number);
+ }
+ else
+ {
+ writer.WriteLine("input.ReadMessage(subBuilder, extensionRegistry);");
+ }
+ writer.WriteLine("{0} = subBuilder.BuildPartial();", PropertyName);
+ }
+
+ public void GenerateSerializationCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (Has{0}) {{", PropertyName);
+ writer.WriteLine(" output.Write{0}({1}, {2});", MessageOrGroup, Number, PropertyName);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateSerializedSizeCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (Has{0}) {{", PropertyName);
+ writer.WriteLine(" size += pb::CodedOutputStream.Compute{0}Size({1}, {2});",
+ MessageOrGroup, Number, PropertyName);
+ writer.WriteLine("}");
+ }
+
+ public override void WriteHash(TextGenerator writer)
+ {
+ writer.WriteLine("if (has{0}) hash ^= {1}_.GetHashCode();", PropertyName, Name);
+ }
+
+ public override void WriteEquals(TextGenerator writer)
+ {
+ writer.WriteLine("if (has{0} != other.has{0} || (has{0} && !{1}_.Equals(other.{1}_))) return false;",
+ PropertyName, Name);
+ }
+
+ public override void WriteToString(TextGenerator writer)
+ {
+ writer.WriteLine("PrintField(\"{2}\", has{0}, {1}_, writer);", PropertyName, Name,
+ Descriptor.FieldType == FieldType.Group ? Descriptor.MessageType.Name : Descriptor.Name);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/MessageGenerator.cs b/src/ProtoGen/MessageGenerator.cs
index 43b8b7eb..9eff86c4 100644
--- a/src/ProtoGen/MessageGenerator.cs
+++ b/src/ProtoGen/MessageGenerator.cs
@@ -1,617 +1,732 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System;
-using System.Collections.Generic;
-using Google.ProtocolBuffers.DescriptorProtos;
-using Google.ProtocolBuffers.Descriptors;
-using ExtensionRange = Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal class MessageGenerator : SourceGeneratorBase<MessageDescriptor>, ISourceGenerator {
- internal MessageGenerator(MessageDescriptor descriptor) : base(descriptor) {
- }
-
- private string ClassName {
- get { return Descriptor.Name; }
- }
-
- private string FullClassName {
- get { return GetClassName(Descriptor); }
- }
-
- /// <summary>
- /// Get an identifier that uniquely identifies this type within the file.
- /// This is used to declare static variables related to this type at the
- /// outermost file scope.
- /// </summary>
- static string GetUniqueFileScopeIdentifier(IDescriptor descriptor) {
- return "static_" + descriptor.FullName.Replace(".", "_");
- }
-
- internal void GenerateStaticVariables(TextGenerator writer) {
- // Because descriptor.proto (Google.ProtocolBuffers.DescriptorProtos) is
- // used in the construction of descriptors, we have a tricky bootstrapping
- // problem. To help control static initialization order, we make sure all
- // descriptors and other static data that depends on them are members of
- // the proto-descriptor class. This way, they will be initialized in
- // a deterministic order.
-
- string identifier = GetUniqueFileScopeIdentifier(Descriptor);
-
- if (!UseLiteRuntime) {
- // The descriptor for this type.
- string access = Descriptor.File.CSharpOptions.NestClasses ? "private" : "internal";
- writer.WriteLine("{0} static pbd::MessageDescriptor internal__{1}__Descriptor;", access, identifier);
- writer.WriteLine("{0} static pb::FieldAccess.FieldAccessorTable<{1}, {1}.Builder> internal__{2}__FieldAccessorTable;",
- access, FullClassName, identifier);
- }
- // Generate static members for all nested types.
- foreach (MessageDescriptor nestedMessage in Descriptor.NestedTypes) {
- new MessageGenerator(nestedMessage).GenerateStaticVariables(writer);
- }
- }
-
- internal void GenerateStaticVariableInitializers(TextGenerator writer) {
- string identifier = GetUniqueFileScopeIdentifier(Descriptor);
-
- if (!UseLiteRuntime) {
- writer.Write("internal__{0}__Descriptor = ", identifier);
- if (Descriptor.ContainingType == null) {
- writer.WriteLine("Descriptor.MessageTypes[{0}];", Descriptor.Index);
- } else {
- writer.WriteLine("internal__{0}__Descriptor.NestedTypes[{1}];", GetUniqueFileScopeIdentifier(Descriptor.ContainingType), Descriptor.Index);
- }
-
- writer.WriteLine("internal__{0}__FieldAccessorTable = ", identifier);
- writer.WriteLine(" new pb::FieldAccess.FieldAccessorTable<{1}, {1}.Builder>(internal__{0}__Descriptor,",
- identifier, FullClassName);
- writer.Print(" new string[] { ");
- foreach (FieldDescriptor field in Descriptor.Fields) {
- writer.Write("\"{0}\", ", field.CSharpOptions.PropertyName);
- }
- writer.WriteLine("});");
- }
-
- // Generate static member initializers for all nested types.
- foreach (MessageDescriptor nestedMessage in Descriptor.NestedTypes) {
- new MessageGenerator(nestedMessage).GenerateStaticVariableInitializers(writer);
- }
-
- foreach (FieldDescriptor extension in Descriptor.Extensions) {
- new ExtensionGenerator(extension).GenerateStaticVariableInitializers(writer);
- }
- }
-
- public void Generate(TextGenerator writer) {
- writer.WriteLine("{0} sealed partial class {1} : pb::{2}Message{3}<{1}, {1}.Builder> {{",
- ClassAccessLevel, ClassName,
- Descriptor.Proto.ExtensionRangeCount > 0 ? "Extendable" : "Generated",
- 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("public static {0} DefaultInstance {{", ClassName);
- writer.WriteLine(" get { return defaultInstance; }");
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("public override {0} DefaultInstanceForType {{", ClassName);
- writer.WriteLine(" get { return defaultInstance; }");
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("protected override {0} ThisMessage {{", ClassName);
- writer.WriteLine(" get { return this; }");
- writer.WriteLine("}");
- writer.WriteLine();
- if (!UseLiteRuntime) {
- writer.WriteLine("public static pbd::MessageDescriptor Descriptor {");
- writer.WriteLine(" get {{ return {0}.internal__{1}__Descriptor; }}", DescriptorUtil.GetFullUmbrellaClassName(Descriptor),
- GetUniqueFileScopeIdentifier(Descriptor));
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("protected override pb::FieldAccess.FieldAccessorTable<{0}, {0}.Builder> InternalFieldAccessors {{", ClassName);
- writer.WriteLine(" get {{ return {0}.internal__{1}__FieldAccessorTable; }}", DescriptorUtil.GetFullUmbrellaClassName(Descriptor),
- GetUniqueFileScopeIdentifier(Descriptor));
- writer.WriteLine("}");
- writer.WriteLine();
- }
-
- // Extensions don't need to go in an extra nested type
- WriteChildren(writer, null, Descriptor.Extensions);
-
- if (Descriptor.EnumTypes.Count + Descriptor.NestedTypes.Count > 0) {
- writer.WriteLine("#region Nested types");
- writer.WriteLine("public static class Types {");
- writer.Indent();
- WriteChildren(writer, null, Descriptor.EnumTypes);
- WriteChildren(writer, null, Descriptor.NestedTypes);
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine("#endregion");
- writer.WriteLine();
- }
-
- foreach(FieldDescriptor fieldDescriptor in Descriptor.Fields) {
- // Rats: we lose the debug comment here :(
- writer.WriteLine("public const int {0} = {1};", GetFieldConstantName(fieldDescriptor), fieldDescriptor.FieldNumber);
- SourceGenerators.CreateFieldGenerator(fieldDescriptor).GenerateMembers(writer);
- writer.WriteLine();
- }
-
- if (OptimizeSpeed) {
- GenerateIsInitialized(writer);
- GenerateMessageSerializationMethods(writer);
- }
- if (UseLiteRuntime) {
- GenerateLiteRuntimeMethods(writer);
- }
-
- GenerateParseFromMethods(writer);
- GenerateBuilder(writer);
-
- // Force the static initialization code for the file to run, since it may
- // initialize static variables declared in this class.
- writer.WriteLine("static {0}() {{", ClassName);
- // We call object.ReferenceEquals() just to make it a valid statement on its own.
- // Another option would be GetType(), but that causes problems in DescriptorProtoFile,
- // where the bootstrapping is somewhat recursive - type initializers call
- // each other, effectively. We temporarily see Descriptor as null.
- writer.WriteLine(" object.ReferenceEquals({0}.Descriptor, null);", DescriptorUtil.GetFullUmbrellaClassName(Descriptor));
- writer.WriteLine("}");
-
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
- }
-
- private void GenerateLiteRuntimeMethods(TextGenerator writer) {
-
- bool callbase = Descriptor.Proto.ExtensionRangeCount > 0;
- writer.WriteLine("#region Lite runtime methods");
- writer.WriteLine("public override int GetHashCode() {");
- writer.Indent();
- writer.WriteLine("int hash = GetType().GetHashCode();");
- foreach (FieldDescriptor fieldDescriptor in Descriptor.Fields) {
- SourceGenerators.CreateFieldGenerator(fieldDescriptor).WriteHash(writer);
- }
- if (callbase) writer.WriteLine("hash ^= base.GetHashCode();");
- writer.WriteLine("return hash;");
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
-
- writer.WriteLine("public override bool Equals(object obj) {");
- writer.Indent();
- writer.WriteLine("{0} other = obj as {0};", ClassName);
- writer.WriteLine("if (other == null) return false;");
- foreach (FieldDescriptor fieldDescriptor in Descriptor.Fields) {
- SourceGenerators.CreateFieldGenerator(fieldDescriptor).WriteEquals(writer);
- }
- if (callbase) writer.WriteLine("if (!base.Equals(other)) return false;");
- writer.WriteLine("return true;");
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
-
- writer.WriteLine("public override void PrintTo(global::System.IO.TextWriter writer) {");
- writer.Indent();
- List<FieldDescriptor> sorted = new List<FieldDescriptor>(Descriptor.Fields);
- sorted.Sort(new Comparison<FieldDescriptor>(delegate(FieldDescriptor a, FieldDescriptor b) { return a.FieldNumber.CompareTo(b.FieldNumber); }));
- foreach (FieldDescriptor fieldDescriptor in sorted) {
- SourceGenerators.CreateFieldGenerator(fieldDescriptor).WriteToString(writer);
- }
- if (callbase) writer.WriteLine("base.PrintTo(writer);");
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine("#endregion");
- writer.WriteLine();
- }
-
- private void GenerateMessageSerializationMethods(TextGenerator writer) {
- List<FieldDescriptor> sortedFields = new List<FieldDescriptor>(Descriptor.Fields);
- sortedFields.Sort((f1, f2) => f1.FieldNumber.CompareTo(f2.FieldNumber));
-
- List<ExtensionRange> sortedExtensions = new List<ExtensionRange>(Descriptor.Proto.ExtensionRangeList);
- sortedExtensions.Sort((r1, r2) => (r1.Start.CompareTo(r2.Start)));
-
- writer.WriteLine("public override void WriteTo(pb::CodedOutputStream output) {");
- writer.Indent();
- // Make sure we've computed the serialized length, so that packed fields are generated correctly.
- writer.WriteLine("int size = SerializedSize;");
- if (Descriptor.Proto.ExtensionRangeList.Count > 0) {
- writer.WriteLine("pb::ExtendableMessage{1}<{0}, {0}.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);",
- ClassName, RuntimeSuffix);
- }
-
- // Merge the fields and the extension ranges, both sorted by field number.
- for (int i = 0, j = 0; i < Descriptor.Fields.Count || j < sortedExtensions.Count; ) {
- if (i == Descriptor.Fields.Count) {
- GenerateSerializeOneExtensionRange(writer, sortedExtensions[j++]);
- } else if (j == sortedExtensions.Count) {
- GenerateSerializeOneField(writer, sortedFields[i++]);
- } else if (sortedFields[i].FieldNumber < sortedExtensions[j].Start) {
- GenerateSerializeOneField(writer, sortedFields[i++]);
- } else {
- GenerateSerializeOneExtensionRange(writer, sortedExtensions[j++]);
- }
- }
-
- if (!UseLiteRuntime) {
- if (Descriptor.Proto.Options.MessageSetWireFormat) {
- writer.WriteLine("UnknownFields.WriteAsMessageSetTo(output);");
- } else {
- writer.WriteLine("UnknownFields.WriteTo(output);");
- }
- }
-
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("private int memoizedSerializedSize = -1;");
- writer.WriteLine("public override int SerializedSize {");
- writer.Indent();
- writer.WriteLine("get {");
- writer.Indent();
- writer.WriteLine("int size = memoizedSerializedSize;");
- writer.WriteLine("if (size != -1) return size;");
- writer.WriteLine();
- writer.WriteLine("size = 0;");
- foreach (FieldDescriptor field in Descriptor.Fields) {
- SourceGenerators.CreateFieldGenerator(field).GenerateSerializedSizeCode(writer);
- }
- if (Descriptor.Proto.ExtensionRangeCount > 0) {
- writer.WriteLine("size += ExtensionsSerializedSize;");
- }
-
- if (!UseLiteRuntime) {
- if (Descriptor.Options.MessageSetWireFormat) {
- writer.WriteLine("size += UnknownFields.SerializedSizeAsMessageSet;");
- } else {
- writer.WriteLine("size += UnknownFields.SerializedSize;");
- }
- }
- writer.WriteLine("memoizedSerializedSize = size;");
- writer.WriteLine("return size;");
- writer.Outdent();
- writer.WriteLine("}");
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
- }
-
- private static void GenerateSerializeOneField(TextGenerator writer, FieldDescriptor fieldDescriptor) {
- SourceGenerators.CreateFieldGenerator(fieldDescriptor).GenerateSerializationCode(writer);
- }
-
- private static void GenerateSerializeOneExtensionRange(TextGenerator writer, ExtensionRange extensionRange) {
- writer.WriteLine("extensionWriter.WriteUntil({0}, output);", extensionRange.End);
- }
-
- private void GenerateParseFromMethods(TextGenerator writer) {
- // Note: These are separate from GenerateMessageSerializationMethods()
- // because they need to be generated even for messages that are optimized
- // for code size.
-
- writer.WriteLine("public static {0} ParseFrom(pb::ByteString data) {{", ClassName);
- writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();");
- writer.WriteLine("}");
- writer.WriteLine("public static {0} ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {{", ClassName);
- writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();");
- writer.WriteLine("}");
- writer.WriteLine("public static {0} ParseFrom(byte[] data) {{", ClassName);
- writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();");
- writer.WriteLine("}");
- writer.WriteLine("public static {0} ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {{", ClassName);
- writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();");
- writer.WriteLine("}");
- writer.WriteLine("public static {0} ParseFrom(global::System.IO.Stream input) {{", ClassName);
- writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();");
- writer.WriteLine("}");
- writer.WriteLine("public static {0} ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {{", ClassName);
- writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();");
- writer.WriteLine("}");
- writer.WriteLine("public static {0} ParseDelimitedFrom(global::System.IO.Stream input) {{", ClassName);
- writer.WriteLine(" return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();");
- writer.WriteLine("}");
- writer.WriteLine("public static {0} ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {{", ClassName);
- writer.WriteLine(" return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();");
- writer.WriteLine("}");
- writer.WriteLine("public static {0} ParseFrom(pb::CodedInputStream input) {{", ClassName);
- writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();");
- writer.WriteLine("}");
- writer.WriteLine("public static {0} ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {{", ClassName);
- writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();");
- writer.WriteLine("}");
- }
-
- /// <summary>
- /// Returns whether or not the specified message type has any required fields.
- /// If it doesn't, calls to check for initialization can be optimised.
- /// TODO(jonskeet): Move this into MessageDescriptor?
- /// </summary>
- private static bool HasRequiredFields(MessageDescriptor descriptor, Dictionary<MessageDescriptor,object> alreadySeen) {
- if (alreadySeen.ContainsKey(descriptor)) {
- // The type is already in cache. This means that either:
- // a. The type has no required fields.
- // b. We are in the midst of checking if the type has required fields,
- // somewhere up the stack. In this case, we know that if the type
- // has any required fields, they'll be found when we return to it,
- // and the whole call to HasRequiredFields() will return true.
- // Therefore, we don't have to check if this type has required fields
- // here.
- return false;
- }
- alreadySeen[descriptor] = descriptor; // Value is irrelevant
-
- // If the type has extensions, an extension with message type could contain
- // required fields, so we have to be conservative and assume such an
- // extension exists.
- if (descriptor.Extensions.Count > 0) {
- return true;
- }
-
- foreach (FieldDescriptor field in descriptor.Fields) {
- if (field.IsRequired) {
- return true;
- }
- // Message or group
- if (field.MappedType == MappedType.Message) {
- if (HasRequiredFields(field.MessageType, alreadySeen)) {
- return true;
- }
- }
- }
- return false;
- }
-
- private void GenerateBuilder(TextGenerator writer) {
- 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(); }");
- writer.WriteLine("public static Builder CreateBuilder({0} prototype) {{", ClassName);
- writer.WriteLine(" return (Builder) new Builder().MergeFrom(prototype);");
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("{0} sealed partial class Builder : pb::{2}Builder{3}<{1}, Builder> {{",
- ClassAccessLevel, ClassName, Descriptor.Proto.ExtensionRangeCount > 0 ? "Extendable" : "Generated", RuntimeSuffix);
- writer.Indent();
- writer.WriteLine("protected override Builder ThisBuilder {");
- writer.WriteLine(" get { return this; }");
- writer.WriteLine("}");
- GenerateCommonBuilderMethods(writer);
- if (OptimizeSpeed) {
- GenerateBuilderParsingMethods(writer);
- }
- foreach (FieldDescriptor field in Descriptor.Fields) {
- writer.WriteLine();
- // No field comment :(
- SourceGenerators.CreateFieldGenerator(field).GenerateBuilderMembers(writer);
- }
- writer.Outdent();
- writer.WriteLine("}");
- }
-
- private void GenerateCommonBuilderMethods(TextGenerator writer) {
- writer.WriteLine("{0} Builder() {{}}", ClassAccessLevel);
- writer.WriteLine();
- writer.WriteLine("{0} result = new {0}();", ClassName);
- writer.WriteLine();
- writer.WriteLine("protected override {0} MessageBeingBuilt {{", ClassName);
- writer.WriteLine(" get { return result; }");
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("public override Builder Clear() {");
- writer.WriteLine(" result = new {0}();", ClassName);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("public override Builder Clone() {");
- writer.WriteLine(" return new Builder().MergeFrom(result);");
- writer.WriteLine("}");
- writer.WriteLine();
- if (!UseLiteRuntime) {
- writer.WriteLine("public override pbd::MessageDescriptor DescriptorForType {");
- writer.WriteLine(" get {{ return {0}.Descriptor; }}", FullClassName);
- writer.WriteLine("}");
- writer.WriteLine();
- }
- writer.WriteLine("public override {0} DefaultInstanceForType {{", ClassName);
- writer.WriteLine(" get {{ return {0}.DefaultInstance; }}", FullClassName);
- writer.WriteLine("}");
- writer.WriteLine();
-
- 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("}");
- foreach (FieldDescriptor field in Descriptor.Fields) {
- SourceGenerators.CreateFieldGenerator(field).GenerateBuildingCode(writer);
- }
- writer.WriteLine("{0} returnMe = result;", ClassName);
- writer.WriteLine("result = null;");
- writer.WriteLine("return returnMe;");
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
-
- if (OptimizeSpeed) {
- writer.WriteLine("public override Builder MergeFrom(pb::IMessage{0} other) {{", RuntimeSuffix);
- writer.WriteLine(" if (other is {0}) {{", ClassName);
- writer.WriteLine(" return MergeFrom(({0}) other);", ClassName);
- writer.WriteLine(" } else {");
- writer.WriteLine(" base.MergeFrom(other);");
- writer.WriteLine(" return this;");
- writer.WriteLine(" }");
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("public override Builder MergeFrom({0} other) {{", ClassName);
- // Optimization: If other is the default instance, we know none of its
- // fields are set so we can skip the merge.
- writer.Indent();
- writer.WriteLine("if (other == {0}.DefaultInstance) return this;", FullClassName);
- foreach (FieldDescriptor field in Descriptor.Fields) {
- SourceGenerators.CreateFieldGenerator(field).GenerateMergingCode(writer);
- }
- // if message type has extensions
- if (Descriptor.Proto.ExtensionRangeCount > 0) {
- writer.WriteLine(" this.MergeExtensionFields(other);");
- }
- if (!UseLiteRuntime) {
- writer.WriteLine("this.MergeUnknownFields(other.UnknownFields);");
- }
- writer.WriteLine("return this;");
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
- }
- }
-
- private void GenerateBuilderParsingMethods(TextGenerator writer) {
- List<FieldDescriptor> sortedFields = new List<FieldDescriptor>(Descriptor.Fields);
- sortedFields.Sort((f1, f2) => f1.FieldNumber.CompareTo(f2.FieldNumber));
-
- writer.WriteLine("public override Builder MergeFrom(pb::CodedInputStream input) {");
- writer.WriteLine(" return MergeFrom(input, pb::ExtensionRegistry.Empty);");
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {");
- writer.Indent();
- if (!UseLiteRuntime) {
- writer.WriteLine("pb::UnknownFieldSet.Builder unknownFields = null;");
- }
- writer.WriteLine("while (true) {");
- writer.Indent();
- writer.WriteLine("uint tag = input.ReadTag();");
- writer.WriteLine("switch (tag) {");
- writer.Indent();
- writer.WriteLine("case 0: {"); // 0 signals EOF / limit reached
- if (!UseLiteRuntime) {
- writer.WriteLine(" if (unknownFields != null) {");
- writer.WriteLine(" this.UnknownFields = unknownFields.Build();");
- writer.WriteLine(" }");
- }
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("default: {");
- writer.WriteLine(" if (pb::WireFormat.IsEndGroupTag(tag)) {");
- if (!UseLiteRuntime) {
- writer.WriteLine(" if (unknownFields != null) {");
- writer.WriteLine(" this.UnknownFields = unknownFields.Build();");
- writer.WriteLine(" }");
- }
- writer.WriteLine(" return this;"); // it's an endgroup tag
- writer.WriteLine(" }");
- if (!UseLiteRuntime) {
- writer.WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now
- writer.WriteLine(" unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
- writer.WriteLine(" }");
- }
- writer.WriteLine(" ParseUnknownField(input, {0}extensionRegistry, tag);", UseLiteRuntime ? "" : "unknownFields, ");
- writer.WriteLine(" break;");
- writer.WriteLine("}");
- foreach (FieldDescriptor field in sortedFields) {
- uint tag = WireFormat.MakeTag(field);
- writer.WriteLine("case {0}: {{", tag);
- writer.Indent();
- SourceGenerators.CreateFieldGenerator(field).GenerateParsingCode(writer);
- writer.WriteLine("break;");
- writer.Outdent();
- writer.WriteLine("}");
- }
- writer.Outdent();
- writer.WriteLine("}");
- writer.Outdent();
- writer.WriteLine("}");
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
- }
-
- private void GenerateIsInitialized(TextGenerator writer) {
- writer.WriteLine("public override bool IsInitialized {");
- writer.Indent();
- writer.WriteLine("get {");
- writer.Indent();
-
- // Check that all required fields in this message are set.
- // TODO(kenton): We can optimize this when we switch to putting all the
- // "has" fields into a single bitfield.
- foreach (FieldDescriptor field in Descriptor.Fields) {
- if (field.IsRequired) {
- writer.WriteLine("if (!has{0}) return false;", field.CSharpOptions.PropertyName);
- }
- }
-
- // Now check that all embedded messages are initialized.
- foreach (FieldDescriptor field in Descriptor.Fields) {
- if (field.FieldType != FieldType.Message ||
- !HasRequiredFields(field.MessageType, new Dictionary<MessageDescriptor, object>())) {
- continue;
- }
- string propertyName = NameHelpers.UnderscoresToPascalCase(GetFieldName(field));
- if (field.IsRepeated) {
- writer.WriteLine("foreach ({0} element in {1}List) {{", GetClassName(field.MessageType), propertyName);
- writer.WriteLine(" if (!element.IsInitialized) return false;");
- writer.WriteLine("}");
- } else if (field.IsOptional) {
- writer.WriteLine("if (Has{0}) {{", propertyName);
- writer.WriteLine(" if (!{0}.IsInitialized) return false;", propertyName);
- writer.WriteLine("}");
- } else {
- writer.WriteLine("if (!{0}.IsInitialized) return false;", propertyName);
- }
- }
-
- if (Descriptor.Proto.ExtensionRangeCount > 0) {
- writer.WriteLine("if (!ExtensionsAreInitialized) return false;");
- }
- writer.WriteLine("return true;");
- writer.Outdent();
- writer.WriteLine("}");
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
- }
-
- internal void GenerateExtensionRegistrationCode(TextGenerator writer) {
- foreach (FieldDescriptor extension in Descriptor.Extensions) {
- new ExtensionGenerator(extension).GenerateExtensionRegistrationCode(writer);
- }
- foreach (MessageDescriptor nestedMessage in Descriptor.NestedTypes) {
- new MessageGenerator(nestedMessage).GenerateExtensionRegistrationCode(writer);
- }
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.DescriptorProtos;
+using Google.ProtocolBuffers.Descriptors;
+using ExtensionRange = Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal class MessageGenerator : SourceGeneratorBase<MessageDescriptor>, ISourceGenerator
+ {
+ internal MessageGenerator(MessageDescriptor descriptor) : base(descriptor)
+ {
+ }
+
+ private string ClassName
+ {
+ get { return Descriptor.Name; }
+ }
+
+ private string FullClassName
+ {
+ get { return GetClassName(Descriptor); }
+ }
+
+ /// <summary>
+ /// Get an identifier that uniquely identifies this type within the file.
+ /// This is used to declare static variables related to this type at the
+ /// outermost file scope.
+ /// </summary>
+ private static string GetUniqueFileScopeIdentifier(IDescriptor descriptor)
+ {
+ return "static_" + descriptor.FullName.Replace(".", "_");
+ }
+
+ internal void GenerateStaticVariables(TextGenerator writer)
+ {
+ // Because descriptor.proto (Google.ProtocolBuffers.DescriptorProtos) is
+ // used in the construction of descriptors, we have a tricky bootstrapping
+ // problem. To help control static initialization order, we make sure all
+ // descriptors and other static data that depends on them are members of
+ // the proto-descriptor class. This way, they will be initialized in
+ // a deterministic order.
+
+ string identifier = GetUniqueFileScopeIdentifier(Descriptor);
+
+ if (!UseLiteRuntime)
+ {
+ // The descriptor for this type.
+ string access = Descriptor.File.CSharpOptions.NestClasses ? "private" : "internal";
+ writer.WriteLine("{0} static pbd::MessageDescriptor internal__{1}__Descriptor;", access, identifier);
+ writer.WriteLine(
+ "{0} static pb::FieldAccess.FieldAccessorTable<{1}, {1}.Builder> internal__{2}__FieldAccessorTable;",
+ access, FullClassName, identifier);
+ }
+ // Generate static members for all nested types.
+ foreach (MessageDescriptor nestedMessage in Descriptor.NestedTypes)
+ {
+ new MessageGenerator(nestedMessage).GenerateStaticVariables(writer);
+ }
+ }
+
+ internal void GenerateStaticVariableInitializers(TextGenerator writer)
+ {
+ string identifier = GetUniqueFileScopeIdentifier(Descriptor);
+
+ if (!UseLiteRuntime)
+ {
+ writer.Write("internal__{0}__Descriptor = ", identifier);
+ if (Descriptor.ContainingType == null)
+ {
+ writer.WriteLine("Descriptor.MessageTypes[{0}];", Descriptor.Index);
+ }
+ else
+ {
+ writer.WriteLine("internal__{0}__Descriptor.NestedTypes[{1}];",
+ GetUniqueFileScopeIdentifier(Descriptor.ContainingType), Descriptor.Index);
+ }
+
+ writer.WriteLine("internal__{0}__FieldAccessorTable = ", identifier);
+ writer.WriteLine(
+ " new pb::FieldAccess.FieldAccessorTable<{1}, {1}.Builder>(internal__{0}__Descriptor,",
+ identifier, FullClassName);
+ writer.Print(" new string[] { ");
+ foreach (FieldDescriptor field in Descriptor.Fields)
+ {
+ writer.Write("\"{0}\", ", field.CSharpOptions.PropertyName);
+ }
+ writer.WriteLine("});");
+ }
+
+ // Generate static member initializers for all nested types.
+ foreach (MessageDescriptor nestedMessage in Descriptor.NestedTypes)
+ {
+ new MessageGenerator(nestedMessage).GenerateStaticVariableInitializers(writer);
+ }
+
+ foreach (FieldDescriptor extension in Descriptor.Extensions)
+ {
+ new ExtensionGenerator(extension).GenerateStaticVariableInitializers(writer);
+ }
+ }
+
+ public void Generate(TextGenerator writer)
+ {
+ writer.WriteLine("{0} sealed partial class {1} : pb::{2}Message{3}<{1}, {1}.Builder> {{",
+ ClassAccessLevel, ClassName,
+ Descriptor.Proto.ExtensionRangeCount > 0 ? "Extendable" : "Generated",
+ 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("public static {0} DefaultInstance {{", ClassName);
+ writer.WriteLine(" get { return defaultInstance; }");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine("public override {0} DefaultInstanceForType {{", ClassName);
+ writer.WriteLine(" get { return defaultInstance; }");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine("protected override {0} ThisMessage {{", ClassName);
+ writer.WriteLine(" get { return this; }");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ if (!UseLiteRuntime)
+ {
+ writer.WriteLine("public static pbd::MessageDescriptor Descriptor {");
+ writer.WriteLine(" get {{ return {0}.internal__{1}__Descriptor; }}",
+ DescriptorUtil.GetFullUmbrellaClassName(Descriptor),
+ GetUniqueFileScopeIdentifier(Descriptor));
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine(
+ "protected override pb::FieldAccess.FieldAccessorTable<{0}, {0}.Builder> InternalFieldAccessors {{",
+ ClassName);
+ writer.WriteLine(" get {{ return {0}.internal__{1}__FieldAccessorTable; }}",
+ DescriptorUtil.GetFullUmbrellaClassName(Descriptor),
+ GetUniqueFileScopeIdentifier(Descriptor));
+ writer.WriteLine("}");
+ writer.WriteLine();
+ }
+
+ // Extensions don't need to go in an extra nested type
+ WriteChildren(writer, null, Descriptor.Extensions);
+
+ if (Descriptor.EnumTypes.Count + Descriptor.NestedTypes.Count > 0)
+ {
+ writer.WriteLine("#region Nested types");
+ writer.WriteLine("public static class Types {");
+ writer.Indent();
+ WriteChildren(writer, null, Descriptor.EnumTypes);
+ WriteChildren(writer, null, Descriptor.NestedTypes);
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine("#endregion");
+ writer.WriteLine();
+ }
+
+ foreach (FieldDescriptor fieldDescriptor in Descriptor.Fields)
+ {
+ // Rats: we lose the debug comment here :(
+ writer.WriteLine("public const int {0} = {1};", GetFieldConstantName(fieldDescriptor),
+ fieldDescriptor.FieldNumber);
+ SourceGenerators.CreateFieldGenerator(fieldDescriptor).GenerateMembers(writer);
+ writer.WriteLine();
+ }
+
+ if (OptimizeSpeed)
+ {
+ GenerateIsInitialized(writer);
+ GenerateMessageSerializationMethods(writer);
+ }
+ if (UseLiteRuntime)
+ {
+ GenerateLiteRuntimeMethods(writer);
+ }
+
+ GenerateParseFromMethods(writer);
+ GenerateBuilder(writer);
+
+ // Force the static initialization code for the file to run, since it may
+ // initialize static variables declared in this class.
+ writer.WriteLine("static {0}() {{", ClassName);
+ // We call object.ReferenceEquals() just to make it a valid statement on its own.
+ // Another option would be GetType(), but that causes problems in DescriptorProtoFile,
+ // where the bootstrapping is somewhat recursive - type initializers call
+ // each other, effectively. We temporarily see Descriptor as null.
+ writer.WriteLine(" object.ReferenceEquals({0}.Descriptor, null);",
+ DescriptorUtil.GetFullUmbrellaClassName(Descriptor));
+ writer.WriteLine("}");
+
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+ }
+
+ private void GenerateLiteRuntimeMethods(TextGenerator writer)
+ {
+ bool callbase = Descriptor.Proto.ExtensionRangeCount > 0;
+ writer.WriteLine("#region Lite runtime methods");
+ writer.WriteLine("public override int GetHashCode() {");
+ writer.Indent();
+ writer.WriteLine("int hash = GetType().GetHashCode();");
+ foreach (FieldDescriptor fieldDescriptor in Descriptor.Fields)
+ {
+ SourceGenerators.CreateFieldGenerator(fieldDescriptor).WriteHash(writer);
+ }
+ if (callbase) writer.WriteLine("hash ^= base.GetHashCode();");
+ writer.WriteLine("return hash;");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+
+ writer.WriteLine("public override bool Equals(object obj) {");
+ writer.Indent();
+ writer.WriteLine("{0} other = obj as {0};", ClassName);
+ writer.WriteLine("if (other == null) return false;");
+ foreach (FieldDescriptor fieldDescriptor in Descriptor.Fields)
+ {
+ SourceGenerators.CreateFieldGenerator(fieldDescriptor).WriteEquals(writer);
+ }
+ if (callbase) writer.WriteLine("if (!base.Equals(other)) return false;");
+ writer.WriteLine("return true;");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+
+ writer.WriteLine("public override void PrintTo(global::System.IO.TextWriter writer) {");
+ writer.Indent();
+ List<FieldDescriptor> sorted = new List<FieldDescriptor>(Descriptor.Fields);
+ sorted.Sort(
+ new Comparison<FieldDescriptor>(
+ delegate(FieldDescriptor a, FieldDescriptor b) { return a.FieldNumber.CompareTo(b.FieldNumber); }));
+ foreach (FieldDescriptor fieldDescriptor in sorted)
+ {
+ SourceGenerators.CreateFieldGenerator(fieldDescriptor).WriteToString(writer);
+ }
+ if (callbase) writer.WriteLine("base.PrintTo(writer);");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine("#endregion");
+ writer.WriteLine();
+ }
+
+ private void GenerateMessageSerializationMethods(TextGenerator writer)
+ {
+ List<FieldDescriptor> sortedFields = new List<FieldDescriptor>(Descriptor.Fields);
+ sortedFields.Sort((f1, f2) => f1.FieldNumber.CompareTo(f2.FieldNumber));
+
+ List<ExtensionRange> sortedExtensions = new List<ExtensionRange>(Descriptor.Proto.ExtensionRangeList);
+ sortedExtensions.Sort((r1, r2) => (r1.Start.CompareTo(r2.Start)));
+
+ writer.WriteLine("public override void WriteTo(pb::CodedOutputStream output) {");
+ writer.Indent();
+ // Make sure we've computed the serialized length, so that packed fields are generated correctly.
+ writer.WriteLine("int size = SerializedSize;");
+ if (Descriptor.Proto.ExtensionRangeList.Count > 0)
+ {
+ writer.WriteLine(
+ "pb::ExtendableMessage{1}<{0}, {0}.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);",
+ ClassName, RuntimeSuffix);
+ }
+
+ // Merge the fields and the extension ranges, both sorted by field number.
+ for (int i = 0, j = 0; i < Descriptor.Fields.Count || j < sortedExtensions.Count;)
+ {
+ if (i == Descriptor.Fields.Count)
+ {
+ GenerateSerializeOneExtensionRange(writer, sortedExtensions[j++]);
+ }
+ else if (j == sortedExtensions.Count)
+ {
+ GenerateSerializeOneField(writer, sortedFields[i++]);
+ }
+ else if (sortedFields[i].FieldNumber < sortedExtensions[j].Start)
+ {
+ GenerateSerializeOneField(writer, sortedFields[i++]);
+ }
+ else
+ {
+ GenerateSerializeOneExtensionRange(writer, sortedExtensions[j++]);
+ }
+ }
+
+ if (!UseLiteRuntime)
+ {
+ if (Descriptor.Proto.Options.MessageSetWireFormat)
+ {
+ writer.WriteLine("UnknownFields.WriteAsMessageSetTo(output);");
+ }
+ else
+ {
+ writer.WriteLine("UnknownFields.WriteTo(output);");
+ }
+ }
+
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine("private int memoizedSerializedSize = -1;");
+ writer.WriteLine("public override int SerializedSize {");
+ writer.Indent();
+ writer.WriteLine("get {");
+ writer.Indent();
+ writer.WriteLine("int size = memoizedSerializedSize;");
+ writer.WriteLine("if (size != -1) return size;");
+ writer.WriteLine();
+ writer.WriteLine("size = 0;");
+ foreach (FieldDescriptor field in Descriptor.Fields)
+ {
+ SourceGenerators.CreateFieldGenerator(field).GenerateSerializedSizeCode(writer);
+ }
+ if (Descriptor.Proto.ExtensionRangeCount > 0)
+ {
+ writer.WriteLine("size += ExtensionsSerializedSize;");
+ }
+
+ if (!UseLiteRuntime)
+ {
+ if (Descriptor.Options.MessageSetWireFormat)
+ {
+ writer.WriteLine("size += UnknownFields.SerializedSizeAsMessageSet;");
+ }
+ else
+ {
+ writer.WriteLine("size += UnknownFields.SerializedSize;");
+ }
+ }
+ writer.WriteLine("memoizedSerializedSize = size;");
+ writer.WriteLine("return size;");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+ }
+
+ private static void GenerateSerializeOneField(TextGenerator writer, FieldDescriptor fieldDescriptor)
+ {
+ SourceGenerators.CreateFieldGenerator(fieldDescriptor).GenerateSerializationCode(writer);
+ }
+
+ private static void GenerateSerializeOneExtensionRange(TextGenerator writer, ExtensionRange extensionRange)
+ {
+ writer.WriteLine("extensionWriter.WriteUntil({0}, output);", extensionRange.End);
+ }
+
+ private void GenerateParseFromMethods(TextGenerator writer)
+ {
+ // Note: These are separate from GenerateMessageSerializationMethods()
+ // because they need to be generated even for messages that are optimized
+ // for code size.
+
+ writer.WriteLine("public static {0} ParseFrom(pb::ByteString data) {{", ClassName);
+ writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();");
+ writer.WriteLine("}");
+ writer.WriteLine(
+ "public static {0} ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {{",
+ ClassName);
+ writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();");
+ writer.WriteLine("}");
+ writer.WriteLine("public static {0} ParseFrom(byte[] data) {{", ClassName);
+ writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();");
+ writer.WriteLine("}");
+ writer.WriteLine("public static {0} ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {{",
+ ClassName);
+ writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();");
+ writer.WriteLine("}");
+ writer.WriteLine("public static {0} ParseFrom(global::System.IO.Stream input) {{", ClassName);
+ writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();");
+ writer.WriteLine("}");
+ writer.WriteLine(
+ "public static {0} ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {{",
+ ClassName);
+ writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();");
+ writer.WriteLine("}");
+ writer.WriteLine("public static {0} ParseDelimitedFrom(global::System.IO.Stream input) {{", ClassName);
+ writer.WriteLine(" return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();");
+ writer.WriteLine("}");
+ writer.WriteLine(
+ "public static {0} ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {{",
+ ClassName);
+ writer.WriteLine(" return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();");
+ writer.WriteLine("}");
+ writer.WriteLine("public static {0} ParseFrom(pb::CodedInputStream input) {{", ClassName);
+ writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();");
+ writer.WriteLine("}");
+ writer.WriteLine(
+ "public static {0} ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {{",
+ ClassName);
+ writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();");
+ writer.WriteLine("}");
+ }
+
+ /// <summary>
+ /// Returns whether or not the specified message type has any required fields.
+ /// If it doesn't, calls to check for initialization can be optimised.
+ /// TODO(jonskeet): Move this into MessageDescriptor?
+ /// </summary>
+ private static bool HasRequiredFields(MessageDescriptor descriptor,
+ Dictionary<MessageDescriptor, object> alreadySeen)
+ {
+ if (alreadySeen.ContainsKey(descriptor))
+ {
+ // The type is already in cache. This means that either:
+ // a. The type has no required fields.
+ // b. We are in the midst of checking if the type has required fields,
+ // somewhere up the stack. In this case, we know that if the type
+ // has any required fields, they'll be found when we return to it,
+ // and the whole call to HasRequiredFields() will return true.
+ // Therefore, we don't have to check if this type has required fields
+ // here.
+ return false;
+ }
+ alreadySeen[descriptor] = descriptor; // Value is irrelevant
+
+ // If the type has extensions, an extension with message type could contain
+ // required fields, so we have to be conservative and assume such an
+ // extension exists.
+ if (descriptor.Extensions.Count > 0)
+ {
+ return true;
+ }
+
+ foreach (FieldDescriptor field in descriptor.Fields)
+ {
+ if (field.IsRequired)
+ {
+ return true;
+ }
+ // Message or group
+ if (field.MappedType == MappedType.Message)
+ {
+ if (HasRequiredFields(field.MessageType, alreadySeen))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void GenerateBuilder(TextGenerator writer)
+ {
+ 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(); }");
+ writer.WriteLine("public static Builder CreateBuilder({0} prototype) {{", ClassName);
+ writer.WriteLine(" return (Builder) new Builder().MergeFrom(prototype);");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine("{0} sealed partial class Builder : pb::{2}Builder{3}<{1}, Builder> {{",
+ ClassAccessLevel, ClassName,
+ Descriptor.Proto.ExtensionRangeCount > 0 ? "Extendable" : "Generated", RuntimeSuffix);
+ writer.Indent();
+ writer.WriteLine("protected override Builder ThisBuilder {");
+ writer.WriteLine(" get { return this; }");
+ writer.WriteLine("}");
+ GenerateCommonBuilderMethods(writer);
+ if (OptimizeSpeed)
+ {
+ GenerateBuilderParsingMethods(writer);
+ }
+ foreach (FieldDescriptor field in Descriptor.Fields)
+ {
+ writer.WriteLine();
+ // No field comment :(
+ SourceGenerators.CreateFieldGenerator(field).GenerateBuilderMembers(writer);
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+
+ private void GenerateCommonBuilderMethods(TextGenerator writer)
+ {
+ writer.WriteLine("{0} Builder() {{}}", ClassAccessLevel);
+ writer.WriteLine();
+ writer.WriteLine("{0} result = new {0}();", ClassName);
+ writer.WriteLine();
+ writer.WriteLine("protected override {0} MessageBeingBuilt {{", ClassName);
+ writer.WriteLine(" get { return result; }");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine("public override Builder Clear() {");
+ writer.WriteLine(" result = new {0}();", ClassName);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine("public override Builder Clone() {");
+ writer.WriteLine(" return new Builder().MergeFrom(result);");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ if (!UseLiteRuntime)
+ {
+ writer.WriteLine("public override pbd::MessageDescriptor DescriptorForType {");
+ writer.WriteLine(" get {{ return {0}.Descriptor; }}", FullClassName);
+ writer.WriteLine("}");
+ writer.WriteLine();
+ }
+ writer.WriteLine("public override {0} DefaultInstanceForType {{", ClassName);
+ writer.WriteLine(" get {{ return {0}.DefaultInstance; }}", FullClassName);
+ writer.WriteLine("}");
+ writer.WriteLine();
+
+ 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("}");
+ foreach (FieldDescriptor field in Descriptor.Fields)
+ {
+ SourceGenerators.CreateFieldGenerator(field).GenerateBuildingCode(writer);
+ }
+ writer.WriteLine("{0} returnMe = result;", ClassName);
+ writer.WriteLine("result = null;");
+ writer.WriteLine("return returnMe;");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+
+ if (OptimizeSpeed)
+ {
+ writer.WriteLine("public override Builder MergeFrom(pb::IMessage{0} other) {{", RuntimeSuffix);
+ writer.WriteLine(" if (other is {0}) {{", ClassName);
+ writer.WriteLine(" return MergeFrom(({0}) other);", ClassName);
+ writer.WriteLine(" } else {");
+ writer.WriteLine(" base.MergeFrom(other);");
+ writer.WriteLine(" return this;");
+ writer.WriteLine(" }");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine("public override Builder MergeFrom({0} other) {{", ClassName);
+ // Optimization: If other is the default instance, we know none of its
+ // fields are set so we can skip the merge.
+ writer.Indent();
+ writer.WriteLine("if (other == {0}.DefaultInstance) return this;", FullClassName);
+ foreach (FieldDescriptor field in Descriptor.Fields)
+ {
+ SourceGenerators.CreateFieldGenerator(field).GenerateMergingCode(writer);
+ }
+ // if message type has extensions
+ if (Descriptor.Proto.ExtensionRangeCount > 0)
+ {
+ writer.WriteLine(" this.MergeExtensionFields(other);");
+ }
+ if (!UseLiteRuntime)
+ {
+ writer.WriteLine("this.MergeUnknownFields(other.UnknownFields);");
+ }
+ writer.WriteLine("return this;");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+ }
+ }
+
+ private void GenerateBuilderParsingMethods(TextGenerator writer)
+ {
+ List<FieldDescriptor> sortedFields = new List<FieldDescriptor>(Descriptor.Fields);
+ sortedFields.Sort((f1, f2) => f1.FieldNumber.CompareTo(f2.FieldNumber));
+
+ writer.WriteLine("public override Builder MergeFrom(pb::CodedInputStream input) {");
+ writer.WriteLine(" return MergeFrom(input, pb::ExtensionRegistry.Empty);");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine(
+ "public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {");
+ writer.Indent();
+ if (!UseLiteRuntime)
+ {
+ writer.WriteLine("pb::UnknownFieldSet.Builder unknownFields = null;");
+ }
+ writer.WriteLine("while (true) {");
+ writer.Indent();
+ writer.WriteLine("uint tag = input.ReadTag();");
+ writer.WriteLine("switch (tag) {");
+ writer.Indent();
+ writer.WriteLine("case 0: {"); // 0 signals EOF / limit reached
+ if (!UseLiteRuntime)
+ {
+ writer.WriteLine(" if (unknownFields != null) {");
+ writer.WriteLine(" this.UnknownFields = unknownFields.Build();");
+ writer.WriteLine(" }");
+ }
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("default: {");
+ writer.WriteLine(" if (pb::WireFormat.IsEndGroupTag(tag)) {");
+ if (!UseLiteRuntime)
+ {
+ writer.WriteLine(" if (unknownFields != null) {");
+ writer.WriteLine(" this.UnknownFields = unknownFields.Build();");
+ writer.WriteLine(" }");
+ }
+ writer.WriteLine(" return this;"); // it's an endgroup tag
+ writer.WriteLine(" }");
+ if (!UseLiteRuntime)
+ {
+ writer.WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now
+ writer.WriteLine(" unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
+ writer.WriteLine(" }");
+ }
+ writer.WriteLine(" ParseUnknownField(input, {0}extensionRegistry, tag);",
+ UseLiteRuntime ? "" : "unknownFields, ");
+ writer.WriteLine(" break;");
+ writer.WriteLine("}");
+ foreach (FieldDescriptor field in sortedFields)
+ {
+ uint tag = WireFormat.MakeTag(field);
+ writer.WriteLine("case {0}: {{", tag);
+ writer.Indent();
+ SourceGenerators.CreateFieldGenerator(field).GenerateParsingCode(writer);
+ writer.WriteLine("break;");
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+ }
+
+ private void GenerateIsInitialized(TextGenerator writer)
+ {
+ writer.WriteLine("public override bool IsInitialized {");
+ writer.Indent();
+ writer.WriteLine("get {");
+ writer.Indent();
+
+ // Check that all required fields in this message are set.
+ // TODO(kenton): We can optimize this when we switch to putting all the
+ // "has" fields into a single bitfield.
+ foreach (FieldDescriptor field in Descriptor.Fields)
+ {
+ if (field.IsRequired)
+ {
+ writer.WriteLine("if (!has{0}) return false;", field.CSharpOptions.PropertyName);
+ }
+ }
+
+ // Now check that all embedded messages are initialized.
+ foreach (FieldDescriptor field in Descriptor.Fields)
+ {
+ if (field.FieldType != FieldType.Message ||
+ !HasRequiredFields(field.MessageType, new Dictionary<MessageDescriptor, object>()))
+ {
+ continue;
+ }
+ string propertyName = NameHelpers.UnderscoresToPascalCase(GetFieldName(field));
+ if (field.IsRepeated)
+ {
+ writer.WriteLine("foreach ({0} element in {1}List) {{", GetClassName(field.MessageType),
+ propertyName);
+ writer.WriteLine(" if (!element.IsInitialized) return false;");
+ writer.WriteLine("}");
+ }
+ else if (field.IsOptional)
+ {
+ writer.WriteLine("if (Has{0}) {{", propertyName);
+ writer.WriteLine(" if (!{0}.IsInitialized) return false;", propertyName);
+ writer.WriteLine("}");
+ }
+ else
+ {
+ writer.WriteLine("if (!{0}.IsInitialized) return false;", propertyName);
+ }
+ }
+
+ if (Descriptor.Proto.ExtensionRangeCount > 0)
+ {
+ writer.WriteLine("if (!ExtensionsAreInitialized) return false;");
+ }
+ writer.WriteLine("return true;");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+ }
+
+ internal void GenerateExtensionRegistrationCode(TextGenerator writer)
+ {
+ foreach (FieldDescriptor extension in Descriptor.Extensions)
+ {
+ new ExtensionGenerator(extension).GenerateExtensionRegistrationCode(writer);
+ }
+ foreach (MessageDescriptor nestedMessage in Descriptor.NestedTypes)
+ {
+ new MessageGenerator(nestedMessage).GenerateExtensionRegistrationCode(writer);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/PrimitiveFieldGenerator.cs b/src/ProtoGen/PrimitiveFieldGenerator.cs
index dbc203d0..ed7d0dc1 100644
--- a/src/ProtoGen/PrimitiveFieldGenerator.cs
+++ b/src/ProtoGen/PrimitiveFieldGenerator.cs
@@ -1,119 +1,134 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- // TODO(jonskeet): Refactor this. There's loads of common code here.
- internal class PrimitiveFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
-
- internal PrimitiveFieldGenerator(FieldDescriptor descriptor)
- : base(descriptor) {
- }
-
- public void GenerateMembers(TextGenerator writer) {
- writer.WriteLine("private bool has{0};", PropertyName);
- writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue);
- writer.WriteLine("public bool Has{0} {{", PropertyName);
- writer.WriteLine(" get {{ return has{0}; }}", PropertyName);
- writer.WriteLine("}");
- AddClsComplianceCheck(writer);
- writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return {0}_; }}", Name);
- writer.WriteLine("}");
- }
-
- public void GenerateBuilderMembers(TextGenerator writer) {
- writer.WriteLine("public bool Has{0} {{", PropertyName);
- writer.WriteLine(" get {{ return result.Has{0}; }}", PropertyName);
- writer.WriteLine("}");
- AddClsComplianceCheck(writer);
- writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return result.{0}; }}", PropertyName);
- writer.WriteLine(" set {{ Set{0}(value); }}", PropertyName);
- writer.WriteLine("}");
- AddClsComplianceCheck(writer);
- writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
- AddNullCheck(writer);
- writer.WriteLine(" result.has{0} = true;", PropertyName);
- writer.WriteLine(" result.{0}_ = value;", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
- writer.WriteLine(" result.has{0} = false;", PropertyName);
- writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- }
-
- public void GenerateMergingCode(TextGenerator writer) {
- writer.WriteLine("if (other.Has{0}) {{", PropertyName);
- writer.WriteLine(" {0} = other.{0};", PropertyName);
- writer.WriteLine("}");
- }
-
- public void GenerateBuildingCode(TextGenerator writer) {
- // Nothing to do here for primitive types
- }
-
- public void GenerateParsingCode(TextGenerator writer) {
- writer.WriteLine("{0} = input.Read{1}();", PropertyName, CapitalizedTypeName);
- }
-
- public void GenerateSerializationCode(TextGenerator writer) {
- writer.WriteLine("if (Has{0}) {{", PropertyName);
- writer.WriteLine(" output.Write{0}({1}, {2});", CapitalizedTypeName, Number, PropertyName);
- writer.WriteLine("}");
- }
-
- public void GenerateSerializedSizeCode(TextGenerator writer) {
- writer.WriteLine("if (Has{0}) {{", PropertyName);
- writer.WriteLine(" size += pb::CodedOutputStream.Compute{0}Size({1}, {2});",
- CapitalizedTypeName, Number, PropertyName);
- writer.WriteLine("}");
- }
-
- public override void WriteHash(TextGenerator writer) {
- writer.WriteLine("if (has{0}) hash ^= {1}_.GetHashCode();", PropertyName, Name);
- }
-
- public override void WriteEquals(TextGenerator writer) {
- writer.WriteLine("if (has{0} != other.has{0} || (has{0} && !{1}_.Equals(other.{1}_))) return false;", PropertyName, Name);
- }
-
- public override void WriteToString(TextGenerator writer) {
- writer.WriteLine("PrintField(\"{0}\", has{1}, {2}_, writer);", Descriptor.Name, PropertyName, Name);
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ // TODO(jonskeet): Refactor this. There's loads of common code here.
+ internal class PrimitiveFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator
+ {
+ internal PrimitiveFieldGenerator(FieldDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
+
+ public void GenerateMembers(TextGenerator writer)
+ {
+ writer.WriteLine("private bool has{0};", PropertyName);
+ writer.WriteLine("private {0} {1}_ = {2};", TypeName, Name, DefaultValue);
+ writer.WriteLine("public bool Has{0} {{", PropertyName);
+ writer.WriteLine(" get {{ return has{0}; }}", PropertyName);
+ writer.WriteLine("}");
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
+ writer.WriteLine(" get {{ return {0}_; }}", Name);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateBuilderMembers(TextGenerator writer)
+ {
+ writer.WriteLine("public bool Has{0} {{", PropertyName);
+ writer.WriteLine(" get {{ return result.Has{0}; }}", PropertyName);
+ writer.WriteLine("}");
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public {0} {1} {{", TypeName, PropertyName);
+ writer.WriteLine(" get {{ return result.{0}; }}", PropertyName);
+ writer.WriteLine(" set {{ Set{0}(value); }}", PropertyName);
+ writer.WriteLine("}");
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
+ AddNullCheck(writer);
+ writer.WriteLine(" result.has{0} = true;", PropertyName);
+ writer.WriteLine(" result.{0}_ = value;", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" result.has{0} = false;", PropertyName);
+ writer.WriteLine(" result.{0}_ = {1};", Name, DefaultValue);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ }
+
+ public void GenerateMergingCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (other.Has{0}) {{", PropertyName);
+ writer.WriteLine(" {0} = other.{0};", PropertyName);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateBuildingCode(TextGenerator writer)
+ {
+ // Nothing to do here for primitive types
+ }
+
+ public void GenerateParsingCode(TextGenerator writer)
+ {
+ writer.WriteLine("{0} = input.Read{1}();", PropertyName, CapitalizedTypeName);
+ }
+
+ public void GenerateSerializationCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (Has{0}) {{", PropertyName);
+ writer.WriteLine(" output.Write{0}({1}, {2});", CapitalizedTypeName, Number, PropertyName);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateSerializedSizeCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (Has{0}) {{", PropertyName);
+ writer.WriteLine(" size += pb::CodedOutputStream.Compute{0}Size({1}, {2});",
+ CapitalizedTypeName, Number, PropertyName);
+ writer.WriteLine("}");
+ }
+
+ public override void WriteHash(TextGenerator writer)
+ {
+ writer.WriteLine("if (has{0}) hash ^= {1}_.GetHashCode();", PropertyName, Name);
+ }
+
+ public override void WriteEquals(TextGenerator writer)
+ {
+ writer.WriteLine("if (has{0} != other.has{0} || (has{0} && !{1}_.Equals(other.{1}_))) return false;",
+ PropertyName, Name);
+ }
+
+ public override void WriteToString(TextGenerator writer)
+ {
+ writer.WriteLine("PrintField(\"{0}\", has{1}, {2}_, writer);", Descriptor.Name, PropertyName, Name);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/Program.cs b/src/ProtoGen/Program.cs
index e8c486cf..4bd6c463 100644
--- a/src/ProtoGen/Program.cs
+++ b/src/ProtoGen/Program.cs
@@ -1,72 +1,78 @@
-#region Copyright notice and license
-
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-using Google.ProtocolBuffers.DescriptorProtos;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- /// <summary>
- /// Entry point for the Protocol Buffers generator.
- /// </summary>
- internal class Program {
- internal static int Main(string[] args) {
- try {
- // Hack to make sure everything's initialized
- DescriptorProtoFile.Descriptor.ToString();
- GeneratorOptions options = new GeneratorOptions {Arguments = args};
-
- IList<string> validationFailures;
- if (!options.TryValidate(out validationFailures)) {
- // We've already got the message-building logic in the exception...
- InvalidOptionsException exception = new InvalidOptionsException(validationFailures);
- Console.WriteLine(exception.Message);
- return 1;
- }
-
- Generator generator = Generator.CreateGenerator(options);
- generator.Generate();
- return 0;
- }
- catch (Exception e) {
- Console.Error.WriteLine("Error: {0}", e.Message);
- Console.Error.WriteLine();
- Console.Error.WriteLine("Detailed exception information: {0}", e);
- return 1;
- }
- }
- }
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.DescriptorProtos;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ /// <summary>
+ /// Entry point for the Protocol Buffers generator.
+ /// </summary>
+ internal class Program
+ {
+ internal static int Main(string[] args)
+ {
+ try
+ {
+ // Hack to make sure everything's initialized
+ DescriptorProtoFile.Descriptor.ToString();
+ GeneratorOptions options = new GeneratorOptions {Arguments = args};
+
+ IList<string> validationFailures;
+ if (!options.TryValidate(out validationFailures))
+ {
+ // We've already got the message-building logic in the exception...
+ InvalidOptionsException exception = new InvalidOptionsException(validationFailures);
+ Console.WriteLine(exception.Message);
+ return 1;
+ }
+
+ Generator generator = Generator.CreateGenerator(options);
+ generator.Generate();
+ return 0;
+ }
+ catch (Exception e)
+ {
+ Console.Error.WriteLine("Error: {0}", e.Message);
+ Console.Error.WriteLine();
+ Console.Error.WriteLine("Detailed exception information: {0}", e);
+ return 1;
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/src/ProtoGen/ProgramPreprocess.cs b/src/ProtoGen/ProgramPreprocess.cs
index 3cc0826d..ed582989 100644
--- a/src/ProtoGen/ProgramPreprocess.cs
+++ b/src/ProtoGen/ProgramPreprocess.cs
@@ -1,153 +1,186 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- /// <summary>
- /// Preprocesses any input files with an extension of '.proto' by running protoc.exe. If arguments
- /// are supplied with '--' prefix they are provided to protoc.exe, otherwise they are assumed to
- /// be used for ProtoGen.exe which is run on the resulting output proto buffer. If the option
- /// --descriptor_set_out= is specified the proto buffer file is kept, otherwise it will be removed
- /// after code generation.
- /// </summary>
- public class ProgramPreprocess {
- private static int Main(string[] args) {
- try {
- return Environment.ExitCode = Run(args);
- }
- catch (Exception ex) {
- Console.Error.WriteLine(ex);
- return Environment.ExitCode = 2;
- }
- }
-
- public static int Run(params string[] args) {
- bool deleteFile = false;
- string tempFile = null;
- int result;
- bool doHelp = args.Length == 0;
- try {
- List<string> protocArgs = new List<string>();
- List<string> protoGenArgs = new List<string>();
-
- foreach (string arg in args) {
- doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "/?");
- doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "/help");
- doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "-?");
- doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "-help");
-
- if (arg.StartsWith("--descriptor_set_out=")) {
- tempFile = arg.Substring("--descriptor_set_out=".Length);
- protoGenArgs.Add(tempFile);
- }
- }
-
- if (doHelp) {
- Console.WriteLine();
- Console.WriteLine("PROTOC.exe: Use any of the following options that begin with '--':");
- Console.WriteLine();
- try {
- RunProtoc("--help");
- }
- catch (Exception ex) {
- Console.Error.WriteLine(ex.Message);
- }
- Console.WriteLine();
- Console.WriteLine();
- Console.WriteLine("PROTOGEN.exe: The following options are used to specify defaults for code generation.");
- Console.WriteLine();
- Program.Main(new string[0]);
- return 0;
- }
-
- foreach (string arg in args) {
- if (arg.StartsWith("--")) {
- protocArgs.Add(arg);
- }
- else if (File.Exists(arg) && StringComparer.OrdinalIgnoreCase.Equals(".proto", Path.GetExtension(arg))) {
- if (tempFile == null) {
- deleteFile = true;
- tempFile = Path.GetTempFileName();
- protocArgs.Add(String.Format("--descriptor_set_out={0}", tempFile));
- protoGenArgs.Add(tempFile);
- }
- protocArgs.Add(arg);
- }
- else {
- protoGenArgs.Add(arg);
- }
- }
-
- if (tempFile != null) {
- result = RunProtoc(protocArgs.ToArray());
- if (result != 0) {
- return result;
- }
- }
-
- result = Program.Main(protoGenArgs.ToArray());
- }
- finally {
- if (deleteFile && tempFile != null && File.Exists(tempFile)) {
- File.Delete(tempFile);
- }
- }
- return result;
- }
-
- private static int RunProtoc(params string[] args) {
- const string protoc = "protoc.exe";
- string exePath = protoc;
-
- // Why oh why is this not in System.IO.Path or Environment...?
- List<string> searchPath = new List<string>();
- searchPath.Add(Environment.CurrentDirectory);
- searchPath.Add(AppDomain.CurrentDomain.BaseDirectory);
- searchPath.AddRange((Environment.GetEnvironmentVariable("PATH") ?? String.Empty).Split(Path.PathSeparator));
-
- foreach (string path in searchPath) {
- if (File.Exists(exePath = Path.Combine(path, protoc))) {
- break;
- }
- }
-
- if (!File.Exists(exePath)) {
- throw new FileNotFoundException("Unable to locate " + protoc + " make sure it is in the PATH, cwd, or exe dir.");
- }
-
- for (int i = 0; i < args.Length; i++) {
- if (args[i].IndexOf(' ') > 0 && args[i][0] != '"') {
- args[i] = '"' + args[i] + '"';
- }
- }
-
- ProcessStartInfo psi = new ProcessStartInfo(exePath);
- psi.Arguments = String.Join(" ", args);
- psi.RedirectStandardError = true;
- psi.RedirectStandardInput = false;
- psi.RedirectStandardOutput = true;
- psi.ErrorDialog = false;
- psi.CreateNoWindow = true;
- psi.UseShellExecute = false;
- psi.WorkingDirectory = Environment.CurrentDirectory;
-
- Process process = Process.Start(psi);
- if (process == null) {
- return 1;
- }
-
- process.WaitForExit();
-
- string tmp = process.StandardOutput.ReadToEnd();
- if (tmp.Trim().Length > 0) {
- Console.Out.WriteLine(tmp);
- }
- tmp = process.StandardError.ReadToEnd();
- if (tmp.Trim().Length > 0) {
- Console.Error.WriteLine(tmp);
- }
- return process.ExitCode;
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ /// <summary>
+ /// Preprocesses any input files with an extension of '.proto' by running protoc.exe. If arguments
+ /// are supplied with '--' prefix they are provided to protoc.exe, otherwise they are assumed to
+ /// be used for ProtoGen.exe which is run on the resulting output proto buffer. If the option
+ /// --descriptor_set_out= is specified the proto buffer file is kept, otherwise it will be removed
+ /// after code generation.
+ /// </summary>
+ public class ProgramPreprocess
+ {
+ private static int Main(string[] args)
+ {
+ try
+ {
+ return Environment.ExitCode = Run(args);
+ }
+ catch (Exception ex)
+ {
+ Console.Error.WriteLine(ex);
+ return Environment.ExitCode = 2;
+ }
+ }
+
+ public static int Run(params string[] args)
+ {
+ bool deleteFile = false;
+ string tempFile = null;
+ int result;
+ bool doHelp = args.Length == 0;
+ try
+ {
+ List<string> protocArgs = new List<string>();
+ List<string> protoGenArgs = new List<string>();
+
+ foreach (string arg in args)
+ {
+ doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "/?");
+ doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "/help");
+ doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "-?");
+ doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "-help");
+
+ if (arg.StartsWith("--descriptor_set_out="))
+ {
+ tempFile = arg.Substring("--descriptor_set_out=".Length);
+ protoGenArgs.Add(tempFile);
+ }
+ }
+
+ if (doHelp)
+ {
+ Console.WriteLine();
+ Console.WriteLine("PROTOC.exe: Use any of the following options that begin with '--':");
+ Console.WriteLine();
+ try
+ {
+ RunProtoc("--help");
+ }
+ catch (Exception ex)
+ {
+ Console.Error.WriteLine(ex.Message);
+ }
+ Console.WriteLine();
+ Console.WriteLine();
+ Console.WriteLine(
+ "PROTOGEN.exe: The following options are used to specify defaults for code generation.");
+ Console.WriteLine();
+ Program.Main(new string[0]);
+ return 0;
+ }
+
+ foreach (string arg in args)
+ {
+ if (arg.StartsWith("--"))
+ {
+ protocArgs.Add(arg);
+ }
+ else if (File.Exists(arg) &&
+ StringComparer.OrdinalIgnoreCase.Equals(".proto", Path.GetExtension(arg)))
+ {
+ if (tempFile == null)
+ {
+ deleteFile = true;
+ tempFile = Path.GetTempFileName();
+ protocArgs.Add(String.Format("--descriptor_set_out={0}", tempFile));
+ protoGenArgs.Add(tempFile);
+ }
+ protocArgs.Add(arg);
+ }
+ else
+ {
+ protoGenArgs.Add(arg);
+ }
+ }
+
+ if (tempFile != null)
+ {
+ result = RunProtoc(protocArgs.ToArray());
+ if (result != 0)
+ {
+ return result;
+ }
+ }
+
+ result = Program.Main(protoGenArgs.ToArray());
+ }
+ finally
+ {
+ if (deleteFile && tempFile != null && File.Exists(tempFile))
+ {
+ File.Delete(tempFile);
+ }
+ }
+ return result;
+ }
+
+ private static int RunProtoc(params string[] args)
+ {
+ const string protoc = "protoc.exe";
+ string exePath = protoc;
+
+ // Why oh why is this not in System.IO.Path or Environment...?
+ List<string> searchPath = new List<string>();
+ searchPath.Add(Environment.CurrentDirectory);
+ searchPath.Add(AppDomain.CurrentDomain.BaseDirectory);
+ searchPath.AddRange((Environment.GetEnvironmentVariable("PATH") ?? String.Empty).Split(Path.PathSeparator));
+
+ foreach (string path in searchPath)
+ {
+ if (File.Exists(exePath = Path.Combine(path, protoc)))
+ {
+ break;
+ }
+ }
+
+ if (!File.Exists(exePath))
+ {
+ throw new FileNotFoundException("Unable to locate " + protoc +
+ " make sure it is in the PATH, cwd, or exe dir.");
+ }
+
+ for (int i = 0; i < args.Length; i++)
+ {
+ if (args[i].IndexOf(' ') > 0 && args[i][0] != '"')
+ {
+ args[i] = '"' + args[i] + '"';
+ }
+ }
+
+ ProcessStartInfo psi = new ProcessStartInfo(exePath);
+ psi.Arguments = String.Join(" ", args);
+ psi.RedirectStandardError = true;
+ psi.RedirectStandardInput = false;
+ psi.RedirectStandardOutput = true;
+ psi.ErrorDialog = false;
+ psi.CreateNoWindow = true;
+ psi.UseShellExecute = false;
+ psi.WorkingDirectory = Environment.CurrentDirectory;
+
+ Process process = Process.Start(psi);
+ if (process == null)
+ {
+ return 1;
+ }
+
+ process.WaitForExit();
+
+ string tmp = process.StandardOutput.ReadToEnd();
+ if (tmp.Trim().Length > 0)
+ {
+ Console.Out.WriteLine(tmp);
+ }
+ tmp = process.StandardError.ReadToEnd();
+ if (tmp.Trim().Length > 0)
+ {
+ Console.Error.WriteLine(tmp);
+ }
+ return process.ExitCode;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/Properties/AssemblyInfo.cs b/src/ProtoGen/Properties/AssemblyInfo.cs
index 7f77b259..a8b228c0 100644
--- a/src/ProtoGen/Properties/AssemblyInfo.cs
+++ b/src/ProtoGen/Properties/AssemblyInfo.cs
@@ -1,37 +1,40 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("ProtoGen")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("ProtoGen")]
-[assembly: AssemblyCopyright("Copyright © 2008")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("7101763b-7a38-41be-87f5-7ede4c554509")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("2.3.0.277")]
-[assembly: AssemblyVersion("2.3.0.277")]
-[assembly: AssemblyFileVersion("2.3.0.277")]
-
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("ProtoGen")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ProtoGen")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("7101763b-7a38-41be-87f5-7ede4c554509")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("2.3.0.277")]
+
+[assembly: AssemblyVersion("2.3.0.277")]
+[assembly: AssemblyFileVersion("2.3.0.277")] \ No newline at end of file
diff --git a/src/ProtoGen/RepeatedEnumFieldGenerator.cs b/src/ProtoGen/RepeatedEnumFieldGenerator.cs
index c500d38b..e98bc929 100644
--- a/src/ProtoGen/RepeatedEnumFieldGenerator.cs
+++ b/src/ProtoGen/RepeatedEnumFieldGenerator.cs
@@ -1,194 +1,219 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using Google.ProtocolBuffers.DescriptorProtos;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal class RepeatedEnumFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
-
- internal RepeatedEnumFieldGenerator(FieldDescriptor descriptor)
- : base(descriptor) {
- }
-
- public void GenerateMembers(TextGenerator writer) {
- if (Descriptor.IsPacked && OptimizeSpeed) {
- writer.WriteLine("private int {0}MemoizedSerializedSize;", Name);
- }
- writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
- writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return pbc::Lists.AsReadOnly({0}_); }}", Name);
- writer.WriteLine("}");
-
- // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
- writer.WriteLine("public int {0}Count {{", PropertyName);
- writer.WriteLine(" get {{ return {0}_.Count; }}", Name);
- writer.WriteLine("}");
-
- writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
- writer.WriteLine(" return {0}_[index];", Name);
- writer.WriteLine("}");
- }
-
- public void GenerateBuilderMembers(TextGenerator writer) {
- // Note: We can return the original list here, because we make it unmodifiable when we build
- // We return it via IPopsicleList so that collection initializers work more pleasantly.
- writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return result.{0}_; }}", Name);
- writer.WriteLine("}");
- writer.WriteLine("public int {0}Count {{", PropertyName);
- writer.WriteLine(" get {{ return result.{0}Count; }}", PropertyName);
- writer.WriteLine("}");
- writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
- writer.WriteLine(" return result.Get{0}(index);", PropertyName);
- writer.WriteLine("}");
- writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
- writer.WriteLine(" result.{0}_[index] = value;", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
- writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
- writer.WriteLine(" base.AddRange(values, result.{0}_);", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
- writer.WriteLine(" result.{0}_.Clear();", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- }
-
- public void GenerateMergingCode(TextGenerator writer) {
- writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
- writer.WriteLine(" base.AddRange(other.{0}_, result.{0}_);", Name);
- writer.WriteLine("}");
- }
-
- public void GenerateBuildingCode(TextGenerator writer) {
- writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
- }
-
- public void GenerateParsingCode(TextGenerator writer) {
- // If packed, set up the while loop
- if (Descriptor.IsPacked) {
- writer.WriteLine("int length = input.ReadInt32();");
- writer.WriteLine("int oldLimit = input.PushLimit(length);");
- writer.WriteLine("while (!input.ReachedLimit) {");
- writer.Indent();
- }
-
- // Read and store the enum
- // TODO(jonskeet): Make a more efficient way of doing this
- writer.WriteLine("int rawValue = input.ReadEnum();");
- writer.WriteLine("if (!global::System.Enum.IsDefined(typeof({0}), rawValue)) {{", TypeName);
- if (!UseLiteRuntime) {
- writer.WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now
- writer.WriteLine(" unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
- writer.WriteLine(" }");
- writer.WriteLine(" unknownFields.MergeVarintField({0}, (ulong) rawValue);", Number);
- }
- writer.WriteLine("} else {");
- writer.WriteLine(" Add{0}(({1}) rawValue);", PropertyName, TypeName);
- writer.WriteLine("}");
-
- if (Descriptor.IsPacked) {
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine("input.PopLimit(oldLimit);");
- }
- }
-
- public void GenerateSerializationCode(TextGenerator writer) {
- writer.WriteLine("if ({0}_.Count > 0) {{", Name);
- writer.Indent();
- if (Descriptor.IsPacked) {
- writer.WriteLine("output.WriteRawVarint32({0});", WireFormat.MakeTag(Descriptor));
- writer.WriteLine("output.WriteRawVarint32((uint) {0}MemoizedSerializedSize);", Name);
- writer.WriteLine("foreach (int element in {0}_) {{", Name);
- writer.WriteLine(" output.WriteEnumNoTag(element);");
- writer.WriteLine("}");
- } else {
- writer.WriteLine("foreach (int element in {0}_) {{", Name);
- writer.WriteLine(" output.WriteEnum({0}, element);", Number);
- writer.WriteLine("}");
- }
- writer.Outdent();
- writer.WriteLine("}");
- }
-
- public void GenerateSerializedSizeCode(TextGenerator writer) {
- writer.WriteLine("{");
- writer.Indent();
- writer.WriteLine("int dataSize = 0;");
- writer.WriteLine("if ({0}_.Count > 0) {{", Name);
- writer.Indent();
- writer.WriteLine("foreach ({0} element in {1}_) {{", TypeName, Name);
- writer.WriteLine(" dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);");
- writer.WriteLine("}");
- writer.WriteLine("size += dataSize;");
- int tagSize = CodedOutputStream.ComputeTagSize(Descriptor.FieldNumber);
- if (Descriptor.IsPacked) {
- writer.WriteLine("size += {0};", tagSize);
- writer.WriteLine("size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);");
- } else {
- writer.WriteLine("size += {0} * {1}_.Count;", tagSize, Name);
- }
- writer.Outdent();
- writer.WriteLine("}");
- // cache the data size for packed fields.
- if (Descriptor.IsPacked) {
- writer.WriteLine("{0}MemoizedSerializedSize = dataSize;", Name);
- }
- writer.Outdent();
- writer.WriteLine("}");
- }
-
- public override void WriteHash(TextGenerator writer) {
- writer.WriteLine("foreach({0} i in {1}_)", TypeName, Name);
- writer.WriteLine(" hash ^= i.GetHashCode();");
- }
-
- public override void WriteEquals(TextGenerator writer) {
- writer.WriteLine("if({0}_.Count != other.{0}_.Count) return false;", Name);
- writer.WriteLine("for(int ix=0; ix < {0}_.Count; ix++)", Name);
- writer.WriteLine(" if(!{0}_[ix].Equals(other.{0}_[ix])) return false;", Name);
- }
-
- public override void WriteToString(TextGenerator writer) {
- writer.WriteLine("PrintField(\"{0}\", {1}_, writer);", Descriptor.Name, Name);
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using Google.ProtocolBuffers.DescriptorProtos;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal class RepeatedEnumFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator
+ {
+ internal RepeatedEnumFieldGenerator(FieldDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
+
+ public void GenerateMembers(TextGenerator writer)
+ {
+ if (Descriptor.IsPacked && OptimizeSpeed)
+ {
+ writer.WriteLine("private int {0}MemoizedSerializedSize;", Name);
+ }
+ writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
+ writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, PropertyName);
+ writer.WriteLine(" get {{ return pbc::Lists.AsReadOnly({0}_); }}", Name);
+ writer.WriteLine("}");
+
+ // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
+ writer.WriteLine("public int {0}Count {{", PropertyName);
+ writer.WriteLine(" get {{ return {0}_.Count; }}", Name);
+ writer.WriteLine("}");
+
+ writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
+ writer.WriteLine(" return {0}_[index];", Name);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateBuilderMembers(TextGenerator writer)
+ {
+ // Note: We can return the original list here, because we make it unmodifiable when we build
+ // We return it via IPopsicleList so that collection initializers work more pleasantly.
+ writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
+ writer.WriteLine(" get {{ return result.{0}_; }}", Name);
+ writer.WriteLine("}");
+ writer.WriteLine("public int {0}Count {{", PropertyName);
+ writer.WriteLine(" get {{ return result.{0}Count; }}", PropertyName);
+ writer.WriteLine("}");
+ writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
+ writer.WriteLine(" return result.Get{0}(index);", PropertyName);
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
+ writer.WriteLine(" result.{0}_[index] = value;", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
+ writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+ writer.WriteLine(" base.AddRange(values, result.{0}_);", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" result.{0}_.Clear();", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ }
+
+ public void GenerateMergingCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
+ writer.WriteLine(" base.AddRange(other.{0}_, result.{0}_);", Name);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateBuildingCode(TextGenerator writer)
+ {
+ writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
+ }
+
+ public void GenerateParsingCode(TextGenerator writer)
+ {
+ // If packed, set up the while loop
+ if (Descriptor.IsPacked)
+ {
+ writer.WriteLine("int length = input.ReadInt32();");
+ writer.WriteLine("int oldLimit = input.PushLimit(length);");
+ writer.WriteLine("while (!input.ReachedLimit) {");
+ writer.Indent();
+ }
+
+ // Read and store the enum
+ // TODO(jonskeet): Make a more efficient way of doing this
+ writer.WriteLine("int rawValue = input.ReadEnum();");
+ writer.WriteLine("if (!global::System.Enum.IsDefined(typeof({0}), rawValue)) {{", TypeName);
+ if (!UseLiteRuntime)
+ {
+ writer.WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now
+ writer.WriteLine(" unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
+ writer.WriteLine(" }");
+ writer.WriteLine(" unknownFields.MergeVarintField({0}, (ulong) rawValue);", Number);
+ }
+ writer.WriteLine("} else {");
+ writer.WriteLine(" Add{0}(({1}) rawValue);", PropertyName, TypeName);
+ writer.WriteLine("}");
+
+ if (Descriptor.IsPacked)
+ {
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine("input.PopLimit(oldLimit);");
+ }
+ }
+
+ public void GenerateSerializationCode(TextGenerator writer)
+ {
+ writer.WriteLine("if ({0}_.Count > 0) {{", Name);
+ writer.Indent();
+ if (Descriptor.IsPacked)
+ {
+ writer.WriteLine("output.WriteRawVarint32({0});", WireFormat.MakeTag(Descriptor));
+ writer.WriteLine("output.WriteRawVarint32((uint) {0}MemoizedSerializedSize);", Name);
+ writer.WriteLine("foreach (int element in {0}_) {{", Name);
+ writer.WriteLine(" output.WriteEnumNoTag(element);");
+ writer.WriteLine("}");
+ }
+ else
+ {
+ writer.WriteLine("foreach (int element in {0}_) {{", Name);
+ writer.WriteLine(" output.WriteEnum({0}, element);", Number);
+ writer.WriteLine("}");
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+
+ public void GenerateSerializedSizeCode(TextGenerator writer)
+ {
+ writer.WriteLine("{");
+ writer.Indent();
+ writer.WriteLine("int dataSize = 0;");
+ writer.WriteLine("if ({0}_.Count > 0) {{", Name);
+ writer.Indent();
+ writer.WriteLine("foreach ({0} element in {1}_) {{", TypeName, Name);
+ writer.WriteLine(" dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);");
+ writer.WriteLine("}");
+ writer.WriteLine("size += dataSize;");
+ int tagSize = CodedOutputStream.ComputeTagSize(Descriptor.FieldNumber);
+ if (Descriptor.IsPacked)
+ {
+ writer.WriteLine("size += {0};", tagSize);
+ writer.WriteLine("size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);");
+ }
+ else
+ {
+ writer.WriteLine("size += {0} * {1}_.Count;", tagSize, Name);
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ // cache the data size for packed fields.
+ if (Descriptor.IsPacked)
+ {
+ writer.WriteLine("{0}MemoizedSerializedSize = dataSize;", Name);
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+
+ public override void WriteHash(TextGenerator writer)
+ {
+ writer.WriteLine("foreach({0} i in {1}_)", TypeName, Name);
+ writer.WriteLine(" hash ^= i.GetHashCode();");
+ }
+
+ public override void WriteEquals(TextGenerator writer)
+ {
+ writer.WriteLine("if({0}_.Count != other.{0}_.Count) return false;", Name);
+ writer.WriteLine("for(int ix=0; ix < {0}_.Count; ix++)", Name);
+ writer.WriteLine(" if(!{0}_[ix].Equals(other.{0}_[ix])) return false;", Name);
+ }
+
+ public override void WriteToString(TextGenerator writer)
+ {
+ writer.WriteLine("PrintField(\"{0}\", {1}_, writer);", Descriptor.Name, Name);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/RepeatedMessageFieldGenerator.cs b/src/ProtoGen/RepeatedMessageFieldGenerator.cs
index 4461190f..c882f562 100644
--- a/src/ProtoGen/RepeatedMessageFieldGenerator.cs
+++ b/src/ProtoGen/RepeatedMessageFieldGenerator.cs
@@ -1,153 +1,170 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal class RepeatedMessageFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
-
- internal RepeatedMessageFieldGenerator(FieldDescriptor descriptor)
- : base(descriptor) {
- }
-
- public void GenerateMembers(TextGenerator writer) {
- writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
- writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return {0}_; }}", Name);
- writer.WriteLine("}");
-
- // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
- writer.WriteLine("public int {0}Count {{", PropertyName);
- writer.WriteLine(" get {{ return {0}_.Count; }}", Name);
- writer.WriteLine("}");
-
- writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
- writer.WriteLine(" return {0}_[index];", Name);
- writer.WriteLine("}");
- }
-
- public void GenerateBuilderMembers(TextGenerator writer) {
- // Note: We can return the original list here, because we make it unmodifiable when we build
- // We return it via IPopsicleList so that collection initializers work more pleasantly.
- writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return result.{0}_; }}", Name);
- writer.WriteLine("}");
- writer.WriteLine("public int {0}Count {{", PropertyName);
- writer.WriteLine(" get {{ return result.{0}Count; }}", PropertyName);
- writer.WriteLine("}");
- writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
- writer.WriteLine(" return result.Get{0}(index);", PropertyName);
- writer.WriteLine("}");
- writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
- AddNullCheck(writer);
- writer.WriteLine(" result.{0}_[index] = value;", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- // Extra overload for builder (just on messages)
- writer.WriteLine("public Builder Set{0}(int index, {1}.Builder builderForValue) {{", PropertyName, TypeName);
- AddNullCheck(writer, "builderForValue");
- writer.WriteLine(" result.{0}_[index] = builderForValue.Build();", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
- AddNullCheck(writer);
- writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- // Extra overload for builder (just on messages)
- writer.WriteLine("public Builder Add{0}({1}.Builder builderForValue) {{", PropertyName, TypeName);
- AddNullCheck(writer, "builderForValue");
- writer.WriteLine(" result.{0}_.Add(builderForValue.Build());", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
- writer.WriteLine(" base.AddRange(values, result.{0}_);", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
- writer.WriteLine(" result.{0}_.Clear();", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- }
-
- public void GenerateMergingCode(TextGenerator writer) {
- writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
- writer.WriteLine(" base.AddRange(other.{0}_, result.{0}_);", Name);
- writer.WriteLine("}");
- }
-
- public void GenerateBuildingCode(TextGenerator writer) {
- writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
- }
-
- public void GenerateParsingCode(TextGenerator writer) {
- writer.WriteLine("{0}.Builder subBuilder = {0}.CreateBuilder();", TypeName);
- if (Descriptor.FieldType == FieldType.Group) {
- writer.WriteLine("input.ReadGroup({0}, subBuilder, extensionRegistry);", Number);
- } else {
- writer.WriteLine("input.ReadMessage(subBuilder, extensionRegistry);");
- }
- writer.WriteLine("Add{0}(subBuilder.BuildPartial());", PropertyName);
- }
-
- public void GenerateSerializationCode(TextGenerator writer) {
- writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, PropertyName);
- writer.WriteLine(" output.Write{0}({1}, element);", MessageOrGroup, Number);
- writer.WriteLine("}");
- }
-
- public void GenerateSerializedSizeCode(TextGenerator writer) {
- writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, PropertyName);
- writer.WriteLine(" size += pb::CodedOutputStream.Compute{0}Size({1}, element);", MessageOrGroup, Number);
- writer.WriteLine("}");
- }
-
- public override void WriteHash(TextGenerator writer) {
- writer.WriteLine("foreach({0} i in {1}_)", TypeName, Name);
- writer.WriteLine(" hash ^= i.GetHashCode();");
- }
-
- public override void WriteEquals(TextGenerator writer) {
- writer.WriteLine("if({0}_.Count != other.{0}_.Count) return false;", Name);
- writer.WriteLine("for(int ix=0; ix < {0}_.Count; ix++)", Name);
- writer.WriteLine(" if(!{0}_[ix].Equals(other.{0}_[ix])) return false;", Name);
- }
-
- public override void WriteToString(TextGenerator writer) {
- writer.WriteLine("PrintField(\"{0}\", {1}_, writer);",
- Descriptor.FieldType == FieldType.Group ? Descriptor.MessageType.Name : Descriptor.Name, Name);
- }
-
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal class RepeatedMessageFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator
+ {
+ internal RepeatedMessageFieldGenerator(FieldDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
+
+ public void GenerateMembers(TextGenerator writer)
+ {
+ writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
+ writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, PropertyName);
+ writer.WriteLine(" get {{ return {0}_; }}", Name);
+ writer.WriteLine("}");
+
+ // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
+ writer.WriteLine("public int {0}Count {{", PropertyName);
+ writer.WriteLine(" get {{ return {0}_.Count; }}", Name);
+ writer.WriteLine("}");
+
+ writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
+ writer.WriteLine(" return {0}_[index];", Name);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateBuilderMembers(TextGenerator writer)
+ {
+ // Note: We can return the original list here, because we make it unmodifiable when we build
+ // We return it via IPopsicleList so that collection initializers work more pleasantly.
+ writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
+ writer.WriteLine(" get {{ return result.{0}_; }}", Name);
+ writer.WriteLine("}");
+ writer.WriteLine("public int {0}Count {{", PropertyName);
+ writer.WriteLine(" get {{ return result.{0}Count; }}", PropertyName);
+ writer.WriteLine("}");
+ writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
+ writer.WriteLine(" return result.Get{0}(index);", PropertyName);
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
+ AddNullCheck(writer);
+ writer.WriteLine(" result.{0}_[index] = value;", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ // Extra overload for builder (just on messages)
+ writer.WriteLine("public Builder Set{0}(int index, {1}.Builder builderForValue) {{", PropertyName, TypeName);
+ AddNullCheck(writer, "builderForValue");
+ writer.WriteLine(" result.{0}_[index] = builderForValue.Build();", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
+ AddNullCheck(writer);
+ writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ // Extra overload for builder (just on messages)
+ writer.WriteLine("public Builder Add{0}({1}.Builder builderForValue) {{", PropertyName, TypeName);
+ AddNullCheck(writer, "builderForValue");
+ writer.WriteLine(" result.{0}_.Add(builderForValue.Build());", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+ writer.WriteLine(" base.AddRange(values, result.{0}_);", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" result.{0}_.Clear();", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ }
+
+ public void GenerateMergingCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
+ writer.WriteLine(" base.AddRange(other.{0}_, result.{0}_);", Name);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateBuildingCode(TextGenerator writer)
+ {
+ writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
+ }
+
+ public void GenerateParsingCode(TextGenerator writer)
+ {
+ writer.WriteLine("{0}.Builder subBuilder = {0}.CreateBuilder();", TypeName);
+ if (Descriptor.FieldType == FieldType.Group)
+ {
+ writer.WriteLine("input.ReadGroup({0}, subBuilder, extensionRegistry);", Number);
+ }
+ else
+ {
+ writer.WriteLine("input.ReadMessage(subBuilder, extensionRegistry);");
+ }
+ writer.WriteLine("Add{0}(subBuilder.BuildPartial());", PropertyName);
+ }
+
+ public void GenerateSerializationCode(TextGenerator writer)
+ {
+ writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, PropertyName);
+ writer.WriteLine(" output.Write{0}({1}, element);", MessageOrGroup, Number);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateSerializedSizeCode(TextGenerator writer)
+ {
+ writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, PropertyName);
+ writer.WriteLine(" size += pb::CodedOutputStream.Compute{0}Size({1}, element);", MessageOrGroup, Number);
+ writer.WriteLine("}");
+ }
+
+ public override void WriteHash(TextGenerator writer)
+ {
+ writer.WriteLine("foreach({0} i in {1}_)", TypeName, Name);
+ writer.WriteLine(" hash ^= i.GetHashCode();");
+ }
+
+ public override void WriteEquals(TextGenerator writer)
+ {
+ writer.WriteLine("if({0}_.Count != other.{0}_.Count) return false;", Name);
+ writer.WriteLine("for(int ix=0; ix < {0}_.Count; ix++)", Name);
+ writer.WriteLine(" if(!{0}_[ix].Equals(other.{0}_[ix])) return false;", Name);
+ }
+
+ public override void WriteToString(TextGenerator writer)
+ {
+ writer.WriteLine("PrintField(\"{0}\", {1}_, writer);",
+ Descriptor.FieldType == FieldType.Group ? Descriptor.MessageType.Name : Descriptor.Name,
+ Name);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs b/src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs
index d670c4ce..b7fe19b3 100644
--- a/src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs
+++ b/src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs
@@ -1,187 +1,216 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using Google.ProtocolBuffers.DescriptorProtos;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal class RepeatedPrimitiveFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
-
- internal RepeatedPrimitiveFieldGenerator(FieldDescriptor descriptor)
- : base(descriptor) {
- }
-
- public void GenerateMembers(TextGenerator writer) {
- if (Descriptor.IsPacked && OptimizeSpeed) {
- writer.WriteLine("private int {0}MemoizedSerializedSize;", Name);
- }
- writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
- AddClsComplianceCheck(writer);
- writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return pbc::Lists.AsReadOnly({0}_); }}", Name);
- writer.WriteLine("}");
-
- // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
- writer.WriteLine("public int {0}Count {{", PropertyName);
- writer.WriteLine(" get {{ return {0}_.Count; }}", Name);
- writer.WriteLine("}");
-
- AddClsComplianceCheck(writer);
- writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
- writer.WriteLine(" return {0}_[index];", Name);
- writer.WriteLine("}");
- }
-
- public void GenerateBuilderMembers(TextGenerator writer) {
- // Note: We can return the original list here, because we make it unmodifiable when we build
- // We return it via IPopsicleList so that collection initializers work more pleasantly.
- AddClsComplianceCheck(writer);
- writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
- writer.WriteLine(" get {{ return result.{0}_; }}", Name);
- writer.WriteLine("}");
- writer.WriteLine("public int {0}Count {{", PropertyName);
- writer.WriteLine(" get {{ return result.{0}Count; }}", PropertyName);
- writer.WriteLine("}");
- AddClsComplianceCheck(writer);
- writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
- writer.WriteLine(" return result.Get{0}(index);", PropertyName);
- writer.WriteLine("}");
- AddClsComplianceCheck(writer);
- writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
- AddNullCheck(writer);
- writer.WriteLine(" result.{0}_[index] = value;", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- AddClsComplianceCheck(writer);
- writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
- AddNullCheck(writer);
- writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- AddClsComplianceCheck(writer);
- writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
- writer.WriteLine(" base.AddRange(values, result.{0}_);", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
- writer.WriteLine(" result.{0}_.Clear();", Name);
- writer.WriteLine(" return this;");
- writer.WriteLine("}");
- }
-
- public void GenerateMergingCode(TextGenerator writer) {
- writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
- writer.WriteLine(" base.AddRange(other.{0}_, result.{0}_);", Name);
- writer.WriteLine("}");
- }
-
- public void GenerateBuildingCode(TextGenerator writer) {
- writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
- }
-
- public void GenerateParsingCode(TextGenerator writer) {
- if (Descriptor.IsPacked) {
- writer.WriteLine("int length = input.ReadInt32();");
- writer.WriteLine("int limit = input.PushLimit(length);");
- writer.WriteLine("while (!input.ReachedLimit) {");
- writer.WriteLine(" Add{0}(input.Read{1}());", PropertyName, CapitalizedTypeName);
- writer.WriteLine("}");
- writer.WriteLine("input.PopLimit(limit);");
- } else {
- writer.WriteLine("Add{0}(input.Read{1}());", PropertyName, CapitalizedTypeName);
- }
- }
-
- public void GenerateSerializationCode(TextGenerator writer) {
- writer.WriteLine("if ({0}_.Count > 0) {{", Name);
- writer.Indent();
- if (Descriptor.IsPacked) {
- writer.WriteLine("output.WriteRawVarint32({0});", WireFormat.MakeTag(Descriptor));
- writer.WriteLine("output.WriteRawVarint32((uint) {0}MemoizedSerializedSize);", Name);
- writer.WriteLine("foreach ({0} element in {1}_) {{", TypeName, Name);
- writer.WriteLine(" output.Write{0}NoTag(element);", CapitalizedTypeName);
- writer.WriteLine("}");
- } else {
- writer.WriteLine("foreach ({0} element in {1}_) {{", TypeName, Name);
- writer.WriteLine(" output.Write{0}({1}, element);", CapitalizedTypeName, Number);
- writer.WriteLine("}");
- }
- writer.Outdent();
- writer.WriteLine("}");
- }
-
- public void GenerateSerializedSizeCode(TextGenerator writer) {
- writer.WriteLine("{");
- writer.Indent();
- writer.WriteLine("int dataSize = 0;");
- if (FixedSize == -1) {
- writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, PropertyName);
- writer.WriteLine(" dataSize += pb::CodedOutputStream.Compute{0}SizeNoTag(element);", CapitalizedTypeName, Number);
- writer.WriteLine("}");
- } else {
- writer.WriteLine("dataSize = {0} * {1}_.Count;", FixedSize, Name);
- }
- writer.WriteLine("size += dataSize;");
- int tagSize = CodedOutputStream.ComputeTagSize(Descriptor.FieldNumber);
- if (Descriptor.IsPacked) {
- writer.WriteLine("if ({0}_.Count != 0) {{", Name);
- writer.WriteLine(" size += {0} + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);", tagSize);
- writer.WriteLine("}");
- } else {
- writer.WriteLine("size += {0} * {1}_.Count;", tagSize, Name);
- }
- // cache the data size for packed fields.
- if (Descriptor.IsPacked) {
- writer.WriteLine("{0}MemoizedSerializedSize = dataSize;", Name);
- }
- writer.Outdent();
- writer.WriteLine("}");
- }
-
- public override void WriteHash(TextGenerator writer) {
- writer.WriteLine("foreach({0} i in {1}_)", TypeName, Name);
- writer.WriteLine(" hash ^= i.GetHashCode();");
- }
-
- public override void WriteEquals(TextGenerator writer) {
- writer.WriteLine("if({0}_.Count != other.{0}_.Count) return false;", Name);
- writer.WriteLine("for(int ix=0; ix < {0}_.Count; ix++)", Name);
- writer.WriteLine(" if(!{0}_[ix].Equals(other.{0}_[ix])) return false;", Name);
- }
-
- public override void WriteToString(TextGenerator writer) {
- writer.WriteLine("PrintField(\"{0}\", {1}_, writer);", Descriptor.Name, Name);
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using Google.ProtocolBuffers.DescriptorProtos;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal class RepeatedPrimitiveFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator
+ {
+ internal RepeatedPrimitiveFieldGenerator(FieldDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
+
+ public void GenerateMembers(TextGenerator writer)
+ {
+ if (Descriptor.IsPacked && OptimizeSpeed)
+ {
+ writer.WriteLine("private int {0}MemoizedSerializedSize;", Name);
+ }
+ writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, PropertyName);
+ writer.WriteLine(" get {{ return pbc::Lists.AsReadOnly({0}_); }}", Name);
+ writer.WriteLine("}");
+
+ // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
+ writer.WriteLine("public int {0}Count {{", PropertyName);
+ writer.WriteLine(" get {{ return {0}_.Count; }}", Name);
+ writer.WriteLine("}");
+
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
+ writer.WriteLine(" return {0}_[index];", Name);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateBuilderMembers(TextGenerator writer)
+ {
+ // Note: We can return the original list here, because we make it unmodifiable when we build
+ // We return it via IPopsicleList so that collection initializers work more pleasantly.
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
+ writer.WriteLine(" get {{ return result.{0}_; }}", Name);
+ writer.WriteLine("}");
+ writer.WriteLine("public int {0}Count {{", PropertyName);
+ writer.WriteLine(" get {{ return result.{0}Count; }}", PropertyName);
+ writer.WriteLine("}");
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
+ writer.WriteLine(" return result.Get{0}(index);", PropertyName);
+ writer.WriteLine("}");
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
+ AddNullCheck(writer);
+ writer.WriteLine(" result.{0}_[index] = value;", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
+ AddNullCheck(writer);
+ writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ AddClsComplianceCheck(writer);
+ writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+ writer.WriteLine(" base.AddRange(values, result.{0}_);", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+ writer.WriteLine(" result.{0}_.Clear();", Name);
+ writer.WriteLine(" return this;");
+ writer.WriteLine("}");
+ }
+
+ public void GenerateMergingCode(TextGenerator writer)
+ {
+ writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
+ writer.WriteLine(" base.AddRange(other.{0}_, result.{0}_);", Name);
+ writer.WriteLine("}");
+ }
+
+ public void GenerateBuildingCode(TextGenerator writer)
+ {
+ writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
+ }
+
+ public void GenerateParsingCode(TextGenerator writer)
+ {
+ if (Descriptor.IsPacked)
+ {
+ writer.WriteLine("int length = input.ReadInt32();");
+ writer.WriteLine("int limit = input.PushLimit(length);");
+ writer.WriteLine("while (!input.ReachedLimit) {");
+ writer.WriteLine(" Add{0}(input.Read{1}());", PropertyName, CapitalizedTypeName);
+ writer.WriteLine("}");
+ writer.WriteLine("input.PopLimit(limit);");
+ }
+ else
+ {
+ writer.WriteLine("Add{0}(input.Read{1}());", PropertyName, CapitalizedTypeName);
+ }
+ }
+
+ public void GenerateSerializationCode(TextGenerator writer)
+ {
+ writer.WriteLine("if ({0}_.Count > 0) {{", Name);
+ writer.Indent();
+ if (Descriptor.IsPacked)
+ {
+ writer.WriteLine("output.WriteRawVarint32({0});", WireFormat.MakeTag(Descriptor));
+ writer.WriteLine("output.WriteRawVarint32((uint) {0}MemoizedSerializedSize);", Name);
+ writer.WriteLine("foreach ({0} element in {1}_) {{", TypeName, Name);
+ writer.WriteLine(" output.Write{0}NoTag(element);", CapitalizedTypeName);
+ writer.WriteLine("}");
+ }
+ else
+ {
+ writer.WriteLine("foreach ({0} element in {1}_) {{", TypeName, Name);
+ writer.WriteLine(" output.Write{0}({1}, element);", CapitalizedTypeName, Number);
+ writer.WriteLine("}");
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+
+ public void GenerateSerializedSizeCode(TextGenerator writer)
+ {
+ writer.WriteLine("{");
+ writer.Indent();
+ writer.WriteLine("int dataSize = 0;");
+ if (FixedSize == -1)
+ {
+ writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, PropertyName);
+ writer.WriteLine(" dataSize += pb::CodedOutputStream.Compute{0}SizeNoTag(element);",
+ CapitalizedTypeName, Number);
+ writer.WriteLine("}");
+ }
+ else
+ {
+ writer.WriteLine("dataSize = {0} * {1}_.Count;", FixedSize, Name);
+ }
+ writer.WriteLine("size += dataSize;");
+ int tagSize = CodedOutputStream.ComputeTagSize(Descriptor.FieldNumber);
+ if (Descriptor.IsPacked)
+ {
+ writer.WriteLine("if ({0}_.Count != 0) {{", Name);
+ writer.WriteLine(" size += {0} + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);", tagSize);
+ writer.WriteLine("}");
+ }
+ else
+ {
+ writer.WriteLine("size += {0} * {1}_.Count;", tagSize, Name);
+ }
+ // cache the data size for packed fields.
+ if (Descriptor.IsPacked)
+ {
+ writer.WriteLine("{0}MemoizedSerializedSize = dataSize;", Name);
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+
+ public override void WriteHash(TextGenerator writer)
+ {
+ writer.WriteLine("foreach({0} i in {1}_)", TypeName, Name);
+ writer.WriteLine(" hash ^= i.GetHashCode();");
+ }
+
+ public override void WriteEquals(TextGenerator writer)
+ {
+ writer.WriteLine("if({0}_.Count != other.{0}_.Count) return false;", Name);
+ writer.WriteLine("for(int ix=0; ix < {0}_.Count; ix++)", Name);
+ writer.WriteLine(" if(!{0}_[ix].Equals(other.{0}_[ix])) return false;", Name);
+ }
+
+ public override void WriteToString(TextGenerator writer)
+ {
+ writer.WriteLine("PrintField(\"{0}\", {1}_, writer);", Descriptor.Name, Name);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/ServiceGenerator.cs b/src/ProtoGen/ServiceGenerator.cs
index 3c70b9ce..baeee4f4 100644
--- a/src/ProtoGen/ServiceGenerator.cs
+++ b/src/ProtoGen/ServiceGenerator.cs
@@ -1,169 +1,185 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal class GenericServiceGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator {
-
- private enum RequestOrResponse {
- Request,
- Response
- }
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal class GenericServiceGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator
+ {
+ private enum RequestOrResponse
+ {
+ Request,
+ Response
+ }
+
+ internal GenericServiceGenerator(ServiceDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
+
+ public void Generate(TextGenerator writer)
+ {
+ writer.WriteLine("{0} abstract class {1} : pb::IService {{", ClassAccessLevel, Descriptor.Name);
+ writer.Indent();
+
+ foreach (MethodDescriptor method in Descriptor.Methods)
+ {
+ writer.WriteLine("{0} abstract void {1}(", ClassAccessLevel,
+ NameHelpers.UnderscoresToPascalCase(method.Name));
+ writer.WriteLine(" pb::IRpcController controller,");
+ writer.WriteLine(" {0} request,", GetClassName(method.InputType));
+ writer.WriteLine(" global::System.Action<{0}> done);", GetClassName(method.OutputType));
+ }
- internal GenericServiceGenerator(ServiceDescriptor descriptor)
- : base(descriptor) {
- }
-
- public void Generate(TextGenerator writer) {
- writer.WriteLine("{0} abstract class {1} : pb::IService {{", ClassAccessLevel, Descriptor.Name);
- writer.Indent();
-
- foreach (MethodDescriptor method in Descriptor.Methods) {
- writer.WriteLine("{0} abstract void {1}(", ClassAccessLevel, NameHelpers.UnderscoresToPascalCase(method.Name));
- writer.WriteLine(" pb::IRpcController controller,");
- writer.WriteLine(" {0} request,", GetClassName(method.InputType));
- writer.WriteLine(" global::System.Action<{0}> done);", GetClassName(method.OutputType));
- }
-
- // Generate Descriptor and DescriptorForType.
- writer.WriteLine();
- writer.WriteLine("{0} static pbd::ServiceDescriptor Descriptor {{", ClassAccessLevel);
- writer.WriteLine(" get {{ return {0}.Descriptor.Services[{1}]; }}",
- DescriptorUtil.GetQualifiedUmbrellaClassName(Descriptor.File.CSharpOptions), Descriptor.Index);
- writer.WriteLine("}");
- writer.WriteLine("{0} pbd::ServiceDescriptor DescriptorForType {{", ClassAccessLevel);
- writer.WriteLine(" get { return Descriptor; }");
- writer.WriteLine("}");
-
- GenerateCallMethod(writer);
- GenerateGetPrototype(RequestOrResponse.Request, writer);
- GenerateGetPrototype(RequestOrResponse.Response, writer);
- GenerateStub(writer);
-
- writer.Outdent();
- writer.WriteLine("}");
- }
-
- private void GenerateCallMethod(TextGenerator writer) {
- writer.WriteLine();
- writer.WriteLine("public void CallMethod(", ClassAccessLevel);
- writer.WriteLine(" pbd::MethodDescriptor method,");
- writer.WriteLine(" pb::IRpcController controller,");
- writer.WriteLine(" pb::IMessage request,");
- writer.WriteLine(" global::System.Action<pb::IMessage> done) {");
- writer.Indent();
- writer.WriteLine("if (method.Service != Descriptor) {");
- writer.WriteLine(" throw new global::System.ArgumentException(");
- writer.WriteLine(" \"Service.CallMethod() given method descriptor for wrong service type.\");");
- writer.WriteLine("}");
- writer.WriteLine("switch(method.Index) {");
- writer.Indent();
- foreach (MethodDescriptor method in Descriptor.Methods) {
- writer.WriteLine("case {0}:", method.Index);
- writer.WriteLine(" this.{0}(controller, ({1}) request,",
- NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType));
- writer.WriteLine(" pb::RpcUtil.SpecializeCallback<{0}>(", GetClassName(method.OutputType));
- writer.WriteLine(" done));");
- writer.WriteLine(" return;");
- }
- writer.WriteLine("default:");
- writer.WriteLine(" throw new global::System.InvalidOperationException(\"Can't get here.\");");
- writer.Outdent();
- writer.WriteLine("}");
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
- }
-
- private void GenerateGetPrototype(RequestOrResponse which, TextGenerator writer) {
- writer.WriteLine("public pb::IMessage Get{0}Prototype(pbd::MethodDescriptor method) {{", which);
- writer.Indent();
- writer.WriteLine("if (method.Service != Descriptor) {");
- writer.WriteLine(" throw new global::System.ArgumentException(");
- writer.WriteLine(" \"Service.Get{0}Prototype() given method descriptor for wrong service type.\");", which);
- writer.WriteLine("}");
- writer.WriteLine("switch(method.Index) {");
- writer.Indent();
-
- foreach (MethodDescriptor method in Descriptor.Methods) {
- writer.WriteLine("case {0}:", method.Index);
- writer.WriteLine(" return {0}.DefaultInstance;",
- GetClassName(which == RequestOrResponse.Request ? method.InputType : method.OutputType));
- }
- writer.WriteLine("default:");
- writer.WriteLine(" throw new global::System.InvalidOperationException(\"Can't get here.\");");
- writer.Outdent();
- writer.WriteLine("}");
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine();
- }
-
- private void GenerateStub(TextGenerator writer) {
- writer.WriteLine("public static Stub CreateStub(pb::IRpcChannel channel) {");
- writer.WriteLine(" return new Stub(channel);");
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("{0} class Stub : {1} {{", ClassAccessLevel, GetClassName(Descriptor));
- writer.Indent();
- writer.WriteLine("internal Stub(pb::IRpcChannel channel) {");
- writer.WriteLine(" this.channel = channel;");
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("private readonly pb::IRpcChannel channel;");
- writer.WriteLine();
- writer.WriteLine("public pb::IRpcChannel Channel {");
- writer.WriteLine(" get { return channel; }");
- writer.WriteLine("}");
-
- foreach (MethodDescriptor method in Descriptor.Methods) {
- writer.WriteLine();
- writer.WriteLine("public override void {0}(", NameHelpers.UnderscoresToPascalCase(method.Name));
- writer.WriteLine(" pb::IRpcController controller,");
- writer.WriteLine(" {0} request,", GetClassName(method.InputType));
- writer.WriteLine(" global::System.Action<{0}> done) {{", GetClassName(method.OutputType));
- writer.Indent();
- writer.WriteLine("channel.CallMethod(Descriptor.Methods[{0}],", method.Index);
- writer.WriteLine(" controller, request, {0}.DefaultInstance,", GetClassName(method.OutputType));
- writer.WriteLine(" pb::RpcUtil.GeneralizeCallback<{0}, {0}.Builder>(done, {0}.DefaultInstance));",
- GetClassName(method.OutputType));
- writer.Outdent();
- writer.WriteLine("}");
- }
- writer.Outdent();
- writer.WriteLine("}");
- }
- }
-}
+ // Generate Descriptor and DescriptorForType.
+ writer.WriteLine();
+ writer.WriteLine("{0} static pbd::ServiceDescriptor Descriptor {{", ClassAccessLevel);
+ writer.WriteLine(" get {{ return {0}.Descriptor.Services[{1}]; }}",
+ DescriptorUtil.GetQualifiedUmbrellaClassName(Descriptor.File.CSharpOptions),
+ Descriptor.Index);
+ writer.WriteLine("}");
+ writer.WriteLine("{0} pbd::ServiceDescriptor DescriptorForType {{", ClassAccessLevel);
+ writer.WriteLine(" get { return Descriptor; }");
+ writer.WriteLine("}");
+
+ GenerateCallMethod(writer);
+ GenerateGetPrototype(RequestOrResponse.Request, writer);
+ GenerateGetPrototype(RequestOrResponse.Response, writer);
+ GenerateStub(writer);
+
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+
+ private void GenerateCallMethod(TextGenerator writer)
+ {
+ writer.WriteLine();
+ writer.WriteLine("public void CallMethod(", ClassAccessLevel);
+ writer.WriteLine(" pbd::MethodDescriptor method,");
+ writer.WriteLine(" pb::IRpcController controller,");
+ writer.WriteLine(" pb::IMessage request,");
+ writer.WriteLine(" global::System.Action<pb::IMessage> done) {");
+ writer.Indent();
+ writer.WriteLine("if (method.Service != Descriptor) {");
+ writer.WriteLine(" throw new global::System.ArgumentException(");
+ writer.WriteLine(" \"Service.CallMethod() given method descriptor for wrong service type.\");");
+ writer.WriteLine("}");
+ writer.WriteLine("switch(method.Index) {");
+ writer.Indent();
+ foreach (MethodDescriptor method in Descriptor.Methods)
+ {
+ writer.WriteLine("case {0}:", method.Index);
+ writer.WriteLine(" this.{0}(controller, ({1}) request,",
+ NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType));
+ writer.WriteLine(" pb::RpcUtil.SpecializeCallback<{0}>(", GetClassName(method.OutputType));
+ writer.WriteLine(" done));");
+ writer.WriteLine(" return;");
+ }
+ writer.WriteLine("default:");
+ writer.WriteLine(" throw new global::System.InvalidOperationException(\"Can't get here.\");");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+ }
+
+ private void GenerateGetPrototype(RequestOrResponse which, TextGenerator writer)
+ {
+ writer.WriteLine("public pb::IMessage Get{0}Prototype(pbd::MethodDescriptor method) {{", which);
+ writer.Indent();
+ writer.WriteLine("if (method.Service != Descriptor) {");
+ writer.WriteLine(" throw new global::System.ArgumentException(");
+ writer.WriteLine(" \"Service.Get{0}Prototype() given method descriptor for wrong service type.\");",
+ which);
+ writer.WriteLine("}");
+ writer.WriteLine("switch(method.Index) {");
+ writer.Indent();
+
+ foreach (MethodDescriptor method in Descriptor.Methods)
+ {
+ writer.WriteLine("case {0}:", method.Index);
+ writer.WriteLine(" return {0}.DefaultInstance;",
+ GetClassName(which == RequestOrResponse.Request ? method.InputType : method.OutputType));
+ }
+ writer.WriteLine("default:");
+ writer.WriteLine(" throw new global::System.InvalidOperationException(\"Can't get here.\");");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine();
+ }
+
+ private void GenerateStub(TextGenerator writer)
+ {
+ writer.WriteLine("public static Stub CreateStub(pb::IRpcChannel channel) {");
+ writer.WriteLine(" return new Stub(channel);");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine("{0} class Stub : {1} {{", ClassAccessLevel, GetClassName(Descriptor));
+ writer.Indent();
+ writer.WriteLine("internal Stub(pb::IRpcChannel channel) {");
+ writer.WriteLine(" this.channel = channel;");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine("private readonly pb::IRpcChannel channel;");
+ writer.WriteLine();
+ writer.WriteLine("public pb::IRpcChannel Channel {");
+ writer.WriteLine(" get { return channel; }");
+ writer.WriteLine("}");
+
+ foreach (MethodDescriptor method in Descriptor.Methods)
+ {
+ writer.WriteLine();
+ writer.WriteLine("public override void {0}(", NameHelpers.UnderscoresToPascalCase(method.Name));
+ writer.WriteLine(" pb::IRpcController controller,");
+ writer.WriteLine(" {0} request,", GetClassName(method.InputType));
+ writer.WriteLine(" global::System.Action<{0}> done) {{", GetClassName(method.OutputType));
+ writer.Indent();
+ writer.WriteLine("channel.CallMethod(Descriptor.Methods[{0}],", method.Index);
+ writer.WriteLine(" controller, request, {0}.DefaultInstance,", GetClassName(method.OutputType));
+ writer.WriteLine(" pb::RpcUtil.GeneralizeCallback<{0}, {0}.Builder>(done, {0}.DefaultInstance));",
+ GetClassName(method.OutputType));
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/ServiceInterfaceGenerator.cs b/src/ProtoGen/ServiceInterfaceGenerator.cs
index 019df4c8..698b7016 100644
--- a/src/ProtoGen/ServiceInterfaceGenerator.cs
+++ b/src/ProtoGen/ServiceInterfaceGenerator.cs
@@ -1,4 +1,5 @@
#region Copyright notice and license
+
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// http://github.com/jskeet/dotnet-protobufs/
@@ -30,6 +31,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
#endregion
using System;
@@ -37,215 +39,255 @@ using System.Collections.Generic;
using Google.ProtocolBuffers.DescriptorProtos;
using Google.ProtocolBuffers.Descriptors;
-namespace Google.ProtocolBuffers.ProtoGen {
- internal class ServiceGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator {
-
- readonly CSharpServiceType svcType;
- ISourceGenerator _generator;
-
- internal ServiceGenerator(ServiceDescriptor descriptor)
- : base(descriptor) {
- svcType = descriptor.File.CSharpOptions.ServiceGeneratorType;
- switch (svcType) {
- case CSharpServiceType.NONE:
- _generator = new NoServicesGenerator(descriptor);
- break;
- case CSharpServiceType.GENERIC:
- _generator = new GenericServiceGenerator(descriptor);
- break;
- case CSharpServiceType.INTERFACE:
- _generator = new ServiceInterfaceGenerator(descriptor);
- break;
- case CSharpServiceType.IRPCDISPATCH:
- _generator = new RpcServiceGenerator(descriptor);
- break;
- default: throw new ApplicationException("Unknown ServiceGeneratorType = " + svcType.ToString());
- }
- }
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal class ServiceGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator
+ {
+ private readonly CSharpServiceType svcType;
+ private ISourceGenerator _generator;
- public void Generate(TextGenerator writer) {
- _generator.Generate(writer);
- }
-
- class NoServicesGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator {
-
- public NoServicesGenerator(ServiceDescriptor descriptor)
- : base(descriptor) {
- }
- public virtual void Generate(TextGenerator writer) {
- writer.WriteLine("/*");
- writer.WriteLine("* Service generation is now disabled by default, use the following option to enable:");
- writer.WriteLine("* option (google.protobuf.csharp_file_options).service_generator_type = GENERIC;");
- writer.WriteLine("*/");
- }
- }
+ internal ServiceGenerator(ServiceDescriptor descriptor)
+ : base(descriptor)
+ {
+ svcType = descriptor.File.CSharpOptions.ServiceGeneratorType;
+ switch (svcType)
+ {
+ case CSharpServiceType.NONE:
+ _generator = new NoServicesGenerator(descriptor);
+ break;
+ case CSharpServiceType.GENERIC:
+ _generator = new GenericServiceGenerator(descriptor);
+ break;
+ case CSharpServiceType.INTERFACE:
+ _generator = new ServiceInterfaceGenerator(descriptor);
+ break;
+ case CSharpServiceType.IRPCDISPATCH:
+ _generator = new RpcServiceGenerator(descriptor);
+ break;
+ default:
+ throw new ApplicationException("Unknown ServiceGeneratorType = " + svcType.ToString());
+ }
+ }
- class ServiceInterfaceGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator {
-
- public ServiceInterfaceGenerator(ServiceDescriptor descriptor)
- : base(descriptor) {
- }
+ public void Generate(TextGenerator writer)
+ {
+ _generator.Generate(writer);
+ }
- public virtual void Generate(TextGenerator writer) {
+ private class NoServicesGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator
+ {
+ public NoServicesGenerator(ServiceDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
- CSharpServiceOptions options = Descriptor.Options.GetExtension(CSharpOptions.CsharpServiceOptions);
- if (options != null && options.HasInterfaceId) {
- writer.WriteLine("[global::System.Runtime.InteropServices.GuidAttribute(\"{0}\")]", new Guid(options.InterfaceId));
+ public virtual void Generate(TextGenerator writer)
+ {
+ writer.WriteLine("/*");
+ writer.WriteLine("* Service generation is now disabled by default, use the following option to enable:");
+ writer.WriteLine("* option (google.protobuf.csharp_file_options).service_generator_type = GENERIC;");
+ writer.WriteLine("*/");
+ }
}
- writer.WriteLine("{0} partial interface I{1} {{", ClassAccessLevel, Descriptor.Name);
- writer.Indent();
- foreach (MethodDescriptor method in Descriptor.Methods)
+ private class ServiceInterfaceGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator
{
- CSharpMethodOptions mth = method.Options.GetExtension(CSharpOptions.CsharpMethodOptions);
- if(mth.HasDispatchId) {
- writer.WriteLine("[global::System.Runtime.InteropServices.DispId({0})]", mth.DispatchId);
- }
- writer.WriteLine("{0} {1}({2} {3});", GetClassName(method.OutputType), NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType), NameHelpers.UnderscoresToCamelCase(method.InputType.Name));
+ public ServiceInterfaceGenerator(ServiceDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
+
+ public virtual void Generate(TextGenerator writer)
+ {
+ CSharpServiceOptions options = Descriptor.Options.GetExtension(CSharpOptions.CsharpServiceOptions);
+ if (options != null && options.HasInterfaceId)
+ {
+ writer.WriteLine("[global::System.Runtime.InteropServices.GuidAttribute(\"{0}\")]",
+ new Guid(options.InterfaceId));
+ }
+ writer.WriteLine("{0} partial interface I{1} {{", ClassAccessLevel, Descriptor.Name);
+ writer.Indent();
+
+ foreach (MethodDescriptor method in Descriptor.Methods)
+ {
+ CSharpMethodOptions mth = method.Options.GetExtension(CSharpOptions.CsharpMethodOptions);
+ if (mth.HasDispatchId)
+ {
+ writer.WriteLine("[global::System.Runtime.InteropServices.DispId({0})]", mth.DispatchId);
+ }
+ writer.WriteLine("{0} {1}({2} {3});", GetClassName(method.OutputType),
+ NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType),
+ NameHelpers.UnderscoresToCamelCase(method.InputType.Name));
+ }
+
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
}
- writer.Outdent();
- writer.WriteLine("}");
- }
- }
-
- class RpcServiceGenerator : ServiceInterfaceGenerator {
+ private class RpcServiceGenerator : ServiceInterfaceGenerator
+ {
+ public RpcServiceGenerator(ServiceDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
- public RpcServiceGenerator(ServiceDescriptor descriptor)
- : base(descriptor) {
- }
+ public override void Generate(TextGenerator writer)
+ {
+ base.Generate(writer);
- public override void Generate(TextGenerator writer)
- {
- base.Generate(writer);
+ writer.WriteLine();
- writer.WriteLine();
+ // CLIENT Proxy
+ {
+ if (Descriptor.File.CSharpOptions.ClsCompliance)
+ writer.WriteLine("[global::System.CLSCompliant(false)]");
+ writer.WriteLine("{0} partial class {1} : I{1}, pb::IRpcDispatch, global::System.IDisposable {{",
+ ClassAccessLevel, Descriptor.Name);
+ writer.Indent();
+ writer.WriteLine("private readonly bool dispose;");
+ writer.WriteLine("private readonly pb::IRpcDispatch dispatch;");
- // CLIENT Proxy
- {
- if (Descriptor.File.CSharpOptions.ClsCompliance)
- writer.WriteLine("[global::System.CLSCompliant(false)]");
- writer.WriteLine("{0} partial class {1} : I{1}, pb::IRpcDispatch, global::System.IDisposable {{", ClassAccessLevel, Descriptor.Name);
- writer.Indent();
- writer.WriteLine("private readonly bool dispose;");
- writer.WriteLine("private readonly pb::IRpcDispatch dispatch;");
-
- writer.WriteLine("public {0}(pb::IRpcDispatch dispatch) : this(dispatch, true) {{", Descriptor.Name);
- writer.WriteLine("}");
- writer.WriteLine("public {0}(pb::IRpcDispatch dispatch, bool dispose) {{", Descriptor.Name);
- writer.WriteLine(" if (null == (this.dispatch = dispatch)) throw new global::System.ArgumentNullException();");
- writer.WriteLine(" this.dispose = dispose && dispatch is global::System.IDisposable;");
- writer.WriteLine("}");
- writer.WriteLine();
-
- writer.WriteLine("public void Dispose() {");
- writer.WriteLine(" if (dispose) ((global::System.IDisposable)dispatch).Dispose();");
- writer.WriteLine("}");
- writer.WriteLine();
- writer.WriteLine("TMessage pb::IRpcDispatch.CallMethod<TMessage, TBuilder>(string method, pb::IMessageLite request, pb::IBuilderLite<TMessage, TBuilder> response) {");
- writer.WriteLine(" return dispatch.CallMethod(method, request, response);");
- writer.WriteLine("}");
- writer.WriteLine();
-
- foreach (MethodDescriptor method in Descriptor.Methods) {
- writer.WriteLine("public {0} {1}({2} {3}) {{", GetClassName(method.OutputType), NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType), NameHelpers.UnderscoresToCamelCase(method.InputType.Name));
- writer.WriteLine(" return dispatch.CallMethod(\"{0}\", {1}, {2}.CreateBuilder());",
- method.Name,
- NameHelpers.UnderscoresToCamelCase(method.InputType.Name),
- GetClassName(method.OutputType)
- );
- writer.WriteLine("}");
- writer.WriteLine();
- }
- }
- // SERVER - DISPATCH
- {
- if (Descriptor.File.CSharpOptions.ClsCompliance)
- writer.WriteLine("[global::System.CLSCompliant(false)]");
- writer.WriteLine("public partial class Dispatch : pb::IRpcDispatch, global::System.IDisposable {");
- writer.Indent();
- writer.WriteLine("private readonly bool dispose;");
- writer.WriteLine("private readonly I{0} implementation;", Descriptor.Name);
-
- writer.WriteLine("public Dispatch(I{0} implementation) : this(implementation, true) {{", Descriptor.Name);
- writer.WriteLine("}");
- writer.WriteLine("public Dispatch(I{0} implementation, bool dispose) {{", Descriptor.Name);
- writer.WriteLine(" if (null == (this.implementation = implementation)) throw new global::System.ArgumentNullException();");
- writer.WriteLine(" this.dispose = dispose && implementation is global::System.IDisposable;");
- writer.WriteLine("}");
- writer.WriteLine();
-
- writer.WriteLine("public void Dispose() {");
- writer.WriteLine(" if (dispose) ((global::System.IDisposable)implementation).Dispose();");
- writer.WriteLine("}");
- writer.WriteLine();
-
- writer.WriteLine("public TMessage CallMethod<TMessage, TBuilder>(string methodName, pb::IMessageLite request, pb::IBuilderLite<TMessage, TBuilder> response)");
- writer.WriteLine(" where TMessage : IMessageLite<TMessage, TBuilder>");
- writer.WriteLine(" where TBuilder : IBuilderLite<TMessage, TBuilder> {");
- writer.Indent();
- writer.WriteLine("switch(methodName) {");
- writer.Indent();
-
- foreach (MethodDescriptor method in Descriptor.Methods) {
- writer.WriteLine("case \"{0}\": return response.MergeFrom(implementation.{1}(({2})request)).Build();", method.Name, NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType));
- }
- writer.WriteLine("default: throw new global::System.MissingMethodException(typeof(ISearchService).FullName, methodName);");
- writer.Outdent();
- writer.WriteLine("}");//end switch
- writer.Outdent();
- writer.WriteLine("}");//end invoke
- writer.Outdent();
- writer.WriteLine("}");//end server
- }
- // SERVER - STUB
- {
- if (Descriptor.File.CSharpOptions.ClsCompliance)
- writer.WriteLine("[global::System.CLSCompliant(false)]");
- writer.WriteLine("public partial class ServerStub : pb::IRpcServerStub, global::System.IDisposable {");
- writer.Indent();
- writer.WriteLine("private readonly bool dispose;");
- writer.WriteLine("private readonly pb::IRpcDispatch implementation;", Descriptor.Name);
-
- writer.WriteLine("public ServerStub(I{0} implementation) : this(implementation, true) {{", Descriptor.Name);
- writer.WriteLine("}");
- writer.WriteLine("public ServerStub(I{0} implementation, bool dispose) : this(new Dispatch(implementation, dispose), dispose) {{", Descriptor.Name);
- writer.WriteLine("}");
-
- writer.WriteLine("public ServerStub(pb::IRpcDispatch implementation) : this(implementation, true) {");
- writer.WriteLine("}");
- writer.WriteLine("public ServerStub(pb::IRpcDispatch implementation, bool dispose) {");
- writer.WriteLine(" if (null == (this.implementation = implementation)) throw new global::System.ArgumentNullException();");
- writer.WriteLine(" this.dispose = dispose && implementation is global::System.IDisposable;");
- writer.WriteLine("}");
- writer.WriteLine();
-
- writer.WriteLine("public void Dispose() {");
- writer.WriteLine(" if (dispose) ((global::System.IDisposable)implementation).Dispose();");
- writer.WriteLine("}");
- writer.WriteLine();
-
- writer.WriteLine("public pb::IMessageLite CallMethod(string methodName, pb::CodedInputStream input, pb::ExtensionRegistry registry) {{", Descriptor.Name);
- writer.Indent();
- writer.WriteLine("switch(methodName) {");
- writer.Indent();
-
- foreach (MethodDescriptor method in Descriptor.Methods)
- {
- writer.WriteLine("case \"{0}\": return implementation.CallMethod(methodName, {1}.ParseFrom(input, registry), {2}.CreateBuilder());", method.Name, GetClassName(method.InputType), GetClassName(method.OutputType));
- }
- writer.WriteLine("default: throw new global::System.MissingMethodException(typeof(ISearchService).FullName, methodName);");
- writer.Outdent();
- writer.WriteLine("}");//end switch
- writer.Outdent();
- writer.WriteLine("}");//end invoke
- writer.Outdent();
- writer.WriteLine("}");//end server
- }
+ writer.WriteLine("public {0}(pb::IRpcDispatch dispatch) : this(dispatch, true) {{", Descriptor.Name);
+ writer.WriteLine("}");
+ writer.WriteLine("public {0}(pb::IRpcDispatch dispatch, bool dispose) {{", Descriptor.Name);
+ writer.WriteLine(
+ " if (null == (this.dispatch = dispatch)) throw new global::System.ArgumentNullException();");
+ writer.WriteLine(" this.dispose = dispose && dispatch is global::System.IDisposable;");
+ writer.WriteLine("}");
+ writer.WriteLine();
+
+ writer.WriteLine("public void Dispose() {");
+ writer.WriteLine(" if (dispose) ((global::System.IDisposable)dispatch).Dispose();");
+ writer.WriteLine("}");
+ writer.WriteLine();
+ writer.WriteLine(
+ "TMessage pb::IRpcDispatch.CallMethod<TMessage, TBuilder>(string method, pb::IMessageLite request, pb::IBuilderLite<TMessage, TBuilder> response) {");
+ writer.WriteLine(" return dispatch.CallMethod(method, request, response);");
+ writer.WriteLine("}");
+ writer.WriteLine();
+
+ foreach (MethodDescriptor method in Descriptor.Methods)
+ {
+ writer.WriteLine("public {0} {1}({2} {3}) {{", GetClassName(method.OutputType),
+ NameHelpers.UnderscoresToPascalCase(method.Name),
+ GetClassName(method.InputType),
+ NameHelpers.UnderscoresToCamelCase(method.InputType.Name));
+ writer.WriteLine(" return dispatch.CallMethod(\"{0}\", {1}, {2}.CreateBuilder());",
+ method.Name,
+ NameHelpers.UnderscoresToCamelCase(method.InputType.Name),
+ GetClassName(method.OutputType)
+ );
+ writer.WriteLine("}");
+ writer.WriteLine();
+ }
+ }
+ // SERVER - DISPATCH
+ {
+ if (Descriptor.File.CSharpOptions.ClsCompliance)
+ writer.WriteLine("[global::System.CLSCompliant(false)]");
+ writer.WriteLine("public partial class Dispatch : pb::IRpcDispatch, global::System.IDisposable {");
+ writer.Indent();
+ writer.WriteLine("private readonly bool dispose;");
+ writer.WriteLine("private readonly I{0} implementation;", Descriptor.Name);
+
+ writer.WriteLine("public Dispatch(I{0} implementation) : this(implementation, true) {{",
+ Descriptor.Name);
+ writer.WriteLine("}");
+ writer.WriteLine("public Dispatch(I{0} implementation, bool dispose) {{", Descriptor.Name);
+ writer.WriteLine(
+ " if (null == (this.implementation = implementation)) throw new global::System.ArgumentNullException();");
+ writer.WriteLine(" this.dispose = dispose && implementation is global::System.IDisposable;");
+ writer.WriteLine("}");
+ writer.WriteLine();
+
+ writer.WriteLine("public void Dispose() {");
+ writer.WriteLine(" if (dispose) ((global::System.IDisposable)implementation).Dispose();");
+ writer.WriteLine("}");
+ writer.WriteLine();
- writer.Outdent();
- writer.WriteLine("}");
- }
+ writer.WriteLine(
+ "public TMessage CallMethod<TMessage, TBuilder>(string methodName, pb::IMessageLite request, pb::IBuilderLite<TMessage, TBuilder> response)");
+ writer.WriteLine(" where TMessage : IMessageLite<TMessage, TBuilder>");
+ writer.WriteLine(" where TBuilder : IBuilderLite<TMessage, TBuilder> {");
+ writer.Indent();
+ writer.WriteLine("switch(methodName) {");
+ writer.Indent();
+
+ foreach (MethodDescriptor method in Descriptor.Methods)
+ {
+ writer.WriteLine(
+ "case \"{0}\": return response.MergeFrom(implementation.{1}(({2})request)).Build();",
+ method.Name, NameHelpers.UnderscoresToPascalCase(method.Name),
+ GetClassName(method.InputType));
+ }
+ writer.WriteLine(
+ "default: throw new global::System.MissingMethodException(typeof(ISearchService).FullName, methodName);");
+ writer.Outdent();
+ writer.WriteLine("}"); //end switch
+ writer.Outdent();
+ writer.WriteLine("}"); //end invoke
+ writer.Outdent();
+ writer.WriteLine("}"); //end server
+ }
+ // SERVER - STUB
+ {
+ if (Descriptor.File.CSharpOptions.ClsCompliance)
+ writer.WriteLine("[global::System.CLSCompliant(false)]");
+ writer.WriteLine(
+ "public partial class ServerStub : pb::IRpcServerStub, global::System.IDisposable {");
+ writer.Indent();
+ writer.WriteLine("private readonly bool dispose;");
+ writer.WriteLine("private readonly pb::IRpcDispatch implementation;", Descriptor.Name);
+
+ writer.WriteLine("public ServerStub(I{0} implementation) : this(implementation, true) {{",
+ Descriptor.Name);
+ writer.WriteLine("}");
+ writer.WriteLine(
+ "public ServerStub(I{0} implementation, bool dispose) : this(new Dispatch(implementation, dispose), dispose) {{",
+ Descriptor.Name);
+ writer.WriteLine("}");
+
+ writer.WriteLine("public ServerStub(pb::IRpcDispatch implementation) : this(implementation, true) {");
+ writer.WriteLine("}");
+ writer.WriteLine("public ServerStub(pb::IRpcDispatch implementation, bool dispose) {");
+ writer.WriteLine(
+ " if (null == (this.implementation = implementation)) throw new global::System.ArgumentNullException();");
+ writer.WriteLine(" this.dispose = dispose && implementation is global::System.IDisposable;");
+ writer.WriteLine("}");
+ writer.WriteLine();
+
+ writer.WriteLine("public void Dispose() {");
+ writer.WriteLine(" if (dispose) ((global::System.IDisposable)implementation).Dispose();");
+ writer.WriteLine("}");
+ writer.WriteLine();
+
+ writer.WriteLine(
+ "public pb::IMessageLite CallMethod(string methodName, pb::CodedInputStream input, pb::ExtensionRegistry registry) {{",
+ Descriptor.Name);
+ writer.Indent();
+ writer.WriteLine("switch(methodName) {");
+ writer.Indent();
+
+ foreach (MethodDescriptor method in Descriptor.Methods)
+ {
+ writer.WriteLine(
+ "case \"{0}\": return implementation.CallMethod(methodName, {1}.ParseFrom(input, registry), {2}.CreateBuilder());",
+ method.Name, GetClassName(method.InputType), GetClassName(method.OutputType));
+ }
+ writer.WriteLine(
+ "default: throw new global::System.MissingMethodException(typeof(ISearchService).FullName, methodName);");
+ writer.Outdent();
+ writer.WriteLine("}"); //end switch
+ writer.Outdent();
+ writer.WriteLine("}"); //end invoke
+ writer.Outdent();
+ writer.WriteLine("}"); //end server
+ }
+
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+ }
}
- }
-}
+} \ No newline at end of file
diff --git a/src/ProtoGen/SourceGeneratorBase.cs b/src/ProtoGen/SourceGeneratorBase.cs
index a7dc2f93..4b9d6ec3 100644
--- a/src/ProtoGen/SourceGeneratorBase.cs
+++ b/src/ProtoGen/SourceGeneratorBase.cs
@@ -1,131 +1,156 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System.Collections.Generic;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- internal abstract class SourceGeneratorBase<T> where T : IDescriptor {
-
- private readonly T descriptor;
-
- protected readonly bool OptimizeSpeed;
- protected readonly bool OptimizeSize;
- protected readonly bool UseLiteRuntime;
- protected readonly string RuntimeSuffix;
-
- protected SourceGeneratorBase(T descriptor) {
- this.descriptor = descriptor;
-
- OptimizeSize = descriptor.File.Options.OptimizeFor == Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode.CODE_SIZE;
- OptimizeSpeed = descriptor.File.Options.OptimizeFor == Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode.SPEED;
- UseLiteRuntime = descriptor.File.Options.OptimizeFor == Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode.LITE_RUNTIME;
- //Lite runtime uses OptimizeSpeed code branches
- OptimizeSpeed |= UseLiteRuntime;
- RuntimeSuffix = UseLiteRuntime ? "Lite" : "";
- }
-
- protected T Descriptor {
- get { return descriptor; }
- }
-
- internal static string GetClassName(IDescriptor descriptor) {
- return ToCSharpName(descriptor.FullName, descriptor.File);
- }
-
- // Groups are hacky: The name of the field is just the lower-cased name
- // of the group type. In C#, though, we would like to retain the original
- // capitalization of the type name.
- internal static string GetFieldName(FieldDescriptor descriptor) {
- if (descriptor.FieldType == FieldType.Group) {
- return descriptor.MessageType.Name;
- } else {
- return descriptor.Name;
- }
- }
-
- internal static string GetFieldConstantName(FieldDescriptor field) {
- return field.CSharpOptions.PropertyName + "FieldNumber";
- }
-
- private static string ToCSharpName(string name, FileDescriptor file) {
- string result = file.CSharpOptions.Namespace;
- if (file.CSharpOptions.NestClasses) {
- if (result != "") {
- result += ".";
- }
- result += file.CSharpOptions.UmbrellaClassname;
- }
- if (result != "") {
- result += '.';
- }
- string classname;
- if (file.Package == "") {
- classname = name;
- } else {
- // Strip the proto package from full_name since we've replaced it with
- // the C# namespace.
- classname = name.Substring(file.Package.Length + 1);
- }
- result += classname.Replace(".", ".Types.");
- return "global::" + result;
- }
-
- protected string ClassAccessLevel {
- get {
- return descriptor.File.CSharpOptions.PublicClasses ? "public" : "internal";
- }
- }
-
- protected void WriteChildren<TChild>(TextGenerator writer, string region, IEnumerable<TChild> children)
- where TChild : IDescriptor {
- // Copy the set of children; makes access easier
- List<TChild> copy = new List<TChild>(children);
- if (copy.Count == 0) {
- return;
- }
-
- if (region != null) {
- writer.WriteLine("#region {0}", region);
- }
- foreach (TChild child in children) {
- SourceGenerators.CreateGenerator(child).Generate(writer);
- }
- if (region != null) {
- writer.WriteLine("#endregion");
- writer.WriteLine();
- }
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ internal abstract class SourceGeneratorBase<T> where T : IDescriptor
+ {
+ private readonly T descriptor;
+
+ protected readonly bool OptimizeSpeed;
+ protected readonly bool OptimizeSize;
+ protected readonly bool UseLiteRuntime;
+ protected readonly string RuntimeSuffix;
+
+ protected SourceGeneratorBase(T descriptor)
+ {
+ this.descriptor = descriptor;
+
+ OptimizeSize = descriptor.File.Options.OptimizeFor ==
+ Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode.CODE_SIZE;
+ OptimizeSpeed = descriptor.File.Options.OptimizeFor ==
+ Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode.SPEED;
+ UseLiteRuntime = descriptor.File.Options.OptimizeFor ==
+ Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode.LITE_RUNTIME;
+ //Lite runtime uses OptimizeSpeed code branches
+ OptimizeSpeed |= UseLiteRuntime;
+ RuntimeSuffix = UseLiteRuntime ? "Lite" : "";
+ }
+
+ protected T Descriptor
+ {
+ get { return descriptor; }
+ }
+
+ internal static string GetClassName(IDescriptor descriptor)
+ {
+ return ToCSharpName(descriptor.FullName, descriptor.File);
+ }
+
+ // Groups are hacky: The name of the field is just the lower-cased name
+ // of the group type. In C#, though, we would like to retain the original
+ // capitalization of the type name.
+ internal static string GetFieldName(FieldDescriptor descriptor)
+ {
+ if (descriptor.FieldType == FieldType.Group)
+ {
+ return descriptor.MessageType.Name;
+ }
+ else
+ {
+ return descriptor.Name;
+ }
+ }
+
+ internal static string GetFieldConstantName(FieldDescriptor field)
+ {
+ return field.CSharpOptions.PropertyName + "FieldNumber";
+ }
+
+ private static string ToCSharpName(string name, FileDescriptor file)
+ {
+ string result = file.CSharpOptions.Namespace;
+ if (file.CSharpOptions.NestClasses)
+ {
+ if (result != "")
+ {
+ result += ".";
+ }
+ result += file.CSharpOptions.UmbrellaClassname;
+ }
+ if (result != "")
+ {
+ result += '.';
+ }
+ string classname;
+ if (file.Package == "")
+ {
+ classname = name;
+ }
+ else
+ {
+ // Strip the proto package from full_name since we've replaced it with
+ // the C# namespace.
+ classname = name.Substring(file.Package.Length + 1);
+ }
+ result += classname.Replace(".", ".Types.");
+ return "global::" + result;
+ }
+
+ protected string ClassAccessLevel
+ {
+ get { return descriptor.File.CSharpOptions.PublicClasses ? "public" : "internal"; }
+ }
+
+ protected void WriteChildren<TChild>(TextGenerator writer, string region, IEnumerable<TChild> children)
+ where TChild : IDescriptor
+ {
+ // Copy the set of children; makes access easier
+ List<TChild> copy = new List<TChild>(children);
+ if (copy.Count == 0)
+ {
+ return;
+ }
+
+ if (region != null)
+ {
+ writer.WriteLine("#region {0}", region);
+ }
+ foreach (TChild child in children)
+ {
+ SourceGenerators.CreateGenerator(child).Generate(writer);
+ }
+ if (region != null)
+ {
+ writer.WriteLine("#endregion");
+ writer.WriteLine();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/SourceGenerators.cs b/src/ProtoGen/SourceGenerators.cs
index 33f5573e..398868cb 100644
--- a/src/ProtoGen/SourceGenerators.cs
+++ b/src/ProtoGen/SourceGenerators.cs
@@ -1,79 +1,152 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System;
-using System.Collections.Generic;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
-
- public delegate TResult Func<T, TResult>(T arg);
-
- internal static class SourceGenerators {
-
- private static readonly Dictionary<Type, Func<IDescriptor, ISourceGenerator>> GeneratorFactories = new Dictionary<Type, Func<IDescriptor, ISourceGenerator>> {
- { typeof(FileDescriptor), descriptor => new UmbrellaClassGenerator((FileDescriptor) descriptor) },
- { typeof(EnumDescriptor), descriptor => new EnumGenerator((EnumDescriptor) descriptor) },
- { typeof(ServiceDescriptor), descriptor => new ServiceGenerator((ServiceDescriptor) descriptor) },
- { typeof(MessageDescriptor), descriptor => new MessageGenerator((MessageDescriptor) descriptor) },
- // For other fields, we have IFieldSourceGenerators.
- { typeof(FieldDescriptor), descriptor => new ExtensionGenerator((FieldDescriptor) descriptor) }
- };
-
- public static IFieldSourceGenerator CreateFieldGenerator(FieldDescriptor field) {
- switch (field.MappedType) {
- case MappedType.Message :
- return field.IsRepeated
- ? (IFieldSourceGenerator) new RepeatedMessageFieldGenerator(field)
- : new MessageFieldGenerator(field);
- case MappedType.Enum:
- return field.IsRepeated
- ? (IFieldSourceGenerator)new RepeatedEnumFieldGenerator(field)
- : new EnumFieldGenerator(field);
- default:
- return field.IsRepeated
- ? (IFieldSourceGenerator)new RepeatedPrimitiveFieldGenerator(field)
- : new PrimitiveFieldGenerator(field);
- }
- }
-
- public static ISourceGenerator CreateGenerator<T>(T descriptor) where T : IDescriptor {
- Func<IDescriptor, ISourceGenerator> factory;
- if (!GeneratorFactories.TryGetValue(typeof(T), out factory)) {
- throw new ArgumentException("No generator registered for " + typeof(T).Name);
- }
- return factory(descriptor);
- }
- }
-}
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ public delegate TResult Func<T, TResult>(T arg);
+
+ internal static class SourceGenerators
+ {
+ private static readonly Dictionary<Type, Func<IDescriptor, ISourceGenerator>> GeneratorFactories = new Dictionary
+ <Type, Func<IDescriptor, ISourceGenerator>>
+ {
+ {
+ typeof
+ (
+ FileDescriptor
+ )
+ ,
+ descriptor
+ =>
+ new UmbrellaClassGenerator
+ ((
+ FileDescriptor
+ )
+ descriptor)
+ },
+ {
+ typeof
+ (
+ EnumDescriptor
+ )
+ ,
+ descriptor
+ =>
+ new EnumGenerator
+ ((
+ EnumDescriptor
+ )
+ descriptor)
+ },
+ {
+ typeof
+ (
+ ServiceDescriptor
+ )
+ ,
+ descriptor
+ =>
+ new ServiceGenerator
+ ((
+ ServiceDescriptor
+ )
+ descriptor)
+ },
+ {
+ typeof
+ (
+ MessageDescriptor
+ )
+ ,
+ descriptor
+ =>
+ new MessageGenerator
+ ((
+ MessageDescriptor
+ )
+ descriptor)
+ },
+ // For other fields, we have IFieldSourceGenerators.
+ {
+ typeof
+ (
+ FieldDescriptor
+ )
+ ,
+ descriptor
+ =>
+ new ExtensionGenerator
+ ((
+ FieldDescriptor
+ )
+ descriptor)
+ }
+ };
+
+ public static IFieldSourceGenerator CreateFieldGenerator(FieldDescriptor field)
+ {
+ switch (field.MappedType)
+ {
+ case MappedType.Message:
+ return field.IsRepeated
+ ? (IFieldSourceGenerator) new RepeatedMessageFieldGenerator(field)
+ : new MessageFieldGenerator(field);
+ case MappedType.Enum:
+ return field.IsRepeated
+ ? (IFieldSourceGenerator) new RepeatedEnumFieldGenerator(field)
+ : new EnumFieldGenerator(field);
+ default:
+ return field.IsRepeated
+ ? (IFieldSourceGenerator) new RepeatedPrimitiveFieldGenerator(field)
+ : new PrimitiveFieldGenerator(field);
+ }
+ }
+
+ public static ISourceGenerator CreateGenerator<T>(T descriptor) where T : IDescriptor
+ {
+ Func<IDescriptor, ISourceGenerator> factory;
+ if (!GeneratorFactories.TryGetValue(typeof (T), out factory))
+ {
+ throw new ArgumentException("No generator registered for " + typeof (T).Name);
+ }
+ return factory(descriptor);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/UmbrellaClassGenerator.cs b/src/ProtoGen/UmbrellaClassGenerator.cs
index e1bbee5d..4e5f8ae4 100644
--- a/src/ProtoGen/UmbrellaClassGenerator.cs
+++ b/src/ProtoGen/UmbrellaClassGenerator.cs
@@ -1,241 +1,285 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// http://github.com/jskeet/dotnet-protobufs/
-// Original C++/Java/Python code:
-// http://code.google.com/p/protobuf/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using Google.ProtocolBuffers.Descriptors;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- /// <summary>
- /// Generator for the class describing the .proto file in general,
- /// containing things like the message descriptor.
- /// </summary>
- internal sealed class UmbrellaClassGenerator : SourceGeneratorBase<FileDescriptor>, ISourceGenerator {
-
- internal UmbrellaClassGenerator(FileDescriptor descriptor)
- : base(descriptor) {
- }
-
- // Recursively searches the given message to see if it contains any extensions.
- private static bool UsesExtensions(IMessage message) {
- // We conservatively assume that unknown fields are extensions.
- if (message.UnknownFields.FieldDictionary.Count > 0) {
- return true;
- }
-
- foreach (KeyValuePair<FieldDescriptor, object> keyValue in message.AllFields) {
- FieldDescriptor field = keyValue.Key;
- if (field.IsExtension) {
- return true;
- }
- if (field.MappedType == MappedType.Message) {
- if (field.IsRepeated) {
- foreach (IMessage subMessage in (IEnumerable)keyValue.Value) {
- if (UsesExtensions(subMessage)) {
- return true;
- }
- }
- } else {
- if (UsesExtensions((IMessage)keyValue.Value)) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
- public void Generate(TextGenerator writer) {
- WriteIntroduction(writer);
- WriteExtensionRegistration(writer);
- WriteChildren(writer, "Extensions", Descriptor.Extensions);
- writer.WriteLine("#region Static variables");
- foreach (MessageDescriptor message in Descriptor.MessageTypes) {
- new MessageGenerator(message).GenerateStaticVariables(writer);
- }
- writer.WriteLine("#endregion");
- if (!UseLiteRuntime) {
- WriteDescriptor(writer);
- } else {
- WriteLiteExtensions(writer);
- }
- // The class declaration either gets closed before or after the children are written.
- if (!Descriptor.CSharpOptions.NestClasses) {
- writer.Outdent();
- writer.WriteLine("}");
-
- // Close the namespace around the umbrella class if defined
- if (!Descriptor.CSharpOptions.NestClasses && Descriptor.CSharpOptions.UmbrellaNamespace != "") {
- writer.Outdent();
- writer.WriteLine("}");
- }
- }
- WriteChildren(writer, "Enums", Descriptor.EnumTypes);
- WriteChildren(writer, "Messages", Descriptor.MessageTypes);
- WriteChildren(writer, "Services", Descriptor.Services);
- if (Descriptor.CSharpOptions.NestClasses) {
- writer.Outdent();
- writer.WriteLine("}");
- }
- if (Descriptor.CSharpOptions.Namespace != "") {
- writer.Outdent();
- writer.WriteLine("}");
- }
- }
-
- private void WriteIntroduction(TextGenerator writer) {
- writer.WriteLine("// Generated by {0}. DO NOT EDIT!", this.GetType().Assembly.FullName);
- writer.WriteLine();
- writer.WriteLine("using pb = global::Google.ProtocolBuffers;");
- writer.WriteLine("using pbc = global::Google.ProtocolBuffers.Collections;");
- writer.WriteLine("using pbd = global::Google.ProtocolBuffers.Descriptors;");
- writer.WriteLine("using scg = global::System.Collections.Generic;");
-
- if (Descriptor.CSharpOptions.Namespace != "") {
- writer.WriteLine("namespace {0} {{", Descriptor.CSharpOptions.Namespace);
- writer.Indent();
- writer.WriteLine();
- }
- // Add the namespace around the umbrella class if defined
- if(!Descriptor.CSharpOptions.NestClasses && Descriptor.CSharpOptions.UmbrellaNamespace != "") {
- writer.WriteLine("namespace {0} {{", Descriptor.CSharpOptions.UmbrellaNamespace);
- writer.Indent();
- writer.WriteLine();
- }
-
- if (Descriptor.CSharpOptions.CodeContracts) {
- writer.WriteLine("[global::System.Diagnostics.Contracts.ContractVerificationAttribute(false)]");
- }
- writer.WriteLine("{0} static partial class {1} {{", ClassAccessLevel, Descriptor.CSharpOptions.UmbrellaClassname);
- writer.WriteLine();
- writer.Indent();
- }
-
- private void WriteExtensionRegistration(TextGenerator writer) {
- writer.WriteLine("#region Extension registration");
- writer.WriteLine("public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {");
- writer.Indent();
- foreach (FieldDescriptor extension in Descriptor.Extensions) {
- new ExtensionGenerator(extension).GenerateExtensionRegistrationCode(writer);
- }
- foreach (MessageDescriptor message in Descriptor.MessageTypes) {
- new MessageGenerator(message).GenerateExtensionRegistrationCode(writer);
- }
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine("#endregion");
- }
-
- private void WriteDescriptor(TextGenerator writer) {
- writer.WriteLine("#region Descriptor");
-
- writer.WriteLine("public static pbd::FileDescriptor Descriptor {");
- writer.WriteLine(" get { return descriptor; }");
- writer.WriteLine("}");
- writer.WriteLine("private static pbd::FileDescriptor descriptor;");
- writer.WriteLine();
- writer.WriteLine("static {0}() {{", Descriptor.CSharpOptions.UmbrellaClassname);
- writer.Indent();
- writer.WriteLine("byte[] descriptorData = global::System.Convert.FromBase64String(");
- writer.Indent();
- writer.Indent();
-
- // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
- byte[] bytes = Descriptor.Proto.ToByteArray();
- string base64 = Convert.ToBase64String(bytes);
-
- while (base64.Length > 60) {
- writer.WriteLine("\"{0}\" + ", base64.Substring(0, 60));
- base64 = base64.Substring(60);
- }
- writer.WriteLine("\"{0}\");", base64);
- writer.Outdent();
- writer.Outdent();
- writer.WriteLine("pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {");
- writer.Indent();
- writer.WriteLine("descriptor = root;");
- foreach (MessageDescriptor message in Descriptor.MessageTypes) {
- new MessageGenerator(message).GenerateStaticVariableInitializers(writer);
- }
- foreach (FieldDescriptor extension in Descriptor.Extensions) {
- new ExtensionGenerator(extension).GenerateStaticVariableInitializers(writer);
- }
-
- if (UsesExtensions(Descriptor.Proto)) {
- // Must construct an ExtensionRegistry containing all possible extensions
- // and return it.
- writer.WriteLine("pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();");
- writer.WriteLine("RegisterAllExtensions(registry);");
- foreach (FileDescriptor dependency in Descriptor.Dependencies) {
- writer.WriteLine("{0}.RegisterAllExtensions(registry);", DescriptorUtil.GetFullUmbrellaClassName(dependency));
- }
- writer.WriteLine("return registry;");
- } else {
- writer.WriteLine("return null;");
- }
- writer.Outdent();
- writer.WriteLine("};");
-
- // -----------------------------------------------------------------
- // Invoke internalBuildGeneratedFileFrom() to build the file.
- writer.WriteLine("pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,");
- writer.WriteLine(" new pbd::FileDescriptor[] {");
- foreach (FileDescriptor dependency in Descriptor.Dependencies) {
- writer.WriteLine(" {0}.Descriptor, ", DescriptorUtil.GetFullUmbrellaClassName(dependency));
- }
- writer.WriteLine(" }, assigner);");
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine("#endregion");
- writer.WriteLine();
- }
-
- private void WriteLiteExtensions(TextGenerator writer) {
- writer.WriteLine("#region Extensions");
- writer.WriteLine("internal static readonly object Descriptor;");
- writer.WriteLine("static {0}() {{", Descriptor.CSharpOptions.UmbrellaClassname);
- writer.Indent();
- writer.WriteLine("Descriptor = null;");
-
- foreach (MessageDescriptor message in Descriptor.MessageTypes) {
- new MessageGenerator(message).GenerateStaticVariableInitializers(writer);
- }
- foreach (FieldDescriptor extension in Descriptor.Extensions) {
- new ExtensionGenerator(extension).GenerateStaticVariableInitializers(writer);
- }
- writer.Outdent();
- writer.WriteLine("}");
- writer.WriteLine("#endregion");
- writer.WriteLine();
- }
- }
-}
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers.ProtoGen
+{
+ /// <summary>
+ /// Generator for the class describing the .proto file in general,
+ /// containing things like the message descriptor.
+ /// </summary>
+ internal sealed class UmbrellaClassGenerator : SourceGeneratorBase<FileDescriptor>, ISourceGenerator
+ {
+ internal UmbrellaClassGenerator(FileDescriptor descriptor)
+ : base(descriptor)
+ {
+ }
+
+ // Recursively searches the given message to see if it contains any extensions.
+ private static bool UsesExtensions(IMessage message)
+ {
+ // We conservatively assume that unknown fields are extensions.
+ if (message.UnknownFields.FieldDictionary.Count > 0)
+ {
+ return true;
+ }
+
+ foreach (KeyValuePair<FieldDescriptor, object> keyValue in message.AllFields)
+ {
+ FieldDescriptor field = keyValue.Key;
+ if (field.IsExtension)
+ {
+ return true;
+ }
+ if (field.MappedType == MappedType.Message)
+ {
+ if (field.IsRepeated)
+ {
+ foreach (IMessage subMessage in (IEnumerable) keyValue.Value)
+ {
+ if (UsesExtensions(subMessage))
+ {
+ return true;
+ }
+ }
+ }
+ else
+ {
+ if (UsesExtensions((IMessage) keyValue.Value))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public void Generate(TextGenerator writer)
+ {
+ WriteIntroduction(writer);
+ WriteExtensionRegistration(writer);
+ WriteChildren(writer, "Extensions", Descriptor.Extensions);
+ writer.WriteLine("#region Static variables");
+ foreach (MessageDescriptor message in Descriptor.MessageTypes)
+ {
+ new MessageGenerator(message).GenerateStaticVariables(writer);
+ }
+ writer.WriteLine("#endregion");
+ if (!UseLiteRuntime)
+ {
+ WriteDescriptor(writer);
+ }
+ else
+ {
+ WriteLiteExtensions(writer);
+ }
+ // The class declaration either gets closed before or after the children are written.
+ if (!Descriptor.CSharpOptions.NestClasses)
+ {
+ writer.Outdent();
+ writer.WriteLine("}");
+
+ // Close the namespace around the umbrella class if defined
+ if (!Descriptor.CSharpOptions.NestClasses && Descriptor.CSharpOptions.UmbrellaNamespace != "")
+ {
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+ }
+ WriteChildren(writer, "Enums", Descriptor.EnumTypes);
+ WriteChildren(writer, "Messages", Descriptor.MessageTypes);
+ WriteChildren(writer, "Services", Descriptor.Services);
+ if (Descriptor.CSharpOptions.NestClasses)
+ {
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+ if (Descriptor.CSharpOptions.Namespace != "")
+ {
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+ }
+
+ private void WriteIntroduction(TextGenerator writer)
+ {
+ writer.WriteLine("// Generated by {0}. DO NOT EDIT!", this.GetType().Assembly.FullName);
+ writer.WriteLine();
+ writer.WriteLine("using pb = global::Google.ProtocolBuffers;");
+ writer.WriteLine("using pbc = global::Google.ProtocolBuffers.Collections;");
+ writer.WriteLine("using pbd = global::Google.ProtocolBuffers.Descriptors;");
+ writer.WriteLine("using scg = global::System.Collections.Generic;");
+
+ if (Descriptor.CSharpOptions.Namespace != "")
+ {
+ writer.WriteLine("namespace {0} {{", Descriptor.CSharpOptions.Namespace);
+ writer.Indent();
+ writer.WriteLine();
+ }
+ // Add the namespace around the umbrella class if defined
+ if (!Descriptor.CSharpOptions.NestClasses && Descriptor.CSharpOptions.UmbrellaNamespace != "")
+ {
+ writer.WriteLine("namespace {0} {{", Descriptor.CSharpOptions.UmbrellaNamespace);
+ writer.Indent();
+ writer.WriteLine();
+ }
+
+ if (Descriptor.CSharpOptions.CodeContracts)
+ {
+ writer.WriteLine("[global::System.Diagnostics.Contracts.ContractVerificationAttribute(false)]");
+ }
+ writer.WriteLine("{0} static partial class {1} {{", ClassAccessLevel,
+ Descriptor.CSharpOptions.UmbrellaClassname);
+ writer.WriteLine();
+ writer.Indent();
+ }
+
+ private void WriteExtensionRegistration(TextGenerator writer)
+ {
+ writer.WriteLine("#region Extension registration");
+ writer.WriteLine("public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {");
+ writer.Indent();
+ foreach (FieldDescriptor extension in Descriptor.Extensions)
+ {
+ new ExtensionGenerator(extension).GenerateExtensionRegistrationCode(writer);
+ }
+ foreach (MessageDescriptor message in Descriptor.MessageTypes)
+ {
+ new MessageGenerator(message).GenerateExtensionRegistrationCode(writer);
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine("#endregion");
+ }
+
+ private void WriteDescriptor(TextGenerator writer)
+ {
+ writer.WriteLine("#region Descriptor");
+
+ writer.WriteLine("public static pbd::FileDescriptor Descriptor {");
+ writer.WriteLine(" get { return descriptor; }");
+ writer.WriteLine("}");
+ writer.WriteLine("private static pbd::FileDescriptor descriptor;");
+ writer.WriteLine();
+ writer.WriteLine("static {0}() {{", Descriptor.CSharpOptions.UmbrellaClassname);
+ writer.Indent();
+ writer.WriteLine("byte[] descriptorData = global::System.Convert.FromBase64String(");
+ writer.Indent();
+ writer.Indent();
+
+ // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
+ byte[] bytes = Descriptor.Proto.ToByteArray();
+ string base64 = Convert.ToBase64String(bytes);
+
+ while (base64.Length > 60)
+ {
+ writer.WriteLine("\"{0}\" + ", base64.Substring(0, 60));
+ base64 = base64.Substring(60);
+ }
+ writer.WriteLine("\"{0}\");", base64);
+ writer.Outdent();
+ writer.Outdent();
+ writer.WriteLine(
+ "pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {");
+ writer.Indent();
+ writer.WriteLine("descriptor = root;");
+ foreach (MessageDescriptor message in Descriptor.MessageTypes)
+ {
+ new MessageGenerator(message).GenerateStaticVariableInitializers(writer);
+ }
+ foreach (FieldDescriptor extension in Descriptor.Extensions)
+ {
+ new ExtensionGenerator(extension).GenerateStaticVariableInitializers(writer);
+ }
+
+ if (UsesExtensions(Descriptor.Proto))
+ {
+ // Must construct an ExtensionRegistry containing all possible extensions
+ // and return it.
+ writer.WriteLine("pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();");
+ writer.WriteLine("RegisterAllExtensions(registry);");
+ foreach (FileDescriptor dependency in Descriptor.Dependencies)
+ {
+ writer.WriteLine("{0}.RegisterAllExtensions(registry);",
+ DescriptorUtil.GetFullUmbrellaClassName(dependency));
+ }
+ writer.WriteLine("return registry;");
+ }
+ else
+ {
+ writer.WriteLine("return null;");
+ }
+ writer.Outdent();
+ writer.WriteLine("};");
+
+ // -----------------------------------------------------------------
+ // Invoke internalBuildGeneratedFileFrom() to build the file.
+ writer.WriteLine("pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,");
+ writer.WriteLine(" new pbd::FileDescriptor[] {");
+ foreach (FileDescriptor dependency in Descriptor.Dependencies)
+ {
+ writer.WriteLine(" {0}.Descriptor, ", DescriptorUtil.GetFullUmbrellaClassName(dependency));
+ }
+ writer.WriteLine(" }, assigner);");
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine("#endregion");
+ writer.WriteLine();
+ }
+
+ private void WriteLiteExtensions(TextGenerator writer)
+ {
+ writer.WriteLine("#region Extensions");
+ writer.WriteLine("internal static readonly object Descriptor;");
+ writer.WriteLine("static {0}() {{", Descriptor.CSharpOptions.UmbrellaClassname);
+ writer.Indent();
+ writer.WriteLine("Descriptor = null;");
+
+ foreach (MessageDescriptor message in Descriptor.MessageTypes)
+ {
+ new MessageGenerator(message).GenerateStaticVariableInitializers(writer);
+ }
+ foreach (FieldDescriptor extension in Descriptor.Extensions)
+ {
+ new ExtensionGenerator(extension).GenerateStaticVariableInitializers(writer);
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine("#endregion");
+ writer.WriteLine();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtoGen/app.config b/src/ProtoGen/app.config
index 0df7832f..285f9f93 100644
--- a/src/ProtoGen/app.config
+++ b/src/ProtoGen/app.config
@@ -1,3 +1,5 @@
-<?xml version="1.0"?>
-<configuration>
- <startup/></configuration>
+<?xml version="1.0"?>
+
+<configuration>
+ <startup />
+</configuration> \ No newline at end of file