예제 #1
0
 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();
 }
예제 #2
0
 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());
 }
예제 #3
0
        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("}");
        }
예제 #4
0
            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("}");
            }
예제 #5
0
        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();
        }
예제 #6
0
 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());
 }
예제 #7
0
        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("}");
        }
예제 #8
0
        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("}");
        }
예제 #9
0
            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());
        }