aboutsummaryrefslogtreecommitdiff
path: root/csharp/ProtoGen/UmbrellaClassGenerator.cs
diff options
context:
space:
mode:
Diffstat (limited to 'csharp/ProtoGen/UmbrellaClassGenerator.cs')
-rw-r--r--csharp/ProtoGen/UmbrellaClassGenerator.cs96
1 files changed, 96 insertions, 0 deletions
diff --git a/csharp/ProtoGen/UmbrellaClassGenerator.cs b/csharp/ProtoGen/UmbrellaClassGenerator.cs
new file mode 100644
index 00000000..7db5c46c
--- /dev/null
+++ b/csharp/ProtoGen/UmbrellaClassGenerator.cs
@@ -0,0 +1,96 @@
+using System;
+using Google.ProtocolBuffers.DescriptorProtos;
+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) {
+ }
+
+ public void Generate(TextGenerator writer) {
+ WriteIntroduction(writer);
+ WriteDescriptor(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");
+ // The class declaration either gets closed before or after the children are written.
+ if (!DescriptorUtil.NestClasses(Descriptor)) {
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+ WriteChildren(writer, "Enums", Descriptor.EnumTypes);
+ WriteChildren(writer, "Messages", Descriptor.MessageTypes);
+ WriteChildren(writer, "Services", Descriptor.Services);
+ if (DescriptorUtil.NestClasses(Descriptor)) {
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+ if (DescriptorUtil.GetNamespace(Descriptor) != "") {
+ writer.Outdent();
+ writer.WriteLine("}");
+ }
+ }
+
+ private void WriteIntroduction(TextGenerator writer) {
+ writer.WriteLine("// Generated by the protocol buffer compiler. DO NOT EDIT!");
+ writer.WriteLine();
+ Helpers.WriteNamespaces(writer);
+
+ if (DescriptorUtil.GetNamespace(Descriptor) != "") {
+ writer.WriteLine("namespace {0} {{", DescriptorUtil.GetNamespace(Descriptor));
+ writer.Indent();
+ writer.WriteLine();
+ }
+
+ writer.WriteLine("{0} static partial class {1} {{", ClassAccessLevel, DescriptorUtil.GetUmbrellaClassName(Descriptor));
+ writer.WriteLine();
+ writer.Indent();
+ }
+
+ 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 readonly pbd::FileDescriptor descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(");
+ writer.WriteLine(" 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.WriteLine("new pbd::FileDescriptor[] {");
+ foreach (FileDescriptor dependency in Descriptor.Dependencies) {
+ // TODO(jonskeet): The normal code won't work for the bootstrapping descriptor, because we don't get unknown fields :(
+ if (dependency.Package == "google.protobuf" && dependency.Name.EndsWith("descriptor.proto")) {
+ writer.WriteLine(" global::" + typeof(DescriptorProtoFile).FullName + ".Descriptor, ");
+ continue;
+ }
+ writer.WriteLine(" {0}.Descriptor, ", DescriptorUtil.GetFullUmbrellaClassName(dependency));
+ }
+ writer.WriteLine("});");
+ writer.Outdent();
+ writer.Outdent();
+ writer.WriteLine("#endregion");
+ writer.WriteLine();
+ }
+ }
+}