Free cookie consent management tool by TermsFeed Policy Generator

source: tags/3.3.1/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/0.9.1/ProtobufCS/src/ProtoGen/UmbrellaClassGenerator.cs

Last change on this file was 3857, checked in by abeham, 14 years ago

#866

  • Added protobuf-csharp-port project source to ExtLibs
File size: 8.7 KB
Line 
1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// http://github.com/jskeet/dotnet-protobufs/
4// Original C++/Java/Python code:
5// http://code.google.com/p/protobuf/
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are
9// met:
10//
11//     * Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//     * Redistributions in binary form must reproduce the above
14// copyright notice, this list of conditions and the following disclaimer
15// in the documentation and/or other materials provided with the
16// distribution.
17//     * Neither the name of Google Inc. nor the names of its
18// contributors may be used to endorse or promote products derived from
19// this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32using System;
33using System.Collections;
34using System.Collections.Generic;
35using Google.ProtocolBuffers.Descriptors;
36
37namespace Google.ProtocolBuffers.ProtoGen {
38  /// <summary>
39  /// Generator for the class describing the .proto file in general,
40  /// containing things like the message descriptor.
41  /// </summary>
42  internal sealed class UmbrellaClassGenerator : SourceGeneratorBase<FileDescriptor>, ISourceGenerator {
43
44    internal UmbrellaClassGenerator(FileDescriptor descriptor)
45      : base(descriptor) {
46    }
47
48    // Recursively searches the given message to see if it contains any extensions.
49    private static bool UsesExtensions(IMessage message) {
50      // We conservatively assume that unknown fields are extensions.
51      if (message.UnknownFields.FieldDictionary.Count > 0) {
52        return true;
53      }
54
55      foreach (KeyValuePair<FieldDescriptor, object> keyValue in message.AllFields) {
56        FieldDescriptor field = keyValue.Key;
57        if (field.IsExtension) {
58          return true;
59        }
60        if (field.MappedType == MappedType.Message) {
61          if (field.IsRepeated) {
62            foreach (IMessage subMessage in (IEnumerable)keyValue.Value) {
63              if (UsesExtensions(subMessage)) {
64                return true;
65              }
66            }
67          } else {
68            if (UsesExtensions((IMessage)keyValue.Value)) {
69              return true;
70            }
71          }
72        }
73      }
74      return false;
75    }
76
77    public string UmbrellaClassName {
78      get { throw new NotImplementedException(); }
79    }
80
81    public void Generate(TextGenerator writer) {
82      WriteIntroduction(writer);
83      WriteExtensionRegistration(writer);
84      WriteChildren(writer, "Extensions", Descriptor.Extensions);
85      writer.WriteLine("#region Static variables");
86      foreach (MessageDescriptor message in Descriptor.MessageTypes) {
87        new MessageGenerator(message).GenerateStaticVariables(writer);
88      }
89      writer.WriteLine("#endregion");
90      WriteDescriptor(writer);
91      // The class declaration either gets closed before or after the children are written.
92      if (!Descriptor.CSharpOptions.NestClasses) {
93        writer.Outdent();
94        writer.WriteLine("}");
95      }
96      WriteChildren(writer, "Enums", Descriptor.EnumTypes);
97      WriteChildren(writer, "Messages", Descriptor.MessageTypes);
98      WriteChildren(writer, "Services", Descriptor.Services);
99      if (Descriptor.CSharpOptions.NestClasses) {
100        writer.Outdent();
101        writer.WriteLine("}");
102      }
103      if (Descriptor.CSharpOptions.Namespace != "") {
104        writer.Outdent();
105        writer.WriteLine("}");
106      }
107    }
108
109    private void WriteIntroduction(TextGenerator writer) {
110      writer.WriteLine("// Generated by the protocol buffer compiler.  DO NOT EDIT!");
111      writer.WriteLine();
112      Helpers.WriteNamespaces(writer);
113
114      if (Descriptor.CSharpOptions.Namespace != "") {
115        writer.WriteLine("namespace {0} {{", Descriptor.CSharpOptions.Namespace);
116        writer.Indent();
117        writer.WriteLine();
118      }   
119      if (Descriptor.CSharpOptions.CodeContracts) {
120          writer.WriteLine("[global::System.Diagnostics.Contracts.ContractVerificationAttribute(false)]");
121      }
122      writer.WriteLine("{0} static partial class {1} {{", ClassAccessLevel, Descriptor.CSharpOptions.UmbrellaClassname);
123      writer.WriteLine();
124      writer.Indent();
125    }
126
127    private void WriteExtensionRegistration(TextGenerator writer) {
128      writer.WriteLine("#region Extension registration");
129      writer.WriteLine("public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {");
130      writer.Indent();
131      foreach (FieldDescriptor extension in Descriptor.Extensions) {
132        new ExtensionGenerator(extension).GenerateExtensionRegistrationCode(writer);
133      }
134      foreach (MessageDescriptor message in Descriptor.MessageTypes) {
135        new MessageGenerator(message).GenerateExtensionRegistrationCode(writer);
136      }
137      writer.Outdent();
138      writer.WriteLine("}");
139      writer.WriteLine("#endregion");
140    }
141
142    private void WriteDescriptor(TextGenerator writer) {
143      writer.WriteLine("#region Descriptor");
144
145      writer.WriteLine("public static pbd::FileDescriptor Descriptor {");
146      writer.WriteLine("  get { return descriptor; }");
147      writer.WriteLine("}");
148      writer.WriteLine("private static pbd::FileDescriptor descriptor;");
149      writer.WriteLine();
150      writer.WriteLine("static {0}() {{", Descriptor.CSharpOptions.UmbrellaClassname);
151      writer.Indent();
152      writer.WriteLine("byte[] descriptorData = global::System.Convert.FromBase64String(");
153      writer.Indent();
154      writer.Indent();
155
156      // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
157      byte[] bytes = Descriptor.Proto.ToByteArray();
158      string base64 = Convert.ToBase64String(bytes);
159
160      while (base64.Length > 60) {
161        writer.WriteLine("\"{0}\" + ", base64.Substring(0, 60));
162        base64 = base64.Substring(60);
163      }
164      writer.WriteLine("\"{0}\");", base64);
165      writer.Outdent();
166      writer.Outdent();
167      writer.WriteLine("pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {");
168      writer.Indent();
169      writer.WriteLine("descriptor = root;");
170      foreach (MessageDescriptor message in Descriptor.MessageTypes) {
171        new MessageGenerator(message).GenerateStaticVariableInitializers(writer);
172      }
173      foreach (FieldDescriptor extension in Descriptor.Extensions) {
174        new ExtensionGenerator(extension).GenerateStaticVariableInitializers(writer);
175      }
176
177      if (UsesExtensions(Descriptor.Proto)) {
178        // Must construct an ExtensionRegistry containing all possible extensions
179        // and return it.
180        writer.WriteLine("pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();");
181        writer.WriteLine("RegisterAllExtensions(registry);");
182        foreach (FileDescriptor dependency in Descriptor.Dependencies) {
183          writer.WriteLine("{0}.RegisterAllExtensions(registry);", DescriptorUtil.GetFullUmbrellaClassName(dependency));
184        }
185        writer.WriteLine("return registry;");
186      } else {
187        writer.WriteLine("return null;");
188      }
189      writer.Outdent();
190      writer.WriteLine("};");
191
192      // -----------------------------------------------------------------
193      // Invoke internalBuildGeneratedFileFrom() to build the file.
194      writer.WriteLine("pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,");
195      writer.WriteLine("    new pbd::FileDescriptor[] {");
196      foreach (FileDescriptor dependency in Descriptor.Dependencies) {
197        writer.WriteLine("    {0}.Descriptor, ", DescriptorUtil.GetFullUmbrellaClassName(dependency));
198      }
199      writer.WriteLine("    }, assigner);");
200      writer.Outdent();
201      writer.WriteLine("}");
202      writer.WriteLine("#endregion");
203      writer.WriteLine();
204    }
205  }
206}
Note: See TracBrowser for help on using the repository browser.