aboutsummaryrefslogtreecommitdiff
path: root/src/ProtoGen/UmbrellaClassGenerator.cs
diff options
context:
space:
mode:
authorJon Skeet <skeet@pobox.com>2009-06-05 19:29:36 +0100
committerJon Skeet <skeet@pobox.com>2009-06-05 19:29:36 +0100
commitdf67f1482beab88844296a469aa135fbaebcec9d (patch)
tree86cc32075c445264bd28a582f1a873913664b968 /src/ProtoGen/UmbrellaClassGenerator.cs
parent6ef233d4ea9099188310e5278f76c01f931ac817 (diff)
downloadprotobuf-df67f1482beab88844296a469aa135fbaebcec9d.tar.gz
protobuf-df67f1482beab88844296a469aa135fbaebcec9d.tar.bz2
protobuf-df67f1482beab88844296a469aa135fbaebcec9d.zip
Fix custom options behaviour
Diffstat (limited to 'src/ProtoGen/UmbrellaClassGenerator.cs')
-rw-r--r--src/ProtoGen/UmbrellaClassGenerator.cs95
1 files changed, 87 insertions, 8 deletions
diff --git a/src/ProtoGen/UmbrellaClassGenerator.cs b/src/ProtoGen/UmbrellaClassGenerator.cs
index 938507b5..732b6f8d 100644
--- a/src/ProtoGen/UmbrellaClassGenerator.cs
+++ b/src/ProtoGen/UmbrellaClassGenerator.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections;
+using System.Collections.Generic;
using Google.ProtocolBuffers.DescriptorProtos;
using Google.ProtocolBuffers.Descriptors;
@@ -13,19 +15,49 @@ namespace Google.ProtocolBuffers.ProtoGen {
: base(descriptor) {
}
+ // Recursively searches the given message to see if it contains any extensions.
+ private static bool UsesExtensions(IMessage message) {
+ // We conservatively assume that unknown fields are extensions.
+ if (message.UnknownFields.FieldDictionary.Count > 0) {
+ return true;
+ }
+
+ foreach (KeyValuePair<FieldDescriptor, object> keyValue in message.AllFields) {
+ FieldDescriptor field = keyValue.Key;
+ if (field.IsExtension) {
+ return true;
+ }
+ if (field.MappedType == MappedType.Message) {
+ if (field.IsRepeated) {
+ foreach (IMessage subMessage in (IEnumerable)keyValue.Value) {
+ if (UsesExtensions(subMessage)) {
+ return true;
+ }
+ }
+ } else {
+ if (UsesExtensions((IMessage)keyValue.Value)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
public string UmbrellaClassName {
get { throw new NotImplementedException(); }
}
public void Generate(TextGenerator writer) {
WriteIntroduction(writer);
- WriteDescriptor(writer);
+ WriteExtensionRegistration(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");
+ WriteDescriptor(writer);
// The class declaration either gets closed before or after the children are written.
if (!Descriptor.CSharpOptions.NestClasses) {
writer.Outdent();
@@ -60,14 +92,32 @@ namespace Google.ProtocolBuffers.ProtoGen {
writer.Indent();
}
+ private void WriteExtensionRegistration(TextGenerator writer) {
+ writer.WriteLine("#region Extension registration");
+ writer.WriteLine("public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {");
+ writer.Indent();
+ foreach (FieldDescriptor extension in Descriptor.Extensions) {
+ new ExtensionGenerator(extension).GenerateExtensionRegistrationCode(writer);
+ }
+ foreach (MessageDescriptor message in Descriptor.MessageTypes) {
+ new MessageGenerator(message).GenerateExtensionRegistrationCode(writer);
+ }
+ writer.Outdent();
+ writer.WriteLine("}");
+ writer.WriteLine("#endregion");
+ }
+
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.WriteLine("private static pbd::FileDescriptor descriptor;");
+ writer.WriteLine();
+ writer.WriteLine("static {0}() {{", Descriptor.CSharpOptions.UmbrellaClassname);
+ writer.Indent();
+ writer.WriteLine("byte[] descriptorData = global::System.Convert.FromBase64String(");
writer.Indent();
writer.Indent();
@@ -79,15 +129,44 @@ namespace Google.ProtocolBuffers.ProtoGen {
writer.WriteLine("\"{0}\" + ", base64.Substring(0, 60));
base64 = base64.Substring(60);
}
- writer.WriteLine("\"{0}\"),", base64);
+ writer.WriteLine("\"{0}\");", base64);
+ writer.Outdent();
+ writer.Outdent();
+ writer.WriteLine("pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {");
+ writer.Indent();
+ writer.WriteLine("descriptor = root;");
+ foreach (MessageDescriptor message in Descriptor.MessageTypes) {
+ new MessageGenerator(message).GenerateStaticVariableInitializers(writer);
+ }
+ foreach (FieldDescriptor extension in Descriptor.Extensions) {
+ new ExtensionGenerator(extension).GenerateStaticVariableInitializers(writer);
+ }
- writer.WriteLine("new pbd::FileDescriptor[] {");
- foreach (FileDescriptor dependency in Descriptor.Dependencies) {
- writer.WriteLine(" {0}.Descriptor, ", DescriptorUtil.GetFullUmbrellaClassName(dependency));
+ if (UsesExtensions(Descriptor.Proto)) {
+ // Must construct an ExtensionRegistry containing all possible extensions
+ // and return it.
+ writer.WriteLine("pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();");
+ writer.WriteLine("RegisterAllExtensions(registry);");
+ foreach (FileDescriptor dependency in Descriptor.Dependencies) {
+ writer.WriteLine("{0}.RegisterAllExtensions(registry);", DescriptorUtil.GetFullUmbrellaClassName(dependency));
+ }
+ writer.WriteLine("return registry;");
+ } else {
+ writer.WriteLine("return null;");
}
- writer.WriteLine("});");
writer.Outdent();
+ writer.WriteLine("};");
+
+ // -----------------------------------------------------------------
+ // Invoke internalBuildGeneratedFileFrom() to build the file.
+ writer.WriteLine("pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,");
+ writer.WriteLine(" new pbd::FileDescriptor[] {");
+ foreach (FileDescriptor dependency in Descriptor.Dependencies) {
+ writer.WriteLine(" {0}.Descriptor, ", DescriptorUtil.GetFullUmbrellaClassName(dependency));
+ }
+ writer.WriteLine(" }, assigner);");
writer.Outdent();
+ writer.WriteLine("}");
writer.WriteLine("#endregion");
writer.WriteLine();
}