private void GenerateCallMethod(TextGenerator writer) { writer.WriteLine(); writer.WriteLine("public void CallMethod("); writer.WriteLine(" pbd::MethodDescriptor method,"); writer.WriteLine(" pb::IRpcController controller,"); writer.WriteLine(" pb::IMessage request,"); writer.WriteLine(" global::System.Action<pb::IMessage> done) {"); writer.Indent(); writer.WriteLine("if (method.Service != Descriptor) {"); writer.WriteLine(" throw new global::System.ArgumentException("); writer.WriteLine(" \"Service.CallMethod() given method descriptor for wrong service type.\");"); writer.WriteLine("}"); writer.WriteLine("switch(method.Index) {"); writer.Indent(); foreach (MethodDescriptor method in Descriptor.Methods) { writer.WriteLine("case {0}:", method.Index); writer.WriteLine(" this.{0}(controller, ({1}) request,", NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType)); writer.WriteLine(" pb::RpcUtil.SpecializeCallback<{0}>(", GetClassName(method.OutputType)); writer.WriteLine(" done));"); writer.WriteLine(" return;"); } writer.WriteLine("default:"); writer.WriteLine(" throw new global::System.InvalidOperationException(\"Can't get here.\");"); writer.Outdent(); writer.WriteLine("}"); writer.Outdent(); writer.WriteLine("}"); writer.WriteLine(); }
private CSharpFieldOptions BuildOrFakeCSharpOptions() { // TODO(jonskeet): Check if we could use FileDescriptorProto.Descriptor.Name - interesting bootstrap issues if (File.Proto.Name == "google/protobuf/csharp_options.proto") { if (Name == "csharp_field_options") { return(new CSharpFieldOptions.Builder { PropertyName = "CSharpFieldOptions" }.Build()); } if (Name == "csharp_file_options") { return(new CSharpFieldOptions.Builder { PropertyName = "CSharpFileOptions" }.Build()); } } CSharpFieldOptions.Builder builder = CSharpFieldOptions.CreateBuilder(); if (Proto.Options.HasExtension(DescriptorProtos.CSharpOptions.CSharpFieldOptions)) { builder.MergeFrom(Proto.Options.GetExtension(DescriptorProtos.CSharpOptions.CSharpFieldOptions)); } if (!builder.HasPropertyName) { string fieldName = FieldType == FieldType.Group ? MessageType.Name : Name; string propertyName = NameHelpers.UnderscoresToPascalCase(fieldName); if (propertyName == ContainingType.Name) { propertyName += "_"; } builder.PropertyName = propertyName; } return(builder.Build()); }
public void Generate(TextGenerator writer) { //writer.WriteLine("[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); WriteGeneratedCodeAttributes(writer); writer.WriteLine("{0} abstract class {1} : pb::IService {{", ClassAccessLevel, Descriptor.Name); writer.Indent(); foreach (MethodDescriptor method in Descriptor.Methods) { writer.WriteLine("{0} abstract void {1}(", ClassAccessLevel, NameHelpers.UnderscoresToPascalCase(method.Name)); writer.WriteLine(" pb::IRpcController controller,"); 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.GetQualifiedUmbrellaClassName(Descriptor.File.CSharpOptions), Descriptor.Index); writer.WriteLine("}"); writer.WriteLine("public pbd::ServiceDescriptor DescriptorForType {"); writer.WriteLine(" get { return Descriptor; }"); writer.WriteLine("}"); GenerateCallMethod(writer); GenerateGetPrototype(RequestOrResponse.Request, writer); GenerateGetPrototype(RequestOrResponse.Response, writer); GenerateStub(writer); writer.Outdent(); writer.WriteLine("}"); }
public virtual void Generate(TextGenerator writer) { CSharpServiceOptions options = Descriptor.Options.GetExtension(CSharpOptions.CsharpServiceOptions); if (options != null && options.HasInterfaceId) { writer.WriteLine("[global::System.Runtime.InteropServices.GuidAttribute(\"{0}\")]", new Guid(options.InterfaceId)); } WriteGeneratedCodeAttributes(writer); writer.WriteLine("{0} partial interface I{1} {{", ClassAccessLevel, Descriptor.Name); writer.Indent(); foreach (MethodDescriptor method in Descriptor.Methods) { CSharpMethodOptions mth = method.Options.GetExtension(CSharpOptions.CsharpMethodOptions); if (mth.HasDispatchId) { writer.WriteLine("[global::System.Runtime.InteropServices.DispId({0})]", mth.DispatchId); } writer.WriteLine("{0} {1}({2} {3});", GetClassName(method.OutputType), NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType), NameHelpers.UnderscoresToCamelCase(method.InputType.Name)); } writer.Outdent(); writer.WriteLine("}"); }
private void GenerateIsInitialized(TextGenerator writer) { writer.WriteLine("#if UNITY_EDITOR\n [pb.FieldNumber] \n #endif//"); writer.WriteLine("public override bool IsInitialized {"); writer.Indent(); writer.WriteLine("get {"); writer.Indent(); // Check that all required fields in this message are set. // TODO(kenton): We can optimize this when we switch to putting all the // "has" fields into a single bitfield. foreach (FieldDescriptor field in Descriptor.Fields) { if (field.IsRequired) { writer.WriteLine("if (!has{0}) return false;", field.CSharpOptions.PropertyName); } } // Now check that all embedded messages are initialized. foreach (FieldDescriptor field in Descriptor.Fields) { if (field.FieldType != FieldType.Message || !HasRequiredFields(field.MessageType, new Dictionary <MessageDescriptor, object>())) { continue; } string propertyName = NameHelpers.UnderscoresToPascalCase(GetFieldName(field)); if (field.IsRepeated) { 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) { writer.WriteLine("if (Has{0}) {{", propertyName); writer.WriteLine(" if (!{0}.IsInitialized) return false;", propertyName); writer.WriteLine("}"); } else { writer.WriteLine("if (!{0}.IsInitialized) return false;", propertyName); } } if (Descriptor.Proto.ExtensionRangeCount > 0) { writer.WriteLine("if (!ExtensionsAreInitialized) return false;"); } writer.WriteLine("return true;"); writer.Outdent(); writer.WriteLine("}"); writer.Outdent(); writer.WriteLine("}"); writer.WriteLine(); }
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(DescriptorProtos.CSharpOptions.CSharpFileOptions)) { builder.MergeFrom(proto.Options.GetExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions)); } 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()); }
private void GenerateStub(TextGenerator writer) { writer.WriteLine("public static Stub CreateStub(pb::IRpcChannel channel) {"); writer.WriteLine(" return new Stub(channel);"); writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine("[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); writer.WriteLine("[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]"); writer.WriteLine("[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"{0}\", \"{1}\")]", GetType().Assembly.GetName().Name, GetType().Assembly.GetName().Version); writer.WriteLine("{0} class Stub : {1} {{", ClassAccessLevel, GetClassName(Descriptor)); writer.Indent(); writer.WriteLine("internal Stub(pb::IRpcChannel channel) {"); writer.WriteLine(" this.channel = channel;"); writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine("private readonly pb::IRpcChannel channel;"); writer.WriteLine(); writer.WriteLine("public pb::IRpcChannel Channel {"); writer.WriteLine(" get { return channel; }"); writer.WriteLine("}"); foreach (MethodDescriptor method in Descriptor.Methods) { writer.WriteLine(); writer.WriteLine("{0} override void {1}(", ClassAccessLevel, NameHelpers.UnderscoresToPascalCase(method.Name)); writer.WriteLine(" pb::IRpcController controller,"); 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,", GetClassName(method.OutputType)); writer.WriteLine(" pb::RpcUtil.GeneralizeCallback<{0}, {0}.Builder>(done, {0}.DefaultInstance));", GetClassName(method.OutputType)); writer.Outdent(); writer.WriteLine("}"); } writer.Outdent(); writer.WriteLine("}"); }
private void GenerateStub(TextGenerator writer) { writer.WriteLine("public static Stub CreateStub(pb::IRpcChannel channel) {"); writer.WriteLine(" return new Stub(channel);"); writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine("{0} class Stub : {1} {{", ClassAccessLevel, GetClassName(Descriptor)); writer.Indent(); writer.WriteLine("internal Stub(pb::IRpcChannel channel) {"); writer.WriteLine(" this.channel = channel;"); writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine("private readonly pb::IRpcChannel channel;"); writer.WriteLine(); writer.WriteLine("public pb::IRpcChannel Channel {"); writer.WriteLine(" get { return channel; }"); writer.WriteLine("}"); foreach (MethodDescriptor method in Descriptor.Methods) { writer.WriteLine(); writer.WriteLine("public override void {0}(", NameHelpers.UnderscoresToPascalCase(method.Name)); writer.WriteLine(" pb::IRpcController controller,"); 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,", GetClassName(method.OutputType)); writer.WriteLine(" pb::RpcUtil.GeneralizeCallback<{0}, {0}.Builder>(done, {0}.DefaultInstance));", GetClassName(method.OutputType)); writer.Outdent(); writer.WriteLine("}"); } writer.Outdent(); writer.WriteLine("}"); }
public override void Generate(TextGenerator writer) { base.Generate(writer); writer.WriteLine(); // CLIENT Proxy { if (Descriptor.File.CSharpOptions.ClsCompliance) { writer.WriteLine("[global::System.CLSCompliant(false)]"); } writer.WriteLine("[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); WriteGeneratedCodeAttributes(writer); writer.WriteLine("{0} partial class {1} : I{1}, pb::IRpcDispatch, global::System.IDisposable {{", ClassAccessLevel, Descriptor.Name); writer.Indent(); writer.WriteLine("private readonly bool dispose;"); writer.WriteLine("private readonly pb::IRpcDispatch dispatch;"); writer.WriteLine("public {0}(pb::IRpcDispatch dispatch) : this(dispatch, true) {{", Descriptor.Name); writer.WriteLine("}"); writer.WriteLine("public {0}(pb::IRpcDispatch dispatch, bool dispose) {{", Descriptor.Name); writer.WriteLine(" pb::ThrowHelper.ThrowIfNull(this.dispatch = dispatch, \"dispatch\");"); writer.WriteLine(" this.dispose = dispose && dispatch is global::System.IDisposable;"); writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine("public void Dispose() {"); writer.WriteLine(" if (dispose) ((global::System.IDisposable)dispatch).Dispose();"); writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine( "TMessage pb::IRpcDispatch.CallMethod<TMessage, TBuilder>(string method, pb::IMessageLite request, pb::IBuilderLite<TMessage, TBuilder> response) {"); writer.WriteLine(" return dispatch.CallMethod(method, request, response);"); writer.WriteLine("}"); writer.WriteLine(); foreach (MethodDescriptor method in Descriptor.Methods) { writer.WriteLine("public {0} {1}({2} {3}) {{", GetClassName(method.OutputType), NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType), NameHelpers.UnderscoresToCamelCase(method.InputType.Name)); writer.WriteLine(" return dispatch.CallMethod(\"{0}\", {1}, {2}.CreateBuilder());", method.Name, NameHelpers.UnderscoresToCamelCase(method.InputType.Name), GetClassName(method.OutputType) ); writer.WriteLine("}"); writer.WriteLine(); } } // SERVER - DISPATCH { if (Descriptor.File.CSharpOptions.ClsCompliance) { writer.WriteLine("[global::System.CLSCompliant(false)]"); } writer.WriteLine("[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); WriteGeneratedCodeAttributes(writer); writer.WriteLine("public partial class Dispatch : pb::IRpcDispatch, global::System.IDisposable {"); writer.Indent(); writer.WriteLine("private readonly bool dispose;"); writer.WriteLine("private readonly I{0} implementation;", Descriptor.Name); writer.WriteLine("public Dispatch(I{0} implementation) : this(implementation, true) {{", Descriptor.Name); writer.WriteLine("}"); writer.WriteLine("public Dispatch(I{0} implementation, bool dispose) {{", Descriptor.Name); writer.WriteLine(" pb::ThrowHelper.ThrowIfNull(this.implementation = implementation, \"implementation\");"); writer.WriteLine(" this.dispose = dispose && implementation is global::System.IDisposable;"); writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine("public void Dispose() {"); writer.WriteLine(" if (dispose) ((global::System.IDisposable)implementation).Dispose();"); writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine( "public TMessage CallMethod<TMessage, TBuilder>(string methodName, pb::IMessageLite request, pb::IBuilderLite<TMessage, TBuilder> response)"); writer.WriteLine(" where TMessage : pb::IMessageLite<TMessage, TBuilder>"); writer.WriteLine(" where TBuilder : pb::IBuilderLite<TMessage, TBuilder> {"); writer.Indent(); writer.WriteLine("switch(methodName) {"); writer.Indent(); foreach (MethodDescriptor method in Descriptor.Methods) { writer.WriteLine( "case \"{0}\": return response.MergeFrom(implementation.{1}(({2})request)).Build();", method.Name, NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType)); } writer.WriteLine("default: throw pb::ThrowHelper.CreateMissingMethod(typeof(I{0}), methodName);", Descriptor.Name); writer.Outdent(); writer.WriteLine("}"); //end switch writer.Outdent(); writer.WriteLine("}"); //end invoke writer.Outdent(); writer.WriteLine("}"); //end server } // SERVER - STUB { if (Descriptor.File.CSharpOptions.ClsCompliance) { writer.WriteLine("[global::System.CLSCompliant(false)]"); } writer.WriteLine("[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); WriteGeneratedCodeAttributes(writer); writer.WriteLine( "public partial class ServerStub : pb::IRpcServerStub, global::System.IDisposable {"); writer.Indent(); writer.WriteLine("private readonly bool dispose;"); writer.WriteLine("private readonly pb::IRpcDispatch implementation;", Descriptor.Name); writer.WriteLine("public ServerStub(I{0} implementation) : this(implementation, true) {{", Descriptor.Name); writer.WriteLine("}"); writer.WriteLine( "public ServerStub(I{0} implementation, bool dispose) : this(new Dispatch(implementation, dispose), dispose) {{", Descriptor.Name); writer.WriteLine("}"); writer.WriteLine("public ServerStub(pb::IRpcDispatch implementation) : this(implementation, true) {"); writer.WriteLine("}"); writer.WriteLine("public ServerStub(pb::IRpcDispatch implementation, bool dispose) {"); writer.WriteLine(" pb::ThrowHelper.ThrowIfNull(this.implementation = implementation, \"implementation\");"); writer.WriteLine(" this.dispose = dispose && implementation is global::System.IDisposable;"); writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine("public void Dispose() {"); writer.WriteLine(" if (dispose) ((global::System.IDisposable)implementation).Dispose();"); writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine( "public pb::IMessageLite CallMethod(string methodName, pb::ICodedInputStream input, pb::ExtensionRegistry registry) {{", Descriptor.Name); writer.Indent(); writer.WriteLine("switch(methodName) {"); writer.Indent(); foreach (MethodDescriptor method in Descriptor.Methods) { writer.WriteLine( "case \"{0}\": return implementation.CallMethod(methodName, {1}.ParseFrom(input, registry), {2}.CreateBuilder());", method.Name, GetClassName(method.InputType), GetClassName(method.OutputType)); } writer.WriteLine("default: throw pb::ThrowHelper.CreateMissingMethod(typeof(I{0}), methodName);", Descriptor.Name); writer.Outdent(); writer.WriteLine("}"); //end switch writer.Outdent(); writer.WriteLine("}"); //end invoke writer.Outdent(); writer.WriteLine("}"); //end server } writer.Outdent(); writer.WriteLine("}"); }
private CSharpFileOptions BuildOrFakeWithDefaultOptions(CSharpFileOptions defaultOptions) { // Fix for being able to relocate these files to any directory structure if (proto.Package == "google.protobuf") { string filename = Path.GetFileName(proto.Name); // TODO(jonskeet): Check if we could use FileDescriptorProto.Descriptor.Name - interesting bootstrap issues) if (filename == "descriptor.proto") { return(new CSharpFileOptions.Builder { Namespace = "Google.ProtocolBuffers.DescriptorProtos", UmbrellaClassname = "DescriptorProtoFile", NestClasses = false, MultipleFiles = false, PublicClasses = true, OutputDirectory = defaultOptions.OutputDirectory, IgnoreGoogleProtobuf = defaultOptions.IgnoreGoogleProtobuf }.Build()); } if (filename == "csharp_options.proto") { return(new CSharpFileOptions.Builder { Namespace = "Google.ProtocolBuffers.DescriptorProtos", UmbrellaClassname = "CSharpOptions", NestClasses = false, MultipleFiles = false, PublicClasses = true, OutputDirectory = defaultOptions.OutputDirectory, IgnoreGoogleProtobuf = defaultOptions.IgnoreGoogleProtobuf }.Build()); } } CSharpFileOptions.Builder builder = defaultOptions.ToBuilder(); if (proto.Options.HasExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions)) { builder.MergeFrom(proto.Options.GetExtension(DescriptorProtos.CSharpOptions.CSharpFileOptions)); } if (!builder.HasNamespace) { builder.Namespace = Package; } if (!builder.HasUmbrellaClassname) { int lastSlash = Name.LastIndexOf('/'); string baseName = Name.Substring(lastSlash + 1); builder.UmbrellaClassname = NameHelpers.UnderscoresToPascalCase(NameHelpers.StripProto(baseName)); } // Auto-fix for name collision by placing umbrella class into a new namespace. This // still won't fix the collisions with nesting enabled; however, you have to turn that on explicitly anyway. if (!builder.NestClasses && !builder.HasUmbrellaNamespace) { bool collision = false; foreach (IDescriptor d in MessageTypes) { collision |= d.Name == builder.UmbrellaClassname; } foreach (IDescriptor d in Services) { collision |= d.Name == builder.UmbrellaClassname; } foreach (IDescriptor d in EnumTypes) { collision |= d.Name == builder.UmbrellaClassname; } if (collision) { builder.UmbrellaNamespace = "Proto"; } } return(builder.Build()); }