aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJon Skeet <skeet@pobox.com>2008-11-12 23:39:44 +0000
committerJon Skeet <skeet@pobox.com>2008-11-12 23:39:44 +0000
commitd6343be707cb6a067fe2b5ccc2efd7848072d17c (patch)
treeea4821795bcd032c0bc82461b699c5cef86c42ab /src
parent60c059b8f0b2b01fba14c537e370b56445437510 (diff)
downloadprotobuf-d6343be707cb6a067fe2b5ccc2efd7848072d17c.tar.gz
protobuf-d6343be707cb6a067fe2b5ccc2efd7848072d17c.tar.bz2
protobuf-d6343be707cb6a067fe2b5ccc2efd7848072d17c.zip
Refactored options
Diffstat (limited to 'src')
-rw-r--r--src/ProtoGen.Test/DescriptorUtilTest.cs4
-rw-r--r--src/ProtoGen.Test/HelpersTest.cs33
-rw-r--r--src/ProtoGen.Test/ProtoGen.Test.csproj1
-rw-r--r--src/ProtoGen/DescriptorUtil.cs77
-rw-r--r--src/ProtoGen/ExtensionGenerator.cs6
-rw-r--r--src/ProtoGen/FieldGeneratorBase.cs12
-rw-r--r--src/ProtoGen/Generator.cs16
-rw-r--r--src/ProtoGen/Helpers.cs60
-rw-r--r--src/ProtoGen/MessageGenerator.cs18
-rw-r--r--src/ProtoGen/ProtoGen.csproj2
-rw-r--r--src/ProtoGen/ServiceGenerator.cs26
-rw-r--r--src/ProtoGen/SourceGeneratorBase.cs50
-rw-r--r--src/ProtoGen/UmbrellaClassGenerator.cs21
-rw-r--r--src/ProtocolBuffers.Test/NameHelpersTest.cs32
-rw-r--r--src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj3
-rw-r--r--src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs6
-rw-r--r--src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs6
-rw-r--r--src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs6
-rw-r--r--src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs6
-rw-r--r--src/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs6
-rw-r--r--src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs6
-rw-r--r--src/ProtocolBuffers.Test/TestProtos/___7469.tmp0
-rw-r--r--src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs392
-rw-r--r--src/ProtocolBuffers/Descriptors/FileDescriptor.cs58
-rw-r--r--src/ProtocolBuffers/NameHelpers.cs78
-rw-r--r--src/ProtocolBuffers/ProtocolBuffers.csproj1
26 files changed, 653 insertions, 273 deletions
diff --git a/src/ProtoGen.Test/DescriptorUtilTest.cs b/src/ProtoGen.Test/DescriptorUtilTest.cs
index 0cbc1c3c..2eb60ef1 100644
--- a/src/ProtoGen.Test/DescriptorUtilTest.cs
+++ b/src/ProtoGen.Test/DescriptorUtilTest.cs
@@ -5,7 +5,7 @@ using NUnit.Framework;
namespace Google.ProtocolBuffers.ProtoGen {
[TestFixture]
public class DescriptorUtilTest {
-
+ /* FIXME: Move these around!
[Test]
public void ExplicitNamespace() {
FileDescriptorProto proto = new FileDescriptorProto.Builder {
@@ -64,6 +64,6 @@ namespace Google.ProtocolBuffers.ProtoGen {
FileDescriptorProto proto = new FileDescriptorProto.Builder { Name = "x/y/foo_bar" }.Build();
FileDescriptor descriptor = FileDescriptor.BuildFrom(proto, null);
Assert.AreEqual("FooBar", DescriptorUtil.GetUmbrellaClassName(descriptor));
- }
+ } */
}
}
diff --git a/src/ProtoGen.Test/HelpersTest.cs b/src/ProtoGen.Test/HelpersTest.cs
deleted file mode 100644
index 6896cfb6..00000000
--- a/src/ProtoGen.Test/HelpersTest.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Google.ProtocolBuffers.ProtoGen;
-using NUnit.Framework;
-
-namespace Google.ProtocolBuffers.ProtoGen {
- [TestFixture]
- public class HelpersTest {
-
- [Test]
- public void UnderscoresToPascalCase() {
- Assert.AreEqual("FooBar", Helpers.UnderscoresToPascalCase("Foo_bar"));
- Assert.AreEqual("FooBar", Helpers.UnderscoresToPascalCase("foo_bar"));
- Assert.AreEqual("Foo0Bar", Helpers.UnderscoresToPascalCase("Foo0bar"));
- Assert.AreEqual("FooBar", Helpers.UnderscoresToPascalCase("Foo_+_Bar"));
- }
-
- [Test]
- public void UnderscoresToCamelCase() {
- Assert.AreEqual("fooBar", Helpers.UnderscoresToCamelCase("Foo_bar"));
- Assert.AreEqual("fooBar", Helpers.UnderscoresToCamelCase("foo_bar"));
- Assert.AreEqual("foo0Bar", Helpers.UnderscoresToCamelCase("Foo0bar"));
- Assert.AreEqual("fooBar", Helpers.UnderscoresToCamelCase("Foo_+_Bar"));
- }
-
- [Test]
- public void StripSuffix() {
- string text = "FooBar";
- Assert.IsFalse(Helpers.StripSuffix(ref text, "Foo"));
- Assert.AreEqual("FooBar", text);
- Assert.IsTrue(Helpers.StripSuffix(ref text, "Bar"));
- Assert.AreEqual("Foo", text);
- }
- }
-} \ No newline at end of file
diff --git a/src/ProtoGen.Test/ProtoGen.Test.csproj b/src/ProtoGen.Test/ProtoGen.Test.csproj
index 805c69ae..a1334493 100644
--- a/src/ProtoGen.Test/ProtoGen.Test.csproj
+++ b/src/ProtoGen.Test/ProtoGen.Test.csproj
@@ -47,7 +47,6 @@
<Compile Include="DependencyResolutionTest.cs" />
<Compile Include="DescriptorUtilTest.cs" />
<Compile Include="GeneratorTest.cs" />
- <Compile Include="HelpersTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
diff --git a/src/ProtoGen/DescriptorUtil.cs b/src/ProtoGen/DescriptorUtil.cs
index 72df575c..1d479bf0 100644
--- a/src/ProtoGen/DescriptorUtil.cs
+++ b/src/ProtoGen/DescriptorUtil.cs
@@ -10,80 +10,11 @@ namespace Google.ProtocolBuffers.ProtoGen {
/// </summary>
internal static class DescriptorUtil {
- internal static bool NestClasses(IDescriptor descriptor) {
- // Defaults to false
- return descriptor.File.Options.GetExtension(CSharpOptions.CSharpNestClasses);
- }
-
- internal static string GetNamespace(FileDescriptor descriptor) {
- if (descriptor.Name == "google/protobuf/descriptor.proto") {
- return typeof(DescriptorProtoFile).Namespace;
- }
- return descriptor.Options.HasExtension(CSharpOptions.CSharpNamespace) ?
- descriptor.Options.GetExtension(CSharpOptions.CSharpNamespace) : descriptor.Package;
- }
-
- // Groups are hacky: The name of the field is just the lower-cased name
- // of the group type. In C#, though, we would like to retain the original
- // capitalization of the type name.
- internal static string GetFieldName(FieldDescriptor descriptor) {
- if (descriptor.FieldType == FieldType.Group) {
- return descriptor.MessageType.Name;
- } else {
- return descriptor.Name;
- }
- }
-
- internal static string GetClassName(IDescriptor descriptor) {
- return ToCSharpName(descriptor.FullName, descriptor.File);
- }
-
- internal static string GetFullUmbrellaClassName(FileDescriptor descriptor) {
- string result = GetNamespace(descriptor);
+ internal static string GetFullUmbrellaClassName(IDescriptor descriptor) {
+ CSharpFileOptions options = descriptor.File.CSharpOptions;
+ string result = options.Namespace;
if (result != "") result += '.';
- result += GetUmbrellaClassName(descriptor);
- return "global::" + result;
- }
-
- internal static string GetUmbrellaClassName(FileDescriptor descriptor) {
- if (descriptor.Name == "google/protobuf/descriptor.proto") {
- return typeof(DescriptorProtoFile).Name;
- }
- FileOptions options = descriptor.Options;
- if (options.HasExtension(CSharpOptions.CSharpUmbrellaClassname)) {
- return descriptor.Options.GetExtension(CSharpOptions.CSharpUmbrellaClassname);
- }
- int lastSlash = descriptor.Name.LastIndexOf('/');
- string baseName = descriptor.Name.Substring(lastSlash + 1);
- return Helpers.UnderscoresToPascalCase(StripProto(baseName));
- }
-
- private static string StripProto(string text) {
- if (!Helpers.StripSuffix(ref text, ".protodevel")) {
- Helpers.StripSuffix(ref text, ".proto");
- }
- return text;
- }
-
- private static string ToCSharpName(string name, FileDescriptor file) {
- string result;
- if (!NestClasses(file)) {
- result = GetNamespace(file);
- } else {
- result = GetUmbrellaClassName(file);
- }
- if (result != "") {
- result += '.';
- }
- string classname;
- if (file.Package == "") {
- classname = name;
- } else {
- // Strip the proto package from full_name since we've replaced it with
- // the C# namespace.
- classname = name.Substring(file.Package.Length + 1);
- }
- result += classname.Replace(".", ".Types.");
+ result += options.UmbrellaClassname;
return "global::" + result;
}
diff --git a/src/ProtoGen/ExtensionGenerator.cs b/src/ProtoGen/ExtensionGenerator.cs
index d5a233b1..d1acacdf 100644
--- a/src/ProtoGen/ExtensionGenerator.cs
+++ b/src/ProtoGen/ExtensionGenerator.cs
@@ -9,15 +9,15 @@ namespace Google.ProtocolBuffers.ProtoGen {
}
public void Generate(TextGenerator writer) {
- string name = Helpers.UnderscoresToPascalCase(DescriptorUtil.GetFieldName(Descriptor));
+ string name = NameHelpers.UnderscoresToPascalCase(GetFieldName(Descriptor));
string type;
switch (Descriptor.MappedType) {
case MappedType.Message:
- type = DescriptorUtil.GetClassName(Descriptor.MessageType);
+ type = GetClassName(Descriptor.MessageType);
break;
case MappedType.Enum:
- type = DescriptorUtil.GetClassName(Descriptor.EnumType);
+ type = GetClassName(Descriptor.EnumType);
break;
default:
type = DescriptorUtil.GetMappedTypeName(Descriptor.MappedType);
diff --git a/src/ProtoGen/FieldGeneratorBase.cs b/src/ProtoGen/FieldGeneratorBase.cs
index 6c8f5416..a6e086ed 100644
--- a/src/ProtoGen/FieldGeneratorBase.cs
+++ b/src/ProtoGen/FieldGeneratorBase.cs
@@ -50,7 +50,7 @@ namespace Google.ProtocolBuffers.ProtoGen {
if (!Descriptor.HasDefaultValue) {
return "pb::ByteString.Empty";
}
- return string.Format("(pb::ByteString) {0}.Descriptor.Fields[{1}].DefaultValue", DescriptorUtil.GetClassName(Descriptor.ContainingType), Descriptor.Index);
+ return string.Format("(pb::ByteString) {0}.Descriptor.Fields[{1}].DefaultValue", GetClassName(Descriptor.ContainingType), Descriptor.Index);
case FieldType.String:
if (AllPrintableAscii(Descriptor.Proto.DefaultValue)) {
// All chars are ASCII and printable. In this case we only
@@ -61,7 +61,7 @@ namespace Google.ProtocolBuffers.ProtoGen {
.Replace("\"", "\\\"")
+ "\"";
}
- return string.Format("(string) {0}.Descriptor.Fields[{1}].DefaultValue", DescriptorUtil.GetClassName(Descriptor.ContainingType), Descriptor.Index);
+ return string.Format("(string) {0}.Descriptor.Fields[{1}].DefaultValue", GetClassName(Descriptor.ContainingType), Descriptor.Index);
case FieldType.Enum:
return TypeName + "." + ((EnumValueDescriptor) Descriptor.DefaultValue).Name;
case FieldType.Message:
@@ -88,11 +88,11 @@ namespace Google.ProtocolBuffers.ProtoGen {
}
protected string CapitalizedName {
- get { return Helpers.UnderscoresToPascalCase(DescriptorUtil.GetFieldName(Descriptor)); }
+ get { return NameHelpers.UnderscoresToPascalCase(GetFieldName(Descriptor)); }
}
protected string Name {
- get { return Helpers.UnderscoresToCamelCase(DescriptorUtil.GetFieldName(Descriptor)); }
+ get { return NameHelpers.UnderscoresToCamelCase(GetFieldName(Descriptor)); }
}
protected int Number {
@@ -103,10 +103,10 @@ namespace Google.ProtocolBuffers.ProtoGen {
get {
switch (Descriptor.FieldType) {
case FieldType.Enum:
- return DescriptorUtil.GetClassName(Descriptor.EnumType);
+ return GetClassName(Descriptor.EnumType);
case FieldType.Message:
case FieldType.Group:
- return DescriptorUtil.GetClassName(Descriptor.MessageType);
+ return GetClassName(Descriptor.MessageType);
default:
return DescriptorUtil.GetMappedTypeName(Descriptor.MappedType);
}
diff --git a/src/ProtoGen/Generator.cs b/src/ProtoGen/Generator.cs
index b447d42f..f7a82cca 100644
--- a/src/ProtoGen/Generator.cs
+++ b/src/ProtoGen/Generator.cs
@@ -30,11 +30,8 @@ namespace Google.ProtocolBuffers.ProtoGen {
foreach (string inputFile in options.InputFiles) {
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);
+ extensionRegistry.Add(CSharpFileOptions.CSharpOptions);
+ extensionRegistry.Add(CSharpFieldOptions.CSharpOptions);
using (Stream inputStream = File.OpenRead(inputFile)) {
descriptorProtos = FileDescriptorSet.ParseFrom(inputStream, extensionRegistry);
}
@@ -51,12 +48,9 @@ namespace Google.ProtocolBuffers.ProtoGen {
/// 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);
+ UmbrellaClassGenerator ucg = new UmbrellaClassGenerator(descriptor);
+ using (TextWriter textWriter = File.CreateText(Path.Combine(options.OutputDirectory, descriptor.CSharpOptions.UmbrellaClassname + ".cs"))) {
+ TextGenerator writer = new TextGenerator(textWriter);
ucg.Generate(writer);
/*
GenerateSiblings(umbrellaSource, descriptor, descriptor.MessageTypes);
diff --git a/src/ProtoGen/Helpers.cs b/src/ProtoGen/Helpers.cs
index 74697bfa..a6a0e6c4 100644
--- a/src/ProtoGen/Helpers.cs
+++ b/src/ProtoGen/Helpers.cs
@@ -8,71 +8,11 @@ namespace Google.ProtocolBuffers.ProtoGen {
/// Helpers to resolve class names etc.
/// </summary>
internal static class Helpers {
- internal static string UnderscoresToPascalCase(string input) {
- return UnderscoresToPascalOrCamelCase(input, true);
- }
-
- internal static string UnderscoresToCamelCase(string input) {
- return UnderscoresToPascalOrCamelCase(input, false);
- }
-
internal static void WriteNamespaces(TextGenerator writer) {
writer.WriteLine("using pb = global::Google.ProtocolBuffers;");
writer.WriteLine("using pbc = global::Google.ProtocolBuffers.Collections;");
writer.WriteLine("using pbd = global::Google.ProtocolBuffers.Descriptors;");
writer.WriteLine("using scg = global::System.Collections.Generic;");
}
-
- /// <summary>
- /// Converts a string to Pascal or Camel case. The first letter is capitalized or
- /// lower-cased depending on <paramref name="pascal"/> is true.
- /// After the first letter, any punctuation is removed but triggers capitalization
- /// of the next letter. Digits are preserved but trigger capitalization of the next
- /// letter.
- /// All capitalisation is done in the invariant culture.
- /// </summary>
- private static string UnderscoresToPascalOrCamelCase(string input, bool pascal) {
- StringBuilder result = new StringBuilder();
- bool capitaliseNext = pascal;
- for (int i=0; i < input.Length; i++) {
- char c = input[i];
- if ('a' <= c && c <= 'z') {
- if (capitaliseNext) {
- result.Append(char.ToUpperInvariant(c));
- } else {
- result.Append(c);
- }
- capitaliseNext = false;
- } else if ('A' <= c && c <= 'Z') {
- if (i == 0 && !pascal) {
- // Force first letter to lower-case unless explicitly told to
- // capitalize it.
- result.Append(char.ToLowerInvariant(c));
- } else {
- // Capital letters after the first are left as-is.
- result.Append(c);
- }
- capitaliseNext = false;
- } else if ('0' <= c && c <= '9') {
- result.Append(c);
- capitaliseNext = true;
- } else {
- capitaliseNext = true;
- }
- }
- return result.ToString();
- }
-
- /// <summary>
- /// Attempts to strip a suffix from a string, returning whether
- /// or not the suffix was actually present.
- /// </summary>
- internal static bool StripSuffix(ref string text, string suffix) {
- if (text.EndsWith(suffix)) {
- text = text.Substring(0, text.Length - suffix.Length);
- return true;
- }
- return false;
- }
}
}
diff --git a/src/ProtoGen/MessageGenerator.cs b/src/ProtoGen/MessageGenerator.cs
index 52dc6d07..f877ac6d 100644
--- a/src/ProtoGen/MessageGenerator.cs
+++ b/src/ProtoGen/MessageGenerator.cs
@@ -15,7 +15,7 @@ namespace Google.ProtocolBuffers.ProtoGen {
}
private string FullClassName {
- get { return DescriptorUtil.GetClassName(Descriptor); }
+ get { return GetClassName(Descriptor); }
}
/// <summary>
@@ -38,7 +38,7 @@ namespace Google.ProtocolBuffers.ProtoGen {
string identifier = GetUniqueFileScopeIdentifier(Descriptor);
// The descriptor for this type.
- string access = Descriptor.File.Options.GetExtension(CSharpOptions.CSharpNestClasses) ? "private" : "internal";
+ string access = Descriptor.File.CSharpOptions.NestClasses ? "private" : "internal";
writer.WriteLine("{0} static readonly pbd::MessageDescriptor internal__{1}__Descriptor", access, identifier);
if (Descriptor.ContainingType == null) {
writer.WriteLine(" = Descriptor.MessageTypes[{0}];", Descriptor.Index);
@@ -51,7 +51,7 @@ namespace Google.ProtocolBuffers.ProtoGen {
FullClassName, identifier);
writer.Print(" new string[] { ");
foreach (FieldDescriptor field in Descriptor.Fields) {
- writer.Write("\"{0}\", ", Helpers.UnderscoresToPascalCase(DescriptorUtil.GetFieldName(field)));
+ writer.Write("\"{0}\", ", NameHelpers.UnderscoresToPascalCase(GetFieldName(field)));
}
writer.WriteLine("});");
@@ -80,12 +80,12 @@ namespace Google.ProtocolBuffers.ProtoGen {
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("public static pbd::MessageDescriptor Descriptor {");
- writer.WriteLine(" get {{ return {0}.internal__{1}__Descriptor; }}", DescriptorUtil.GetFullUmbrellaClassName(Descriptor.File),
+ writer.WriteLine(" get {{ return {0}.internal__{1}__Descriptor; }}", DescriptorUtil.GetFullUmbrellaClassName(Descriptor),
GetUniqueFileScopeIdentifier(Descriptor));
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine("protected override pb::FieldAccess.FieldAccessorTable<{0}, {0}.Builder> InternalFieldAccessors {{", ClassName);
- writer.WriteLine(" get {{ return {0}.internal__{1}__FieldAccessorTable; }}", DescriptorUtil.GetFullUmbrellaClassName(Descriptor.File),
+ writer.WriteLine(" get {{ return {0}.internal__{1}__FieldAccessorTable; }}", DescriptorUtil.GetFullUmbrellaClassName(Descriptor),
GetUniqueFileScopeIdentifier(Descriptor));
writer.WriteLine("}");
writer.WriteLine();
@@ -186,7 +186,7 @@ namespace Google.ProtocolBuffers.ProtoGen {
writer.WriteLine();
}
- private static void GenerateSerializeOneField(TextGenerator writer, FieldDescriptor fieldDescriptor) {
+ private void GenerateSerializeOneField(TextGenerator writer, FieldDescriptor fieldDescriptor) {
SourceGenerators.CreateFieldGenerator(fieldDescriptor).GenerateSerializationCode(writer);
}
@@ -415,7 +415,7 @@ namespace Google.ProtocolBuffers.ProtoGen {
// "has" fields into a single bitfield.
foreach (FieldDescriptor field in Descriptor.Fields) {
if (field.IsRequired) {
- writer.WriteLine("if (!has{0}) return false;", Helpers.UnderscoresToPascalCase(field.Name));
+ writer.WriteLine("if (!has{0}) return false;", NameHelpers.UnderscoresToPascalCase(field.Name));
}
}
@@ -425,9 +425,9 @@ namespace Google.ProtocolBuffers.ProtoGen {
!HasRequiredFields(field.MessageType, new Dictionary<MessageDescriptor, object>())) {
continue;
}
- string propertyName = Helpers.UnderscoresToPascalCase(DescriptorUtil.GetFieldName(field));
+ string propertyName = NameHelpers.UnderscoresToPascalCase(GetFieldName(field));
if (field.IsRepeated) {
- writer.WriteLine("foreach ({0} element in {1}List) {{", DescriptorUtil.GetClassName(field.MessageType), propertyName);
+ writer.WriteLine("foreach ({0} element in {1}List) {{", GetClassName(field.MessageType), propertyName);
writer.WriteLine(" if (!element.IsInitialized) return false;");
writer.WriteLine("}");
} else if (field.IsOptional) {
diff --git a/src/ProtoGen/ProtoGen.csproj b/src/ProtoGen/ProtoGen.csproj
index f48df42c..126c1d04 100644
--- a/src/ProtoGen/ProtoGen.csproj
+++ b/src/ProtoGen/ProtoGen.csproj
@@ -36,6 +36,8 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DescriptorUtil.cs" />
diff --git a/src/ProtoGen/ServiceGenerator.cs b/src/ProtoGen/ServiceGenerator.cs
index d36eec19..ebc9d46c 100644
--- a/src/ProtoGen/ServiceGenerator.cs
+++ b/src/ProtoGen/ServiceGenerator.cs
@@ -20,17 +20,17 @@ namespace Google.ProtocolBuffers.ProtoGen {
writer.Indent();
foreach (MethodDescriptor method in Descriptor.Methods) {
- writer.WriteLine("{0} abstract void {1}(", ClassAccessLevel, Helpers.UnderscoresToPascalCase(method.Name));
+ writer.WriteLine("{0} abstract void {1}(", ClassAccessLevel, NameHelpers.UnderscoresToPascalCase(method.Name));
writer.WriteLine(" pb::IRpcController controller,");
- writer.WriteLine(" {0} request,", DescriptorUtil.GetClassName(method.InputType));
- writer.WriteLine(" global::System.Action<{0}> done);", DescriptorUtil.GetClassName(method.OutputType));
+ writer.WriteLine(" {0} request,", GetClassName(method.InputType));
+ writer.WriteLine(" global::System.Action<{0}> done);", GetClassName(method.OutputType));
}
// Generate Descriptor and DescriptorForType.
writer.WriteLine();
writer.WriteLine("{0} static pbd::ServiceDescriptor Descriptor {{", ClassAccessLevel);
writer.WriteLine(" get {{ return {0}.Descriptor.Services[{1}]; }}",
- DescriptorUtil.GetUmbrellaClassName(Descriptor.File), Descriptor.Index);
+ Descriptor.File.CSharpOptions.UmbrellaClassname, Descriptor.Index);
writer.WriteLine("}");
writer.WriteLine("{0} pbd::ServiceDescriptor DescriptorForType {{", ClassAccessLevel);
writer.WriteLine(" get { return Descriptor; }");
@@ -62,8 +62,8 @@ namespace Google.ProtocolBuffers.ProtoGen {
foreach (MethodDescriptor method in Descriptor.Methods) {
writer.WriteLine("case {0}:", method.Index);
writer.WriteLine(" this.{0}(controller, ({1}) request,",
- Helpers.UnderscoresToPascalCase(method.Name), DescriptorUtil.GetClassName(method.InputType));
- writer.WriteLine(" pb::RpcUtil.SpecializeCallback<{0}>(", DescriptorUtil.GetClassName(method.OutputType));
+ NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType));
+ writer.WriteLine(" pb::RpcUtil.SpecializeCallback<{0}>(", GetClassName(method.OutputType));
writer.WriteLine(" done));");
writer.WriteLine(" return;");
}
@@ -89,7 +89,7 @@ namespace Google.ProtocolBuffers.ProtoGen {
foreach (MethodDescriptor method in Descriptor.Methods) {
writer.WriteLine("case {0}:", method.Index);
writer.WriteLine(" return {0}.DefaultInstance;",
- DescriptorUtil.GetClassName(which == RequestOrResponse.Request ? method.InputType : method.OutputType));
+ GetClassName(which == RequestOrResponse.Request ? method.InputType : method.OutputType));
}
writer.WriteLine("default:");
writer.WriteLine(" throw new global::System.InvalidOperationException(\"Can't get here.\");");
@@ -105,7 +105,7 @@ namespace Google.ProtocolBuffers.ProtoGen {
writer.WriteLine(" return new Stub(channel);");
writer.WriteLine("}");
writer.WriteLine();
- writer.WriteLine("{0} class Stub : {1} {{", ClassAccessLevel, DescriptorUtil.GetClassName(Descriptor));
+ writer.WriteLine("{0} class Stub : {1} {{", ClassAccessLevel, GetClassName(Descriptor));
writer.Indent();
writer.WriteLine("internal Stub(pb::IRpcChannel channel) {");
writer.WriteLine(" this.channel = channel;");
@@ -119,15 +119,15 @@ namespace Google.ProtocolBuffers.ProtoGen {
foreach (MethodDescriptor method in Descriptor.Methods) {
writer.WriteLine();
- writer.WriteLine("public override void {0}(", Helpers.UnderscoresToPascalCase(method.Name));
+ writer.WriteLine("public override void {0}(", NameHelpers.UnderscoresToPascalCase(method.Name));
writer.WriteLine(" pb::IRpcController controller,");
- writer.WriteLine(" {0} request,", DescriptorUtil.GetClassName(method.InputType));
- writer.WriteLine(" global::System.Action<{0}> done) {{", DescriptorUtil.GetClassName(method.OutputType));
+ writer.WriteLine(" {0} request,", GetClassName(method.InputType));
+ writer.WriteLine(" global::System.Action<{0}> done) {{", GetClassName(method.OutputType));
writer.Indent();
writer.WriteLine("channel.CallMethod(Descriptor.Methods[{0}],", method.Index);
- writer.WriteLine(" controller, request, {0}.DefaultInstance,", DescriptorUtil.GetClassName(method.OutputType));
+ writer.WriteLine(" controller, request, {0}.DefaultInstance,", GetClassName(method.OutputType));
writer.WriteLine(" pb::RpcUtil.GeneralizeCallback<{0}, {0}.Builder>(done, {0}.DefaultInstance));",
- DescriptorUtil.GetClassName(method.OutputType));
+ GetClassName(method.OutputType));
writer.Outdent();
writer.WriteLine("}");
}
diff --git a/src/ProtoGen/SourceGeneratorBase.cs b/src/ProtoGen/SourceGeneratorBase.cs
index 7787d59a..6abe1dde 100644
--- a/src/ProtoGen/SourceGeneratorBase.cs
+++ b/src/ProtoGen/SourceGeneratorBase.cs
@@ -1,5 +1,5 @@
+using System;
using System.Collections.Generic;
-using Google.ProtocolBuffers.DescriptorProtos;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.ProtoGen {
@@ -15,19 +15,51 @@ namespace Google.ProtocolBuffers.ProtoGen {
get { return descriptor; }
}
- protected string ClassAccessLevel {
- get {
- // Default to public
- return !descriptor.File.Options.HasExtension(CSharpOptions.CSharpPublicClasses)
- || descriptor.File.Options.GetExtension(CSharpOptions.CSharpPublicClasses) ? "public" : "internal";
+ internal static string GetClassName(IDescriptor descriptor) {
+ return ToCSharpName(descriptor.FullName, descriptor.File);
+ }
+
+ // Groups are hacky: The name of the field is just the lower-cased name
+ // of the group type. In C#, though, we would like to retain the original
+ // capitalization of the type name.
+ internal static string GetFieldName(FieldDescriptor descriptor) {
+ if (descriptor.FieldType == FieldType.Group) {
+ return descriptor.MessageType.Name;
+ } else {
+ return descriptor.Name;
+ }
+ }
+
+ private static string ToCSharpName(string name, FileDescriptor file) {
+ string result = file.CSharpOptions.Namespace;
+ if (file.CSharpOptions.NestClasses) {
+ if (result != "") {
+ result += ".";
+ }
+ result += file.CSharpOptions.UmbrellaClassname;
+ }
+ if (result != "") {
+ result += '.';
+ }
+ string classname;
+ if (file.Package == "") {
+ classname = name;
+ } else {
+ // Strip the proto package from full_name since we've replaced it with
+ // the C# namespace.
+ classname = name.Substring(file.Package.Length + 1);
}
+ result += classname.Replace(".", ".Types.");
+ return "global::" + result;
}
- public bool MultipleFiles {
- get { return descriptor.File.Options.GetExtension(CSharpOptions.CSharpMultipleFiles); }
+ protected string ClassAccessLevel {
+ get {
+ return descriptor.File.CSharpOptions.PublicClasses ? "public" : "internal";
+ }
}
- protected static void WriteChildren<TChild>(TextGenerator writer, string region, IEnumerable<TChild> children)
+ protected void WriteChildren<TChild>(TextGenerator writer, string region, IEnumerable<TChild> children)
where TChild : IDescriptor {
// Copy the set of children; makes access easier
List<TChild> copy = new List<TChild>(children);
diff --git a/src/ProtoGen/UmbrellaClassGenerator.cs b/src/ProtoGen/UmbrellaClassGenerator.cs
index cbb50682..938507b5 100644
--- a/src/ProtoGen/UmbrellaClassGenerator.cs
+++ b/src/ProtoGen/UmbrellaClassGenerator.cs
@@ -13,6 +13,10 @@ namespace Google.ProtocolBuffers.ProtoGen {
: base(descriptor) {
}
+ public string UmbrellaClassName {
+ get { throw new NotImplementedException(); }
+ }
+
public void Generate(TextGenerator writer) {
WriteIntroduction(writer);
WriteDescriptor(writer);
@@ -23,18 +27,18 @@ namespace Google.ProtocolBuffers.ProtoGen {
}
writer.WriteLine("#endregion");
// The class declaration either gets closed before or after the children are written.
- if (!DescriptorUtil.NestClasses(Descriptor)) {
+ if (!Descriptor.CSharpOptions.NestClasses) {
writer.Outdent();
writer.WriteLine("}");
}
WriteChildren(writer, "Enums", Descriptor.EnumTypes);
WriteChildren(writer, "Messages", Descriptor.MessageTypes);
WriteChildren(writer, "Services", Descriptor.Services);
- if (DescriptorUtil.NestClasses(Descriptor)) {
+ if (Descriptor.CSharpOptions.NestClasses) {
writer.Outdent();
writer.WriteLine("}");
}
- if (DescriptorUtil.GetNamespace(Descriptor) != "") {
+ if (Descriptor.CSharpOptions.Namespace != "") {
writer.Outdent();
writer.WriteLine("}");
}
@@ -45,13 +49,13 @@ namespace Google.ProtocolBuffers.ProtoGen {
writer.WriteLine();
Helpers.WriteNamespaces(writer);
- if (DescriptorUtil.GetNamespace(Descriptor) != "") {
- writer.WriteLine("namespace {0} {{", DescriptorUtil.GetNamespace(Descriptor));
+ if (Descriptor.CSharpOptions.Namespace != "") {
+ writer.WriteLine("namespace {0} {{", Descriptor.CSharpOptions.Namespace);
writer.Indent();
writer.WriteLine();
}
- writer.WriteLine("{0} static partial class {1} {{", ClassAccessLevel, DescriptorUtil.GetUmbrellaClassName(Descriptor));
+ writer.WriteLine("{0} static partial class {1} {{", ClassAccessLevel, Descriptor.CSharpOptions.UmbrellaClassname);
writer.WriteLine();
writer.Indent();
}
@@ -79,11 +83,6 @@ namespace Google.ProtocolBuffers.ProtoGen {
writer.WriteLine("new pbd::FileDescriptor[] {");
foreach (FileDescriptor dependency in Descriptor.Dependencies) {
- // TODO(jonskeet): The normal code won't work for the bootstrapping descriptor, because we don't get unknown fields :(
- if (dependency.Package == "google.protobuf" && dependency.Name.EndsWith("descriptor.proto")) {
- writer.WriteLine(" global::" + typeof(DescriptorProtoFile).FullName + ".Descriptor, ");
- continue;
- }
writer.WriteLine(" {0}.Descriptor, ", DescriptorUtil.GetFullUmbrellaClassName(dependency));
}
writer.WriteLine("});");
diff --git a/src/ProtocolBuffers.Test/NameHelpersTest.cs b/src/ProtocolBuffers.Test/NameHelpersTest.cs
new file mode 100644
index 00000000..0bdab19c
--- /dev/null
+++ b/src/ProtocolBuffers.Test/NameHelpersTest.cs
@@ -0,0 +1,32 @@
+using NUnit.Framework;
+
+namespace Google.ProtocolBuffers {
+ [TestFixture]
+ public class NameHelpersTest {
+
+ [Test]
+ public void UnderscoresToPascalCase() {
+ Assert.AreEqual("FooBar", NameHelpers.UnderscoresToPascalCase("Foo_bar"));
+ Assert.AreEqual("FooBar", NameHelpers.UnderscoresToPascalCase("foo_bar"));
+ Assert.AreEqual("Foo0Bar", NameHelpers.UnderscoresToPascalCase("Foo0bar"));
+ Assert.AreEqual("FooBar", NameHelpers.UnderscoresToPascalCase("Foo_+_Bar"));
+ }
+
+ [Test]
+ public void UnderscoresToCamelCase() {
+ Assert.AreEqual("fooBar", NameHelpers.UnderscoresToCamelCase("Foo_bar"));
+ Assert.AreEqual("fooBar", NameHelpers.UnderscoresToCamelCase("foo_bar"));
+ Assert.AreEqual("foo0Bar", NameHelpers.UnderscoresToCamelCase("Foo0bar"));
+ Assert.AreEqual("fooBar", NameHelpers.UnderscoresToCamelCase("Foo_+_Bar"));
+ }
+
+ [Test]
+ public void StripSuffix() {
+ string text = "FooBar";
+ Assert.IsFalse(NameHelpers.StripSuffix(ref text, "Foo"));
+ Assert.AreEqual("FooBar", text);
+ Assert.IsTrue(NameHelpers.StripSuffix(ref text, "Bar"));
+ Assert.AreEqual("Foo", text);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj b/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
index 7f84da07..836ee2d8 100644
--- a/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
+++ b/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
@@ -42,6 +42,8 @@
<HintPath>..\..\lib\Rhino.Mocks.dll</HintPath>
</Reference>
<Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AbstractMessageTest.cs" />
@@ -55,6 +57,7 @@
<Compile Include="MessageStreamIteratorTest.cs" />
<Compile Include="MessageStreamWriterTest.cs" />
<Compile Include="MessageTest.cs" />
+ <Compile Include="NameHelpersTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReflectionTester.cs" />
<Compile Include="ServiceTest.cs" />
diff --git a/src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs b/src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs
index 8a1def53..ff777cbb 100644
--- a/src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs
+++ b/src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs
@@ -109,9 +109,9 @@ namespace Google.ProtocolBuffers.TestProtos {
"Zi5NZXNzYWdlT3B0aW9ucxjvi9IDIAEoCzIlLnByb3RvYnVmX3VuaXR0ZXN0" +
"LkNvbXBsZXhPcHRpb25UeXBlMzpXCgtjb21wbGV4b3B0NhIfLmdvb2dsZS5w" +
"cm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjMy88DIAEoCjIeLnByb3RvYnVmX3Vu" +
- "aXR0ZXN0LkNvbXBsZXhPcHQ2QlCC4gkhR29vZ2xlLlByb3RvY29sQnVmZmVy" +
- "cy5UZXN0UHJvdG9ziuIJHlVuaXRUZXN0Q3VzdG9tT3B0aW9uc1Byb3RvRmls" +
- "ZfDowR3qrcDlJA=="),
+ "aXR0ZXN0LkNvbXBsZXhPcHQ2Qk/CPkMKIUdvb2dsZS5Qcm90b2NvbEJ1ZmZl" +
+ "cnMuVGVzdFByb3RvcxIeVW5pdFRlc3RDdXN0b21PcHRpb25zUHJvdG9GaWxl" +
+ "8OjBHeqtwOUk"),
new pbd::FileDescriptor[] {
global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor,
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor,
diff --git a/src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs b/src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs
index 9dcbf1fe..c31de51b 100644
--- a/src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs
+++ b/src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs
@@ -21,9 +21,9 @@ namespace Google.ProtocolBuffers.TestProtos {
"ci5wcm90byKhAQoZVGVzdEVtYmVkT3B0aW1pemVkRm9yU2l6ZRJBChBvcHRp" +
"b25hbF9tZXNzYWdlGAEgASgLMicucHJvdG9idWZfdW5pdHRlc3QuVGVzdE9w" +
"dGltaXplZEZvclNpemUSQQoQcmVwZWF0ZWRfbWVzc2FnZRgCIAMoCzInLnBy" +
- "b3RvYnVmX3VuaXR0ZXN0LlRlc3RPcHRpbWl6ZWRGb3JTaXplQkxIAYLiCSFH" +
- "b29nbGUuUHJvdG9jb2xCdWZmZXJzLlRlc3RQcm90b3OK4gkhVW5pdFRlc3RF" +
- "bWJlZE9wdGltaXplRm9yUHJvdG9GaWxl"),
+ "b3RvYnVmX3VuaXR0ZXN0LlRlc3RPcHRpbWl6ZWRGb3JTaXplQktIAcI+Rgoh" +
+ "R29vZ2xlLlByb3RvY29sQnVmZmVycy5UZXN0UHJvdG9zEiFVbml0VGVzdEVt" +
+ "YmVkT3B0aW1pemVGb3JQcm90b0ZpbGU="),
new pbd::FileDescriptor[] {
global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor,
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor,
diff --git a/src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs b/src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs
index c8f5bef2..c774c644 100644
--- a/src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs
+++ b/src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs
@@ -19,9 +19,9 @@ namespace Google.ProtocolBuffers.TestProtos {
"b3B0aW9ucy5wcm90bxogZ29vZ2xlL3Byb3RvYnVmL2Rlc2NyaXB0b3IucHJv" +
"dG8iGgoNSW1wb3J0TWVzc2FnZRIJCgFkGAEgASgFKjwKCkltcG9ydEVudW0S" +
"DgoKSU1QT1JUX0ZPTxAHEg4KCklNUE9SVF9CQVIQCBIOCgpJTVBPUlRfQkFa" +
- "EAlCXAoYY29tLmdvb2dsZS5wcm90b2J1Zi50ZXN0SAGC4gkhR29vZ2xlLlBy" +
- "b3RvY29sQnVmZmVycy5UZXN0UHJvdG9ziuIJF1VuaXRUZXN0SW1wb3J0UHJv" +
- "dG9GaWxl"),
+ "EAlCWwoYY29tLmdvb2dsZS5wcm90b2J1Zi50ZXN0SAHCPjwKIUdvb2dsZS5Q" +
+ "cm90b2NvbEJ1ZmZlcnMuVGVzdFByb3RvcxIXVW5pdFRlc3RJbXBvcnRQcm90" +
+ "b0ZpbGU="),
new pbd::FileDescriptor[] {
global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor,
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor,
diff --git a/src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs b/src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs
index 72b06d33..e83794e0 100644
--- a/src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs
+++ b/src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs
@@ -28,9 +28,9 @@ namespace Google.ProtocolBuffers.TestProtos {
"U2V0GPm7XiABKAsyKy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWVzc2FnZVNl" +
"dEV4dGVuc2lvbjIibgoNUmF3TWVzc2FnZVNldBIzCgRpdGVtGAEgAygKMiUu" +
"cHJvdG9idWZfdW5pdHRlc3QuUmF3TWVzc2FnZVNldC5JdGVtGigKBEl0ZW0S" +
- "DwoHdHlwZV9pZBgCIAIoBRIPCgdtZXNzYWdlGAMgAigMQkZIAYLiCSFHb29n" +
- "bGUuUHJvdG9jb2xCdWZmZXJzLlRlc3RQcm90b3OK4gkbVW5pdFRlc3RNZXNz" +
- "YWdlU2V0UHJvdG9GaWxl"),
+ "DwoHdHlwZV9pZBgCIAIoBRIPCgdtZXNzYWdlGAMgAigMQkVIAcI+QAohR29v" +
+ "Z2xlLlByb3RvY29sQnVmZmVycy5UZXN0UHJvdG9zEhtVbml0VGVzdE1lc3Nh" +
+ "Z2VTZXRQcm90b0ZpbGU="),
new pbd::FileDescriptor[] {
global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor,
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor,
diff --git a/src/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs b/src/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs
index cc555777..3129ec47 100644
--- a/src/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs
+++ b/src/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs
@@ -26,9 +26,9 @@ namespace Google.ProtocolBuffers.TestProtos {
"dWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkT3B0aW1pemVkRm9yU2l6ZSIpChxU" +
"ZXN0UmVxdWlyZWRPcHRpbWl6ZWRGb3JTaXplEgkKAXgYASACKAUiWgocVGVz" +
"dE9wdGlvbmFsT3B0aW1pemVkRm9yU2l6ZRI6CgFvGAEgASgLMi8ucHJvdG9i" +
- "dWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkT3B0aW1pemVkRm9yU2l6ZUJHSAKC" +
- "4gkhR29vZ2xlLlByb3RvY29sQnVmZmVycy5UZXN0UHJvdG9ziuIJHFVuaXRU" +
- "ZXN0T3B0aW1pemVGb3JQcm90b0ZpbGU="),
+ "dWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkT3B0aW1pemVkRm9yU2l6ZUJGSALC" +
+ "PkEKIUdvb2dsZS5Qcm90b2NvbEJ1ZmZlcnMuVGVzdFByb3RvcxIcVW5pdFRl" +
+ "c3RPcHRpbWl6ZUZvclByb3RvRmlsZQ=="),
new pbd::FileDescriptor[] {
global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor,
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor,
diff --git a/src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs b/src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs
index 9e706b02..03195c9d 100644
--- a/src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs
+++ b/src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs
@@ -284,9 +284,9 @@ namespace Google.ProtocolBuffers.TestProtos {
"dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYVSABKAk6AzEyM0ICCAE6QgoT" +
"bXlfZXh0ZW5zaW9uX3N0cmluZxIlLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RG" +
"aWVsZE9yZGVyaW5ncxgyIAEoCTo/ChBteV9leHRlbnNpb25faW50EiUucHJv" +
- "dG9idWZfdW5pdHRlc3QuVGVzdEZpZWxkT3JkZXJpbmdzGAUgASgFQktCDVVu" +
- "aXR0ZXN0UHJvdG9IAYLiCSFHb29nbGUuUHJvdG9jb2xCdWZmZXJzLlRlc3RQ" +
- "cm90b3OK4gkRVW5pdFRlc3RQcm90b0ZpbGU="),
+ "dG9idWZfdW5pdHRlc3QuVGVzdEZpZWxkT3JkZXJpbmdzGAUgASgFQkpCDVVu" +
+ "aXR0ZXN0UHJvdG9IAcI+NgohR29vZ2xlLlByb3RvY29sQnVmZmVycy5UZXN0" +
+ "UHJvdG9zEhFVbml0VGVzdFByb3RvRmlsZQ=="),
new pbd::FileDescriptor[] {
global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor,
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor,
diff --git a/src/ProtocolBuffers.Test/TestProtos/___7469.tmp b/src/ProtocolBuffers.Test/TestProtos/___7469.tmp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/ProtocolBuffers.Test/TestProtos/___7469.tmp
diff --git a/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs b/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs
index 14d6bb64..55a30030 100644
--- a/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs
+++ b/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs
@@ -15,35 +15,381 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
private static readonly pbd::FileDescriptor descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom(
global::System.Convert.FromBase64String(
"CiRnb29nbGUvcHJvdG9idWYvY3NoYXJwX29wdGlvbnMucHJvdG8SD2dvb2ds" +
- "ZS5wcm90b2J1ZhogZ29vZ2xlL3Byb3RvYnVmL2Rlc2NyaXB0b3IucHJvdG86" +
- "NwoPQ1NoYXJwTmFtZXNwYWNlEhwuZ29vZ2xlLnByb3RvYnVmLkZpbGVPcHRp" +
- "b25zGKCcASABKAk6PwoXQ1NoYXJwVW1icmVsbGFDbGFzc25hbWUSHC5nb29n" +
- "bGUucHJvdG9idWYuRmlsZU9wdGlvbnMYoZwBIAEoCTo7ChNDU2hhcnBNdWx0" +
- "aXBsZUZpbGVzEhwuZ29vZ2xlLnByb3RvYnVmLkZpbGVPcHRpb25zGKKcASAB" +
- "KAg6OQoRQ1NoYXJwTmVzdENsYXNzZXMSHC5nb29nbGUucHJvdG9idWYuRmls" +
- "ZU9wdGlvbnMYo5wBIAEoCDo7ChNDU2hhcnBQdWJsaWNDbGFzc2VzEhwuZ29v" +
- "Z2xlLnByb3RvYnVmLkZpbGVPcHRpb25zGKScASABKAhCPILiCSdHb29nbGUu" +
- "UHJvdG9jb2xCdWZmZXJzLkRlc2NyaXB0b3JQcm90b3OK4gkNQ1NoYXJwT3B0" +
- "aW9ucw=="),
+ "ZS5wcm90b2J1ZhogZ29vZ2xlL3Byb3RvYnVmL2Rlc2NyaXB0b3IucHJvdG8i" +
+ "4wEKEUNTaGFycEZpbGVPcHRpb25zEhEKCW5hbWVzcGFjZRgBIAEoCRIaChJ1" +
+ "bWJyZWxsYV9jbGFzc25hbWUYAiABKAkSFgoOcHVibGljX2NsYXNzZXMYAyAB" +
+ "KAgSFgoObXVsdGlwbGVfZmlsZXMYBCABKAgSFAoMbmVzdF9jbGFzc2VzGAUg" +
+ "ASgIMlkKDmNzaGFycF9vcHRpb25zEhwuZ29vZ2xlLnByb3RvYnVmLkZpbGVP" +
+ "cHRpb25zGOgHIAEoCzIiLmdvb2dsZS5wcm90b2J1Zi5DU2hhcnBGaWxlT3B0" +
+ "aW9ucyKIAQoSQ1NoYXJwRmllbGRPcHRpb25zEhUKDXByb3BlcnR5X25hbWUY" +
+ "ASABKAkyWwoOY3NoYXJwX29wdGlvbnMSHS5nb29nbGUucHJvdG9idWYuRmll" +
+ "bGRPcHRpb25zGOgHIAEoCzIjLmdvb2dsZS5wcm90b2J1Zi5DU2hhcnBGaWVs" +
+ "ZE9wdGlvbnM="),
new pbd::FileDescriptor[] {
global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor,
});
#endregion
- #region Extensions
- public static readonly pb::GeneratedExtensionBase<string> CSharpNamespace =
- pb::GeneratedSingleExtension<string>.CreateInstance(Descriptor.Extensions[0]);
- public static readonly pb::GeneratedExtensionBase<string> CSharpUmbrellaClassname =
- pb::GeneratedSingleExtension<string>.CreateInstance(Descriptor.Extensions[1]);
- public static readonly pb::GeneratedExtensionBase<bool> CSharpMultipleFiles =
- pb::GeneratedSingleExtension<bool>.CreateInstance(Descriptor.Extensions[2]);
- public static readonly pb::GeneratedExtensionBase<bool> CSharpNestClasses =
- pb::GeneratedSingleExtension<bool>.CreateInstance(Descriptor.Extensions[3]);
- public static readonly pb::GeneratedExtensionBase<bool> CSharpPublicClasses =
- pb::GeneratedSingleExtension<bool>.CreateInstance(Descriptor.Extensions[4]);
- #endregion
-
#region Static variables
+ internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_CSharpFileOptions__Descriptor
+ = Descriptor.MessageTypes[0];
+ internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.CSharpFileOptions, global::Google.ProtocolBuffers.DescriptorProtos.CSharpFileOptions.Builder> internal__static_google_protobuf_CSharpFileOptions__FieldAccessorTable
+ = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.CSharpFileOptions, global::Google.ProtocolBuffers.DescriptorProtos.CSharpFileOptions.Builder>(internal__static_google_protobuf_CSharpFileOptions__Descriptor,
+ new string[] { "Namespace", "UmbrellaClassname", "PublicClasses", "MultipleFiles", "NestClasses", });
+ internal static readonly pbd::MessageDescriptor internal__static_google_protobuf_CSharpFieldOptions__Descriptor
+ = Descriptor.MessageTypes[1];
+ internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.CSharpFieldOptions, global::Google.ProtocolBuffers.DescriptorProtos.CSharpFieldOptions.Builder> internal__static_google_protobuf_CSharpFieldOptions__FieldAccessorTable
+ = new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.CSharpFieldOptions, global::Google.ProtocolBuffers.DescriptorProtos.CSharpFieldOptions.Builder>(internal__static_google_protobuf_CSharpFieldOptions__Descriptor,
+ new string[] { "PropertyName", });
#endregion
}
+ #region Messages
+ public sealed partial class CSharpFileOptions : pb::GeneratedMessage<CSharpFileOptions, CSharpFileOptions.Builder> {
+ private static readonly CSharpFileOptions defaultInstance = new Builder().BuildPartial();
+ public static CSharpFileOptions DefaultInstance {
+ get { return defaultInstance; }
+ }
+
+ public override CSharpFileOptions DefaultInstanceForType {
+ get { return defaultInstance; }
+ }
+
+ protected override CSharpFileOptions ThisMessage {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor {
+ get { return global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.internal__static_google_protobuf_CSharpFileOptions__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable<CSharpFileOptions, CSharpFileOptions.Builder> InternalFieldAccessors {
+ get { return global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.internal__static_google_protobuf_CSharpFileOptions__FieldAccessorTable; }
+ }
+
+ public static readonly pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.DescriptorProtos.CSharpFileOptions> CSharpOptions =
+ pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.DescriptorProtos.CSharpFileOptions>.CreateInstance(Descriptor.Extensions[0]);
+ private bool hasNamespace;
+ private string namespace_ = "";
+ public bool HasNamespace {
+ get { return hasNamespace; }
+ }
+ public string Namespace {
+ get { return namespace_; }
+ }
+
+ private bool hasUmbrellaClassname;
+ private string umbrellaClassname_ = "";
+ public bool HasUmbrellaClassname {
+ get { return hasUmbrellaClassname; }
+ }
+ public string UmbrellaClassname {
+ get { return umbrellaClassname_; }
+ }
+
+ private bool hasPublicClasses;
+ private bool publicClasses_ = false;
+ public bool HasPublicClasses {
+ get { return hasPublicClasses; }
+ }
+ public bool PublicClasses {
+ get { return publicClasses_; }
+ }
+
+ private bool hasMultipleFiles;
+ private bool multipleFiles_ = false;
+ public bool HasMultipleFiles {
+ get { return hasMultipleFiles; }
+ }
+ public bool MultipleFiles {
+ get { return multipleFiles_; }
+ }
+
+ private bool hasNestClasses;
+ private bool nestClasses_ = false;
+ public bool HasNestClasses {
+ get { return hasNestClasses; }
+ }
+ public bool NestClasses {
+ get { return nestClasses_; }
+ }
+
+ public static CSharpFileOptions ParseFrom(pb::ByteString data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static CSharpFileOptions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static CSharpFileOptions ParseFrom(byte[] data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static CSharpFileOptions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static CSharpFileOptions ParseFrom(global::System.IO.Stream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static CSharpFileOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static CSharpFileOptions ParseFrom(pb::CodedInputStream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static CSharpFileOptions ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(CSharpFileOptions prototype) {
+ return (Builder) new Builder().MergeFrom(prototype);
+ }
+
+ public sealed partial class Builder : pb::GeneratedBuilder<CSharpFileOptions, Builder> {
+ protected override Builder ThisBuilder {
+ get { return this; }
+ }
+ public Builder() {}
+
+ CSharpFileOptions result = new CSharpFileOptions();
+
+ protected override CSharpFileOptions MessageBeingBuilt {
+ get { return result; }
+ }
+
+ public override Builder Clear() {
+ result = new CSharpFileOptions();
+ return this;
+ }
+
+ public override Builder Clone() {
+ return new Builder().MergeFrom(result);
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType {
+ get { return CSharpFileOptions.Descriptor; }
+ }
+
+ public override CSharpFileOptions DefaultInstanceForType {
+ get { return CSharpFileOptions.DefaultInstance; }
+ }
+
+ public override CSharpFileOptions BuildPartial() {
+ CSharpFileOptions returnMe = result;
+ result = null;
+ return returnMe;
+ }
+
+
+ public bool HasNamespace {
+ get { return result.HasNamespace; }
+ }
+ public string Namespace {
+ get { return result.Namespace; }
+ set { SetNamespace(value); }
+ }
+ public Builder SetNamespace(string value) {
+ result.hasNamespace = true;
+ result.namespace_ = value;
+ return this;
+ }
+ public Builder ClearNamespace() {
+ result.hasNamespace = false;
+ result.namespace_ = "";
+ return this;
+ }
+
+ public bool HasUmbrellaClassname {
+ get { return result.HasUmbrellaClassname; }
+ }
+ public string UmbrellaClassname {
+ get { return result.UmbrellaClassname; }
+ set { SetUmbrellaClassname(value); }
+ }
+ public Builder SetUmbrellaClassname(string value) {
+ result.hasUmbrellaClassname = true;
+ result.umbrellaClassname_ = value;
+ return this;
+ }
+ public Builder ClearUmbrellaClassname() {
+ result.hasUmbrellaClassname = false;
+ result.umbrellaClassname_ = "";
+ return this;
+ }
+
+ public bool HasPublicClasses {
+ get { return result.HasPublicClasses; }
+ }
+ public bool PublicClasses {
+ get { return result.PublicClasses; }
+ set { SetPublicClasses(value); }
+ }
+ public Builder SetPublicClasses(bool value) {
+ result.hasPublicClasses = true;
+ result.publicClasses_ = value;
+ return this;
+ }
+ public Builder ClearPublicClasses() {
+ result.hasPublicClasses = false;
+ result.publicClasses_ = false;
+ return this;
+ }
+
+ public bool HasMultipleFiles {
+ get { return result.HasMultipleFiles; }
+ }
+ public bool MultipleFiles {
+ get { return result.MultipleFiles; }
+ set { SetMultipleFiles(value); }
+ }
+ public Builder SetMultipleFiles(bool value) {
+ result.hasMultipleFiles = true;
+ result.multipleFiles_ = value;
+ return this;
+ }
+ public Builder ClearMultipleFiles() {
+ result.hasMultipleFiles = false;
+ result.multipleFiles_ = false;
+ return this;
+ }
+
+ public bool HasNestClasses {
+ get { return result.HasNestClasses; }
+ }
+ public bool NestClasses {
+ get { return result.NestClasses; }
+ set { SetNestClasses(value); }
+ }
+ public Builder SetNestClasses(bool value) {
+ result.hasNestClasses = true;
+ result.nestClasses_ = value;
+ return this;
+ }
+ public Builder ClearNestClasses() {
+ result.hasNestClasses = false;
+ result.nestClasses_ = false;
+ return this;
+ }
+ }
+ }
+
+ public sealed partial class CSharpFieldOptions : pb::GeneratedMessage<CSharpFieldOptions, CSharpFieldOptions.Builder> {
+ private static readonly CSharpFieldOptions defaultInstance = new Builder().BuildPartial();
+ public static CSharpFieldOptions DefaultInstance {
+ get { return defaultInstance; }
+ }
+
+ public override CSharpFieldOptions DefaultInstanceForType {
+ get { return defaultInstance; }
+ }
+
+ protected override CSharpFieldOptions ThisMessage {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor {
+ get { return global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.internal__static_google_protobuf_CSharpFieldOptions__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable<CSharpFieldOptions, CSharpFieldOptions.Builder> InternalFieldAccessors {
+ get { return global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.internal__static_google_protobuf_CSharpFieldOptions__FieldAccessorTable; }
+ }
+
+ public static readonly pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.DescriptorProtos.CSharpFieldOptions> CSharpOptions =
+ pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.DescriptorProtos.CSharpFieldOptions>.CreateInstance(Descriptor.Extensions[0]);
+ private bool hasPropertyName;
+ private string propertyName_ = "";
+ public bool HasPropertyName {
+ get { return hasPropertyName; }
+ }
+ public string PropertyName {
+ get { return propertyName_; }
+ }
+
+ public static CSharpFieldOptions ParseFrom(pb::ByteString data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static CSharpFieldOptions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static CSharpFieldOptions ParseFrom(byte[] data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static CSharpFieldOptions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static CSharpFieldOptions ParseFrom(global::System.IO.Stream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static CSharpFieldOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static CSharpFieldOptions ParseFrom(pb::CodedInputStream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static CSharpFieldOptions ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(CSharpFieldOptions prototype) {
+ return (Builder) new Builder().MergeFrom(prototype);
+ }
+
+ public sealed partial class Builder : pb::GeneratedBuilder<CSharpFieldOptions, Builder> {
+ protected override Builder ThisBuilder {
+ get { return this; }
+ }
+ public Builder() {}
+
+ CSharpFieldOptions result = new CSharpFieldOptions();
+
+ protected override CSharpFieldOptions MessageBeingBuilt {
+ get { return result; }
+ }
+
+ public override Builder Clear() {
+ result = new CSharpFieldOptions();
+ return this;
+ }
+
+ public override Builder Clone() {
+ return new Builder().MergeFrom(result);
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType {
+ get { return CSharpFieldOptions.Descriptor; }
+ }
+
+ public override CSharpFieldOptions DefaultInstanceForType {
+ get { return CSharpFieldOptions.DefaultInstance; }
+ }
+
+ public override CSharpFieldOptions BuildPartial() {
+ CSharpFieldOptions returnMe = result;
+ result = null;
+ return returnMe;
+ }
+
+
+ public bool HasPropertyName {
+ get { return result.HasPropertyName; }
+ }
+ public string PropertyName {
+ get { return result.PropertyName; }
+ set { SetPropertyName(value); }
+ }
+ public Builder SetPropertyName(string value) {
+ result.hasPropertyName = true;
+ result.propertyName_ = value;
+ return this;
+ }
+ public Builder ClearPropertyName() {
+ result.hasPropertyName = false;
+ result.propertyName_ = "";
+ return this;
+ }
+ }
+ }
+
+ #endregion
+
}
diff --git a/src/ProtocolBuffers/Descriptors/FileDescriptor.cs b/src/ProtocolBuffers/Descriptors/FileDescriptor.cs
index ebb6b159..79e034a1 100644
--- a/src/ProtocolBuffers/Descriptors/FileDescriptor.cs
+++ b/src/ProtocolBuffers/Descriptors/FileDescriptor.cs
@@ -50,6 +50,8 @@ namespace Google.ProtocolBuffers.Descriptors {
private readonly IList<FieldDescriptor> extensions;
private readonly IList<FileDescriptor> dependencies;
private readonly DescriptorPool pool;
+ private CSharpFileOptions csharpFileOptions;
+ private readonly object optionsLock = new object();
private FileDescriptor(FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool) {
this.pool = pool;
@@ -71,6 +73,44 @@ namespace Google.ProtocolBuffers.Descriptors {
(field, index) => new FieldDescriptor(field, this, null, index, true));
}
+ private CSharpFileOptions BuildOrFakeCSharpOptions() {
+ // TODO(jonskeet): Check if we could use FileDescriptorProto.Descriptor.Name - interesting bootstrap issues
+ if (proto.Name == "google/protobuf/descriptor.proto") {
+ return new CSharpFileOptions.Builder {
+ Namespace = "Google.ProtocolBuffers.DescriptorProtos",
+ UmbrellaClassname = "DescriptorProtoFile", NestClasses = false, MultipleFiles = false, PublicClasses = true
+ }.Build();
+ }
+ if (proto.Name == "google/protobuf/csharp_options.proto") {
+ return new CSharpFileOptions.Builder {
+ Namespace = "Google.ProtocolBuffers.DescriptorProtos",
+ UmbrellaClassname = "CSharpOptions", NestClasses = false, MultipleFiles = false, PublicClasses = true
+ }.Build();
+ }
+ CSharpFileOptions.Builder builder = CSharpFileOptions.CreateBuilder();
+ if (proto.Options.HasExtension(CSharpFileOptions.CSharpOptions)) {
+ builder.MergeFrom(proto.Options.GetExtension(CSharpFileOptions.CSharpOptions));
+ }
+ if (!builder.HasNamespace) {
+ builder.Namespace = Package;
+ }
+ if (!builder.HasMultipleFiles) {
+ builder.MultipleFiles = false;
+ }
+ if (!builder.HasNestClasses) {
+ builder.NestClasses = false;
+ }
+ if (!builder.HasPublicClasses) {
+ builder.PublicClasses = true;
+ }
+ if (!builder.HasUmbrellaClassname) {
+ int lastSlash = Name.LastIndexOf('/');
+ string baseName = Name.Substring(lastSlash + 1);
+ builder.UmbrellaClassname = NameHelpers.UnderscoresToPascalCase(NameHelpers.StripProto(baseName));
+ }
+ return builder.Build();
+ }
+
/// <value>
/// The descriptor in its protocol message representation.
/// </value>
@@ -85,6 +125,22 @@ namespace Google.ProtocolBuffers.Descriptors {
get { return proto.Options; }
}
+ /// <summary>
+ /// Returns the C#-specific options for this file descriptor. This will always be
+ /// completely filled in.
+ /// FIXME: This isn't thread-safe. Can't do it at construction time due to bootstrapping issues.
+ /// </summary>
+ public CSharpFileOptions CSharpOptions {
+ get {
+ lock (optionsLock) {
+ if (csharpFileOptions == null) {
+ csharpFileOptions = BuildOrFakeCSharpOptions();
+ }
+ }
+ return csharpFileOptions;
+ }
+ }
+
/// <value>
/// The file name.
/// </value>
@@ -250,7 +306,7 @@ namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// This method is to be called by generated code only. It is equivalent
- /// to BuilderFrom except that the FileDescriptorProto is encoded in
+ /// to BuildFrom except that the FileDescriptorProto is encoded in
/// protocol buffer wire format.
/// </summary>
public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData,
diff --git a/src/ProtocolBuffers/NameHelpers.cs b/src/ProtocolBuffers/NameHelpers.cs
new file mode 100644
index 00000000..8b297f95
--- /dev/null
+++ b/src/ProtocolBuffers/NameHelpers.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Google.ProtocolBuffers {
+ /// <summary>
+ /// Helpers for converting names to pascal case etc.
+ /// </summary>
+ internal class NameHelpers {
+
+ internal static string UnderscoresToPascalCase(string input) {
+ return UnderscoresToPascalOrCamelCase(input, true);
+ }
+
+ internal static string UnderscoresToCamelCase(string input) {
+ return UnderscoresToPascalOrCamelCase(input, false);
+ }
+
+ /// <summary>
+ /// Converts a string to Pascal or Camel case. The first letter is capitalized or
+ /// lower-cased depending on <paramref name="pascal"/> is true.
+ /// After the first letter, any punctuation is removed but triggers capitalization
+ /// of the next letter. Digits are preserved but trigger capitalization of the next
+ /// letter.
+ /// All capitalisation is done in the invariant culture.
+ /// </summary>
+ private static string UnderscoresToPascalOrCamelCase(string input, bool pascal) {
+ StringBuilder result = new StringBuilder();
+ bool capitaliseNext = pascal;
+ for (int i = 0; i < input.Length; i++) {
+ char c = input[i];
+ if ('a' <= c && c <= 'z') {
+ if (capitaliseNext) {
+ result.Append(char.ToUpperInvariant(c));
+ } else {
+ result.Append(c);
+ }
+ capitaliseNext = false;
+ } else if ('A' <= c && c <= 'Z') {
+ if (i == 0 && !pascal) {
+ // Force first letter to lower-case unless explicitly told to
+ // capitalize it.
+ result.Append(char.ToLowerInvariant(c));
+ } else {
+ // Capital letters after the first are left as-is.
+ result.Append(c);
+ }
+ capitaliseNext = false;
+ } else if ('0' <= c && c <= '9') {
+ result.Append(c);
+ capitaliseNext = true;
+ } else {
+ capitaliseNext = true;
+ }
+ }
+ return result.ToString();
+ }
+
+ internal static string StripProto(string text) {
+ if (!StripSuffix(ref text, ".protodevel")) {
+ StripSuffix(ref text, ".proto");
+ }
+ return text;
+ }
+
+ /// <summary>
+ /// Attempts to strip a suffix from a string, returning whether
+ /// or not the suffix was actually present.
+ /// </summary>
+ internal static bool StripSuffix(ref string text, string suffix) {
+ if (text.EndsWith(suffix)) {
+ text = text.Substring(0, text.Length - suffix.Length);
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/ProtocolBuffers/ProtocolBuffers.csproj b/src/ProtocolBuffers/ProtocolBuffers.csproj
index 3f76aa7f..6a746cc9 100644
--- a/src/ProtocolBuffers/ProtocolBuffers.csproj
+++ b/src/ProtocolBuffers/ProtocolBuffers.csproj
@@ -97,6 +97,7 @@
<Compile Include="IService.cs" />
<Compile Include="MessageStreamIterator.cs" />
<Compile Include="MessageStreamWriter.cs" />
+ <Compile Include="NameHelpers.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RpcUtil.cs" />
<Compile Include="TextFormat.cs" />