diff --git a/protos/google/protobuf/csharp_options.proto b/protos/google/protobuf/csharp_options.proto index b58a549172..8a27046e59 100644 --- a/protos/google/protobuf/csharp_options.proto +++ b/protos/google/protobuf/csharp_options.proto @@ -5,12 +5,36 @@ import "google/protobuf/descriptor.proto"; package google.protobuf; message CSharpFileOptions { + + // Namespace for generated classes; defaults to the package. optional string namespace = 1; + + // Name of the "umbrella" class used for metadata about all + // the messages within this file. Default is based on the name + // of the file. optional string umbrella_classname = 2; + + // Whether classes should be public (true) or internal (false) optional bool public_classes = 3 [default = true]; + + // Whether to generate a single file for everything within the + // .proto file (false), or one file per message (true). + // This option is not currently honored; please log a feature + // request if you really want it. optional bool multiple_files = 4; + + // Whether to nest messages within a single umbrella class (true) + // or create the umbrella class as a peer, with messages as + // top-level classes in the namespace (false) optional bool nest_classes = 5; + + // Generate appropriate support for Code Contracts + // (Ongoing; support should improve over time) optional bool code_contracts = 6; + + // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" + // would generate files within [output directory]/Foo/Bar + optional bool expand_namespace_directories = 7; } extend FileOptions { diff --git a/src/ProtoGen/Generator.cs b/src/ProtoGen/Generator.cs index 9c0771ee8e..7e48ad672f 100644 --- a/src/ProtoGen/Generator.cs +++ b/src/ProtoGen/Generator.cs @@ -82,12 +82,29 @@ namespace Google.ProtocolBuffers.ProtoGen { /// private void Generate(FileDescriptor descriptor) { UmbrellaClassGenerator ucg = new UmbrellaClassGenerator(descriptor); - using (TextWriter textWriter = File.CreateText(Path.Combine(options.OutputDirectory, descriptor.CSharpOptions.UmbrellaClassname + ".cs"))) { - TextGenerator writer = new TextGenerator(textWriter); + using (TextWriter textWriter = File.CreateText(GetOutputFile(descriptor))) { + TextGenerator writer = new TextGenerator(textWriter); ucg.Generate(writer); } } + private string GetOutputFile(FileDescriptor descriptor) { + CSharpFileOptions fileOptions = descriptor.CSharpOptions; + string filename = descriptor.CSharpOptions.UmbrellaClassname + ".cs"; + string outputDirectory = options.OutputDirectory; + if (fileOptions.ExpandNamespaceDirectories) { + string package = fileOptions.Namespace; + if (!string.IsNullOrEmpty(package)) { + string[] bits = package.Split('.'); + foreach (string bit in bits) { + outputDirectory = Path.Combine(outputDirectory, bit); + } + Directory.CreateDirectory(outputDirectory); + } + } + return Path.Combine(outputDirectory, filename); + } + /// /// 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. diff --git a/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs b/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs index 9ab99dfe32..b589a60ce7 100644 --- a/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs +++ b/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs @@ -37,22 +37,22 @@ namespace Google.ProtocolBuffers.DescriptorProtos { byte[] descriptorData = global::System.Convert.FromBase64String( "CiRnb29nbGUvcHJvdG9idWYvY3NoYXJwX29wdGlvbnMucHJvdG8SD2dvb2ds" + "ZS5wcm90b2J1ZhogZ29vZ2xlL3Byb3RvYnVmL2Rlc2NyaXB0b3IucHJvdG8i" + - "pgEKEUNTaGFycEZpbGVPcHRpb25zEhEKCW5hbWVzcGFjZRgBIAEoCRIaChJ1" + + "zAEKEUNTaGFycEZpbGVPcHRpb25zEhEKCW5hbWVzcGFjZRgBIAEoCRIaChJ1" + "bWJyZWxsYV9jbGFzc25hbWUYAiABKAkSHAoOcHVibGljX2NsYXNzZXMYAyAB" + "KAg6BHRydWUSFgoObXVsdGlwbGVfZmlsZXMYBCABKAgSFAoMbmVzdF9jbGFz" + - "c2VzGAUgASgIEhYKDmNvZGVfY29udHJhY3RzGAYgASgIIisKEkNTaGFycEZp" + - "ZWxkT3B0aW9ucxIVCg1wcm9wZXJ0eV9uYW1lGAEgASgJOl4KE2NzaGFycF9m" + - "aWxlX29wdGlvbnMSHC5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMY6Acg" + - "ASgLMiIuZ29vZ2xlLnByb3RvYnVmLkNTaGFycEZpbGVPcHRpb25zOmEKFGNz" + - "aGFycF9maWVsZF9vcHRpb25zEh0uZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0" + - "aW9ucxjoByABKAsyIy5nb29nbGUucHJvdG9idWYuQ1NoYXJwRmllbGRPcHRp" + - "b25z"); + "c2VzGAUgASgIEhYKDmNvZGVfY29udHJhY3RzGAYgASgIEiQKHGV4cGFuZF9u" + + "YW1lc3BhY2VfZGlyZWN0b3JpZXMYByABKAgiKwoSQ1NoYXJwRmllbGRPcHRp" + + "b25zEhUKDXByb3BlcnR5X25hbWUYASABKAk6XgoTY3NoYXJwX2ZpbGVfb3B0" + + "aW9ucxIcLmdvb2dsZS5wcm90b2J1Zi5GaWxlT3B0aW9ucxjoByABKAsyIi5n" + + "b29nbGUucHJvdG9idWYuQ1NoYXJwRmlsZU9wdGlvbnM6YQoUY3NoYXJwX2Zp" + + "ZWxkX29wdGlvbnMSHS5nb29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zGOgH" + + "IAEoCzIjLmdvb2dsZS5wcm90b2J1Zi5DU2hhcnBGaWVsZE9wdGlvbnM="); pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) { descriptor = root; internal__static_google_protobuf_CSharpFileOptions__Descriptor = Descriptor.MessageTypes[0]; internal__static_google_protobuf_CSharpFileOptions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_google_protobuf_CSharpFileOptions__Descriptor, - new string[] { "Namespace", "UmbrellaClassname", "PublicClasses", "MultipleFiles", "NestClasses", "CodeContracts", }); + new string[] { "Namespace", "UmbrellaClassname", "PublicClasses", "MultipleFiles", "NestClasses", "CodeContracts", "ExpandNamespaceDirectories", }); internal__static_google_protobuf_CSharpFieldOptions__Descriptor = Descriptor.MessageTypes[1]; internal__static_google_protobuf_CSharpFieldOptions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_google_protobuf_CSharpFieldOptions__Descriptor, @@ -152,6 +152,16 @@ namespace Google.ProtocolBuffers.DescriptorProtos { get { return codeContracts_; } } + public const int ExpandNamespaceDirectoriesFieldNumber = 7; + private bool hasExpandNamespaceDirectories; + private bool expandNamespaceDirectories_ = false; + public bool HasExpandNamespaceDirectories { + get { return hasExpandNamespaceDirectories; } + } + public bool ExpandNamespaceDirectories { + get { return expandNamespaceDirectories_; } + } + public override bool IsInitialized { get { return true; @@ -177,6 +187,9 @@ namespace Google.ProtocolBuffers.DescriptorProtos { if (HasCodeContracts) { output.WriteBool(6, CodeContracts); } + if (HasExpandNamespaceDirectories) { + output.WriteBool(7, ExpandNamespaceDirectories); + } UnknownFields.WriteTo(output); } @@ -205,6 +218,9 @@ namespace Google.ProtocolBuffers.DescriptorProtos { if (HasCodeContracts) { size += pb::CodedOutputStream.ComputeBoolSize(6, CodeContracts); } + if (HasExpandNamespaceDirectories) { + size += pb::CodedOutputStream.ComputeBoolSize(7, ExpandNamespaceDirectories); + } size += UnknownFields.SerializedSize; memoizedSerializedSize = size; return size; @@ -315,6 +331,9 @@ namespace Google.ProtocolBuffers.DescriptorProtos { if (other.HasCodeContracts) { CodeContracts = other.CodeContracts; } + if (other.HasExpandNamespaceDirectories) { + ExpandNamespaceDirectories = other.ExpandNamespaceDirectories; + } this.MergeUnknownFields(other.UnknownFields); return this; } @@ -371,6 +390,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { CodeContracts = input.ReadBool(); break; } + case 56: { + ExpandNamespaceDirectories = input.ReadBool(); + break; + } } } } @@ -485,6 +508,24 @@ namespace Google.ProtocolBuffers.DescriptorProtos { result.codeContracts_ = false; return this; } + + public bool HasExpandNamespaceDirectories { + get { return result.HasExpandNamespaceDirectories; } + } + public bool ExpandNamespaceDirectories { + get { return result.ExpandNamespaceDirectories; } + set { SetExpandNamespaceDirectories(value); } + } + public Builder SetExpandNamespaceDirectories(bool value) { + result.hasExpandNamespaceDirectories = true; + result.expandNamespaceDirectories_ = value; + return this; + } + public Builder ClearExpandNamespaceDirectories() { + result.hasExpandNamespaceDirectories = false; + result.expandNamespaceDirectories_ = false; + return this; + } } static CSharpFileOptions() { object.ReferenceEquals(global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor, null);