diff options
Diffstat (limited to 'csharp/ProtoGen/Generator.cs')
-rw-r--r-- | csharp/ProtoGen/Generator.cs | 101 |
1 files changed, 96 insertions, 5 deletions
diff --git a/csharp/ProtoGen/Generator.cs b/csharp/ProtoGen/Generator.cs index d1ff76b2..f656386b 100644 --- a/csharp/ProtoGen/Generator.cs +++ b/csharp/ProtoGen/Generator.cs @@ -1,8 +1,10 @@ using System; 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> @@ -26,22 +28,111 @@ namespace Google.ProtocolBuffers.ProtoGen { public void Generate() { foreach (string inputFile in options.InputFiles) { - FileDescriptorSet descriptorProtos; + FileDescriptorSet descriptorProtos; + ExtensionRegistry extensionRegistry = ExtensionRegistry.CreateInstance(); + extensionRegistry.Add(CSharpOptions.CSharpUmbrellaClassname); + extensionRegistry.Add(CSharpOptions.CSharpMultipleFiles); + extensionRegistry.Add(CSharpOptions.CSharpNamespace); + extensionRegistry.Add(CSharpOptions.CSharpNestClasses); + extensionRegistry.Add(CSharpOptions.CSharpPublicClasses); using (Stream inputStream = File.OpenRead(inputFile)) { - descriptorProtos = FileDescriptorSet.ParseFrom(inputStream); + descriptorProtos = FileDescriptorSet.ParseFrom(inputStream, extensionRegistry); } - List<FileDescriptor> descriptors = ConvertDescriptors(descriptorProtos); + IList<FileDescriptor> descriptors = ConvertDescriptors(descriptorProtos); + + foreach (FileDescriptor descriptor in descriptors) { + Generate(descriptor); + } + } + } + + /// <summary> + /// Generates code for a particular file. All dependencies must + /// already have been resolved. + /// </summary> + private void Generate(FileDescriptor descriptor) { + string umbrellaClass = DescriptorUtil.GetUmbrellaClassName(descriptor); + string ns = DescriptorUtil.GetNamespace(descriptor); + using (TextWriter textWriter = File.CreateText(Path.Combine(options.OutputDirectory, umbrellaClass + ".cs"))) { + TextGenerator writer = new TextGenerator(textWriter); + + UmbrellaClassGenerator ucg = new UmbrellaClassGenerator(descriptor); + ucg.Generate(writer); + /* + GenerateSiblings(umbrellaSource, descriptor, descriptor.MessageTypes); + GenerateSiblings(umbrellaSource, descriptor, descriptor.EnumTypes); + GenerateSiblings(umbrellaSource, descriptor, descriptor.Services);*/ } } + private static void GenerateSiblings<T>(SourceFileGenerator parentSourceGenerator, FileDescriptor file, IEnumerable<T> siblings) + where T : IDescriptor { + } + /// <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> - internal static List<FileDescriptor> ConvertDescriptors(FileDescriptorSet descriptorProtos) { - return null; + internal static IList<FileDescriptor> ConvertDescriptors(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 + IList<FileDescriptorProto> fileList = descriptorProtos.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]; + bool foundAllDependencies = true; + for (int j = 0; j < dependencies.Length; j++) { + if (!convertedMap.TryGetValue(candidate.DependencyList[j], out dependencies[j])) { + 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); } } } |