Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2901_StaticSelectionMethods/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/2.4.1/ProtobufCS/src/ProtoGen/UmbrellaClassGenerator.cs

Last change on this file was 8295, checked in by abeham, 12 years ago

#1897:

  • Removed protocol buffers 0.9.1
  • Added protocol buffers 2.4.1
  • Updated proto processing command
File size: 12.5 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{
39    /// <summary>
40    /// Generator for the class describing the .proto file in general,
41    /// containing things like the message descriptor.
42    /// </summary>
43    internal sealed class UmbrellaClassGenerator : SourceGeneratorBase<FileDescriptor>, ISourceGenerator
44    {
45        internal UmbrellaClassGenerator(FileDescriptor descriptor)
46            : base(descriptor)
47        {
48        }
49
50        // Recursively searches the given message to see if it contains any extensions.
51        private static bool UsesExtensions(IMessage message)
52        {
53            // We conservatively assume that unknown fields are extensions.
54            if (message.UnknownFields.FieldDictionary.Count > 0)
55            {
56                return true;
57            }
58
59            foreach (KeyValuePair<FieldDescriptor, object> keyValue in message.AllFields)
60            {
61                FieldDescriptor field = keyValue.Key;
62                if (field.IsExtension)
63                {
64                    return true;
65                }
66                if (field.MappedType == MappedType.Message)
67                {
68                    if (field.IsRepeated)
69                    {
70                        foreach (IMessage subMessage in (IEnumerable) keyValue.Value)
71                        {
72                            if (UsesExtensions(subMessage))
73                            {
74                                return true;
75                            }
76                        }
77                    }
78                    else
79                    {
80                        if (UsesExtensions((IMessage) keyValue.Value))
81                        {
82                            return true;
83                        }
84                    }
85                }
86            }
87            return false;
88        }
89
90        public void Generate(TextGenerator writer)
91        {
92            WriteIntroduction(writer);
93            WriteExtensionRegistration(writer);
94            WriteChildren(writer, "Extensions", Descriptor.Extensions);
95            writer.WriteLine("#region Static variables");
96            foreach (MessageDescriptor message in Descriptor.MessageTypes)
97            {
98                new MessageGenerator(message).GenerateStaticVariables(writer);
99            }
100            writer.WriteLine("#endregion");
101            if (!UseLiteRuntime)
102            {
103                WriteDescriptor(writer);
104            }
105            else
106            {
107                WriteLiteExtensions(writer);
108            }
109            // The class declaration either gets closed before or after the children are written.
110            if (!Descriptor.CSharpOptions.NestClasses)
111            {
112                writer.Outdent();
113                writer.WriteLine("}");
114
115                // Close the namespace around the umbrella class if defined
116                if (!Descriptor.CSharpOptions.NestClasses && Descriptor.CSharpOptions.UmbrellaNamespace != "")
117                {
118                    writer.Outdent();
119                    writer.WriteLine("}");
120                }
121            }
122            WriteChildren(writer, "Enums", Descriptor.EnumTypes);
123            WriteChildren(writer, "Messages", Descriptor.MessageTypes);
124            WriteChildren(writer, "Services", Descriptor.Services);
125            if (Descriptor.CSharpOptions.NestClasses)
126            {
127                writer.Outdent();
128                writer.WriteLine("}");
129            }
130            if (Descriptor.CSharpOptions.Namespace != "")
131            {
132                writer.Outdent();
133                writer.WriteLine("}");
134            }
135            writer.WriteLine();
136            writer.WriteLine("#endregion Designer generated code");
137        }
138
139        private void WriteIntroduction(TextGenerator writer)
140        {
141            writer.WriteLine("// Generated by {0}.  DO NOT EDIT!", this.GetType().Assembly.FullName);
142            writer.WriteLine("#pragma warning disable 1591, 0612");
143            writer.WriteLine("#region Designer generated code");
144
145            writer.WriteLine();
146            writer.WriteLine("using pb = global::Google.ProtocolBuffers;");
147            writer.WriteLine("using pbc = global::Google.ProtocolBuffers.Collections;");
148            writer.WriteLine("using pbd = global::Google.ProtocolBuffers.Descriptors;");
149            writer.WriteLine("using scg = global::System.Collections.Generic;");
150
151            if (Descriptor.CSharpOptions.Namespace != "")
152            {
153                writer.WriteLine("namespace {0} {{", Descriptor.CSharpOptions.Namespace);
154                writer.Indent();
155                writer.WriteLine();
156            }
157            // Add the namespace around the umbrella class if defined
158            if (!Descriptor.CSharpOptions.NestClasses && Descriptor.CSharpOptions.UmbrellaNamespace != "")
159            {
160                writer.WriteLine("namespace {0} {{", Descriptor.CSharpOptions.UmbrellaNamespace);
161                writer.Indent();
162                writer.WriteLine();
163            }
164
165            if (Descriptor.CSharpOptions.CodeContracts)
166            {
167                writer.WriteLine("[global::System.Diagnostics.Contracts.ContractVerificationAttribute(false)]");
168            }
169            writer.WriteLine("[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]");
170            writer.WriteLine("[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]");
171            writer.WriteLine("[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"{0}\", \"{1}\")]",
172                             GetType().Assembly.GetName().Name, GetType().Assembly.GetName().Version);
173            writer.WriteLine("{0} static partial class {1} {{", ClassAccessLevel,
174                             Descriptor.CSharpOptions.UmbrellaClassname);
175            writer.WriteLine();
176            writer.Indent();
177        }
178
179        private void WriteExtensionRegistration(TextGenerator writer)
180        {
181            writer.WriteLine("#region Extension registration");
182            writer.WriteLine("public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {");
183            writer.Indent();
184            foreach (FieldDescriptor extension in Descriptor.Extensions)
185            {
186                new ExtensionGenerator(extension).GenerateExtensionRegistrationCode(writer);
187            }
188            foreach (MessageDescriptor message in Descriptor.MessageTypes)
189            {
190                new MessageGenerator(message).GenerateExtensionRegistrationCode(writer);
191            }
192            writer.Outdent();
193            writer.WriteLine("}");
194            writer.WriteLine("#endregion");
195        }
196
197        private void WriteDescriptor(TextGenerator writer)
198        {
199            writer.WriteLine("#region Descriptor");
200
201            writer.WriteLine("public static pbd::FileDescriptor Descriptor {");
202            writer.WriteLine("  get { return descriptor; }");
203            writer.WriteLine("}");
204            writer.WriteLine("private static pbd::FileDescriptor descriptor;");
205            writer.WriteLine();
206            writer.WriteLine("static {0}() {{", Descriptor.CSharpOptions.UmbrellaClassname);
207            writer.Indent();
208            writer.WriteLine("byte[] descriptorData = global::System.Convert.FromBase64String(");
209            writer.Indent();
210            writer.Indent();
211
212            // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64.
213            byte[] bytes = Descriptor.Proto.ToByteArray();
214            string base64 = Convert.ToBase64String(bytes);
215
216            while (base64.Length > 60)
217            {
218                writer.WriteLine("\"{0}\" + ", base64.Substring(0, 60));
219                base64 = base64.Substring(60);
220            }
221            writer.WriteLine("\"{0}\");", base64);
222            writer.Outdent();
223            writer.Outdent();
224            writer.WriteLine(
225                "pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {");
226            writer.Indent();
227            writer.WriteLine("descriptor = root;");
228            foreach (MessageDescriptor message in Descriptor.MessageTypes)
229            {
230                new MessageGenerator(message).GenerateStaticVariableInitializers(writer);
231            }
232            foreach (FieldDescriptor extension in Descriptor.Extensions)
233            {
234                new ExtensionGenerator(extension).GenerateStaticVariableInitializers(writer);
235            }
236
237            if (UsesExtensions(Descriptor.Proto))
238            {
239                // Must construct an ExtensionRegistry containing all possible extensions
240                // and return it.
241                writer.WriteLine("pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();");
242                writer.WriteLine("RegisterAllExtensions(registry);");
243                foreach (FileDescriptor dependency in Descriptor.Dependencies)
244                {
245                    writer.WriteLine("{0}.RegisterAllExtensions(registry);",
246                                     DescriptorUtil.GetFullUmbrellaClassName(dependency));
247                }
248                writer.WriteLine("return registry;");
249            }
250            else
251            {
252                writer.WriteLine("return null;");
253            }
254            writer.Outdent();
255            writer.WriteLine("};");
256
257            // -----------------------------------------------------------------
258            // Invoke internalBuildGeneratedFileFrom() to build the file.
259            writer.WriteLine("pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,");
260            writer.WriteLine("    new pbd::FileDescriptor[] {");
261            foreach (FileDescriptor dependency in Descriptor.Dependencies)
262            {
263                writer.WriteLine("    {0}.Descriptor, ", DescriptorUtil.GetFullUmbrellaClassName(dependency));
264            }
265            writer.WriteLine("    }, assigner);");
266            writer.Outdent();
267            writer.WriteLine("}");
268            writer.WriteLine("#endregion");
269            writer.WriteLine();
270        }
271
272        private void WriteLiteExtensions(TextGenerator writer)
273        {
274            writer.WriteLine("#region Extensions");
275            writer.WriteLine("internal static readonly object Descriptor;");
276            writer.WriteLine("static {0}() {{", Descriptor.CSharpOptions.UmbrellaClassname);
277            writer.Indent();
278            writer.WriteLine("Descriptor = null;");
279
280            foreach (MessageDescriptor message in Descriptor.MessageTypes)
281            {
282                new MessageGenerator(message).GenerateStaticVariableInitializers(writer);
283            }
284            foreach (FieldDescriptor extension in Descriptor.Extensions)
285            {
286                new ExtensionGenerator(extension).GenerateStaticVariableInitializers(writer);
287            }
288            writer.Outdent();
289            writer.WriteLine("}");
290            writer.WriteLine("#endregion");
291            writer.WriteLine();
292        }
293    }
294}
Note: See TracBrowser for help on using the repository browser.