Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2922-DataCompletenessChartPerf/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/2.4.1/ProtobufCS/src/ProtoGen/Generator.cs @ 16793

Last change on this file since 16793 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: 10.8 KB
Line 
1#region Copyright notice and license
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc.  All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13//     * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15//     * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19//     * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35#endregion
36
37using System.Collections.Generic;
38using System.IO;
39using System.Text;
40using Google.ProtocolBuffers.Collections;
41using Google.ProtocolBuffers.DescriptorProtos;
42using Google.ProtocolBuffers.Descriptors;
43
44namespace Google.ProtocolBuffers.ProtoGen
45{
46    /// <summary>
47    /// Code generator for protocol buffers. Only C# is supported at the moment.
48    /// </summary>
49    public sealed class Generator
50    {
51        private readonly GeneratorOptions options;
52
53        private Generator(GeneratorOptions options)
54        {
55            options.Validate();
56            this.options = options;
57        }
58
59        /// <summary>
60        /// Returns a generator configured with the specified options.
61        /// </summary>
62        public static Generator CreateGenerator(GeneratorOptions options)
63        {
64            return new Generator(options);
65        }
66
67        public void Generate()
68        {
69            List<FileDescriptorSet> descriptorProtos = new List<FileDescriptorSet>();
70            foreach (string inputFile in options.InputFiles)
71            {
72                ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance();
73                CSharpOptions.RegisterAllExtensions(extensionRegistry);
74                using (Stream inputStream = File.OpenRead(inputFile))
75                {
76                    descriptorProtos.Add(FileDescriptorSet.ParseFrom(inputStream, extensionRegistry));
77                }
78            }
79
80            IList<FileDescriptor> descriptors = ConvertDescriptors(options.FileOptions, descriptorProtos.ToArray());
81
82            // Combine with options from command line
83            foreach (FileDescriptor descriptor in descriptors)
84            {
85                descriptor.ConfigureWithDefaultOptions(options.FileOptions);
86            }
87
88            foreach (FileDescriptor descriptor in descriptors)
89            {
90                // Optionally exclude descriptors in google.protobuf
91                if (descriptor.CSharpOptions.IgnoreGoogleProtobuf && descriptor.Package == "google.protobuf")
92                {
93                    continue;
94                }
95                Generate(descriptor);
96            }
97        }
98
99        /// <summary>
100        /// Generates code for a particular file. All dependencies must
101        /// already have been resolved.
102        /// </summary>
103        private void Generate(FileDescriptor descriptor)
104        {
105            UmbrellaClassGenerator ucg = new UmbrellaClassGenerator(descriptor);
106            using (TextWriter textWriter = File.CreateText(GetOutputFile(descriptor)))
107            {
108                TextGenerator writer = new TextGenerator(textWriter, options.LineBreak);
109                ucg.Generate(writer);
110            }
111        }
112
113        private string GetOutputFile(FileDescriptor descriptor)
114        {
115            CSharpFileOptions fileOptions = descriptor.CSharpOptions;
116
117            string filename = descriptor.CSharpOptions.UmbrellaClassname + descriptor.CSharpOptions.FileExtension;
118
119            string outputDirectory = descriptor.CSharpOptions.OutputDirectory;
120            if (fileOptions.ExpandNamespaceDirectories)
121            {
122                string package = fileOptions.Namespace;
123                if (!string.IsNullOrEmpty(package))
124                {
125                    string[] bits = package.Split('.');
126                    foreach (string bit in bits)
127                    {
128                        outputDirectory = Path.Combine(outputDirectory, bit);
129                    }
130                }
131            }
132
133            // As the directory can be explicitly specified in options, we need to make sure it exists
134            Directory.CreateDirectory(outputDirectory);
135            return Path.Combine(outputDirectory, filename);
136        }
137
138        /// <summary>
139        /// Resolves any dependencies and converts FileDescriptorProtos into FileDescriptors.
140        /// The list returned is in the same order as the protos are listed in the descriptor set.
141        /// Note: this method is internal rather than private to allow testing.
142        /// </summary>
143        /// <exception cref="DependencyResolutionException">Not all dependencies could be resolved.</exception>
144        public static IList<FileDescriptor> ConvertDescriptors(CSharpFileOptions options,
145                                                               params FileDescriptorSet[] descriptorProtos)
146        {
147            // Simple strategy: Keep going through the list of protos to convert, only doing ones where
148            // we've already converted all the dependencies, until we get to a stalemate
149            List<FileDescriptorProto> fileList = new List<FileDescriptorProto>();
150            foreach (FileDescriptorSet set in descriptorProtos)
151            {
152                fileList.AddRange(set.FileList);
153            }
154
155            FileDescriptor[] converted = new FileDescriptor[fileList.Count];
156
157            Dictionary<string, FileDescriptor> convertedMap = new Dictionary<string, FileDescriptor>();
158
159            int totalConverted = 0;
160
161            bool madeProgress = true;
162            while (madeProgress && totalConverted < converted.Length)
163            {
164                madeProgress = false;
165                for (int i = 0; i < converted.Length; i++)
166                {
167                    if (converted[i] != null)
168                    {
169                        // Already done this one
170                        continue;
171                    }
172                    FileDescriptorProto candidate = fileList[i];
173                    FileDescriptor[] dependencies = new FileDescriptor[candidate.DependencyList.Count];
174
175
176                    CSharpFileOptions.Builder builder = options.ToBuilder();
177                    if (candidate.Options.HasExtension(CSharpOptions.CSharpFileOptions))
178                    {
179                        builder.MergeFrom(
180                            candidate.Options.GetExtension(CSharpOptions.CSharpFileOptions));
181                    }
182                    CSharpFileOptions localOptions = builder.Build();
183
184                    bool foundAllDependencies = true;
185                    for (int j = 0; j < dependencies.Length; j++)
186                    {
187                        if (!convertedMap.TryGetValue(candidate.DependencyList[j], out dependencies[j]))
188                        {
189                            // We can auto-magically resolve these since we already have their description
190                            // This way if the file is only referencing options it does not need to be built with the
191                            // --include_imports definition.
192                            if (localOptions.IgnoreGoogleProtobuf &&
193                                (candidate.DependencyList[j] == "google/protobuf/csharp_options.proto"))
194                            {
195                                dependencies[j] = CSharpOptions.Descriptor;
196                                continue;
197                            }
198                            if (localOptions.IgnoreGoogleProtobuf &&
199                                (candidate.DependencyList[j] == "google/protobuf/descriptor.proto"))
200                            {
201                                dependencies[j] = DescriptorProtoFile.Descriptor;
202                                continue;
203                            }
204                            foundAllDependencies = false;
205                            break;
206                        }
207                    }
208                    if (!foundAllDependencies)
209                    {
210                        continue;
211                    }
212                    madeProgress = true;
213                    totalConverted++;
214                    converted[i] = FileDescriptor.BuildFrom(candidate, dependencies);
215                    convertedMap[candidate.Name] = converted[i];
216                }
217            }
218            if (!madeProgress)
219            {
220                StringBuilder remaining = new StringBuilder();
221                for (int i = 0; i < converted.Length; i++)
222                {
223                    if (converted[i] == null)
224                    {
225                        if (remaining.Length != 0)
226                        {
227                            remaining.Append(", ");
228                        }
229                        FileDescriptorProto failure = fileList[i];
230                        remaining.Append(failure.Name);
231                        remaining.Append(":");
232                        foreach (string dependency in failure.DependencyList)
233                        {
234                            if (!convertedMap.ContainsKey(dependency))
235                            {
236                                remaining.Append(" ");
237                                remaining.Append(dependency);
238                            }
239                        }
240                        remaining.Append(";");
241                    }
242                }
243                throw new DependencyResolutionException("Unable to resolve all dependencies: " + remaining);
244            }
245            return Lists.AsReadOnly(converted);
246        }
247    }
248}
Note: See TracBrowser for help on using the repository browser.