blob: 698b70165d7fcdf0507e39f76e7a0b44b2d63350 [file] [log] [blame]
csharptest68d831e2011-05-03 13:47:34 -05001#region Copyright notice and license
csharptest71f662c2011-05-20 15:15:34 -05002
csharptest68d831e2011-05-03 13:47:34 -05003// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc. All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13// * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15// * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19// * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
csharptest71f662c2011-05-20 15:15:34 -050034
csharptest68d831e2011-05-03 13:47:34 -050035#endregion
36
37using System;
38using System.Collections.Generic;
39using Google.ProtocolBuffers.DescriptorProtos;
40using Google.ProtocolBuffers.Descriptors;
41
csharptest71f662c2011-05-20 15:15:34 -050042namespace Google.ProtocolBuffers.ProtoGen
43{
44 internal class ServiceGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator
45 {
46 private readonly CSharpServiceType svcType;
47 private ISourceGenerator _generator;
csharptest68d831e2011-05-03 13:47:34 -050048
csharptest71f662c2011-05-20 15:15:34 -050049 internal ServiceGenerator(ServiceDescriptor descriptor)
50 : base(descriptor)
csharptest68d831e2011-05-03 13:47:34 -050051 {
csharptest71f662c2011-05-20 15:15:34 -050052 svcType = descriptor.File.CSharpOptions.ServiceGeneratorType;
53 switch (svcType)
54 {
55 case CSharpServiceType.NONE:
56 _generator = new NoServicesGenerator(descriptor);
57 break;
58 case CSharpServiceType.GENERIC:
59 _generator = new GenericServiceGenerator(descriptor);
60 break;
61 case CSharpServiceType.INTERFACE:
62 _generator = new ServiceInterfaceGenerator(descriptor);
63 break;
64 case CSharpServiceType.IRPCDISPATCH:
65 _generator = new RpcServiceGenerator(descriptor);
66 break;
67 default:
68 throw new ApplicationException("Unknown ServiceGeneratorType = " + svcType.ToString());
69 }
csharptest68d831e2011-05-03 13:47:34 -050070 }
71
csharptest71f662c2011-05-20 15:15:34 -050072 public void Generate(TextGenerator writer)
73 {
74 _generator.Generate(writer);
75 }
76
77 private class NoServicesGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator
78 {
79 public NoServicesGenerator(ServiceDescriptor descriptor)
80 : base(descriptor)
81 {
82 }
83
84 public virtual void Generate(TextGenerator writer)
85 {
86 writer.WriteLine("/*");
87 writer.WriteLine("* Service generation is now disabled by default, use the following option to enable:");
88 writer.WriteLine("* option (google.protobuf.csharp_file_options).service_generator_type = GENERIC;");
89 writer.WriteLine("*/");
90 }
91 }
92
93 private class ServiceInterfaceGenerator : SourceGeneratorBase<ServiceDescriptor>, ISourceGenerator
94 {
95 public ServiceInterfaceGenerator(ServiceDescriptor descriptor)
96 : base(descriptor)
97 {
98 }
99
100 public virtual void Generate(TextGenerator writer)
101 {
102 CSharpServiceOptions options = Descriptor.Options.GetExtension(CSharpOptions.CsharpServiceOptions);
103 if (options != null && options.HasInterfaceId)
104 {
105 writer.WriteLine("[global::System.Runtime.InteropServices.GuidAttribute(\"{0}\")]",
106 new Guid(options.InterfaceId));
107 }
108 writer.WriteLine("{0} partial interface I{1} {{", ClassAccessLevel, Descriptor.Name);
109 writer.Indent();
110
111 foreach (MethodDescriptor method in Descriptor.Methods)
112 {
113 CSharpMethodOptions mth = method.Options.GetExtension(CSharpOptions.CsharpMethodOptions);
114 if (mth.HasDispatchId)
115 {
116 writer.WriteLine("[global::System.Runtime.InteropServices.DispId({0})]", mth.DispatchId);
117 }
118 writer.WriteLine("{0} {1}({2} {3});", GetClassName(method.OutputType),
119 NameHelpers.UnderscoresToPascalCase(method.Name), GetClassName(method.InputType),
120 NameHelpers.UnderscoresToCamelCase(method.InputType.Name));
121 }
122
123 writer.Outdent();
124 writer.WriteLine("}");
125 }
126 }
127
128 private class RpcServiceGenerator : ServiceInterfaceGenerator
129 {
130 public RpcServiceGenerator(ServiceDescriptor descriptor)
131 : base(descriptor)
132 {
133 }
134
135 public override void Generate(TextGenerator writer)
136 {
137 base.Generate(writer);
138
139 writer.WriteLine();
140
141 // CLIENT Proxy
142 {
143 if (Descriptor.File.CSharpOptions.ClsCompliance)
144 writer.WriteLine("[global::System.CLSCompliant(false)]");
145 writer.WriteLine("{0} partial class {1} : I{1}, pb::IRpcDispatch, global::System.IDisposable {{",
146 ClassAccessLevel, Descriptor.Name);
147 writer.Indent();
148 writer.WriteLine("private readonly bool dispose;");
149 writer.WriteLine("private readonly pb::IRpcDispatch dispatch;");
150
151 writer.WriteLine("public {0}(pb::IRpcDispatch dispatch) : this(dispatch, true) {{", Descriptor.Name);
152 writer.WriteLine("}");
153 writer.WriteLine("public {0}(pb::IRpcDispatch dispatch, bool dispose) {{", Descriptor.Name);
154 writer.WriteLine(
155 " if (null == (this.dispatch = dispatch)) throw new global::System.ArgumentNullException();");
156 writer.WriteLine(" this.dispose = dispose && dispatch is global::System.IDisposable;");
157 writer.WriteLine("}");
158 writer.WriteLine();
159
160 writer.WriteLine("public void Dispose() {");
161 writer.WriteLine(" if (dispose) ((global::System.IDisposable)dispatch).Dispose();");
162 writer.WriteLine("}");
163 writer.WriteLine();
164 writer.WriteLine(
165 "TMessage pb::IRpcDispatch.CallMethod<TMessage, TBuilder>(string method, pb::IMessageLite request, pb::IBuilderLite<TMessage, TBuilder> response) {");
166 writer.WriteLine(" return dispatch.CallMethod(method, request, response);");
167 writer.WriteLine("}");
168 writer.WriteLine();
169
170 foreach (MethodDescriptor method in Descriptor.Methods)
171 {
172 writer.WriteLine("public {0} {1}({2} {3}) {{", GetClassName(method.OutputType),
173 NameHelpers.UnderscoresToPascalCase(method.Name),
174 GetClassName(method.InputType),
175 NameHelpers.UnderscoresToCamelCase(method.InputType.Name));
176 writer.WriteLine(" return dispatch.CallMethod(\"{0}\", {1}, {2}.CreateBuilder());",
177 method.Name,
178 NameHelpers.UnderscoresToCamelCase(method.InputType.Name),
179 GetClassName(method.OutputType)
180 );
181 writer.WriteLine("}");
182 writer.WriteLine();
183 }
184 }
185 // SERVER - DISPATCH
186 {
187 if (Descriptor.File.CSharpOptions.ClsCompliance)
188 writer.WriteLine("[global::System.CLSCompliant(false)]");
189 writer.WriteLine("public partial class Dispatch : pb::IRpcDispatch, global::System.IDisposable {");
190 writer.Indent();
191 writer.WriteLine("private readonly bool dispose;");
192 writer.WriteLine("private readonly I{0} implementation;", Descriptor.Name);
193
194 writer.WriteLine("public Dispatch(I{0} implementation) : this(implementation, true) {{",
195 Descriptor.Name);
196 writer.WriteLine("}");
197 writer.WriteLine("public Dispatch(I{0} implementation, bool dispose) {{", Descriptor.Name);
198 writer.WriteLine(
199 " if (null == (this.implementation = implementation)) throw new global::System.ArgumentNullException();");
200 writer.WriteLine(" this.dispose = dispose && implementation is global::System.IDisposable;");
201 writer.WriteLine("}");
202 writer.WriteLine();
203
204 writer.WriteLine("public void Dispose() {");
205 writer.WriteLine(" if (dispose) ((global::System.IDisposable)implementation).Dispose();");
206 writer.WriteLine("}");
207 writer.WriteLine();
208
209 writer.WriteLine(
210 "public TMessage CallMethod<TMessage, TBuilder>(string methodName, pb::IMessageLite request, pb::IBuilderLite<TMessage, TBuilder> response)");
211 writer.WriteLine(" where TMessage : IMessageLite<TMessage, TBuilder>");
212 writer.WriteLine(" where TBuilder : IBuilderLite<TMessage, TBuilder> {");
213 writer.Indent();
214 writer.WriteLine("switch(methodName) {");
215 writer.Indent();
216
217 foreach (MethodDescriptor method in Descriptor.Methods)
218 {
219 writer.WriteLine(
220 "case \"{0}\": return response.MergeFrom(implementation.{1}(({2})request)).Build();",
221 method.Name, NameHelpers.UnderscoresToPascalCase(method.Name),
222 GetClassName(method.InputType));
223 }
224 writer.WriteLine(
225 "default: throw new global::System.MissingMethodException(typeof(ISearchService).FullName, methodName);");
226 writer.Outdent();
227 writer.WriteLine("}"); //end switch
228 writer.Outdent();
229 writer.WriteLine("}"); //end invoke
230 writer.Outdent();
231 writer.WriteLine("}"); //end server
232 }
233 // SERVER - STUB
234 {
235 if (Descriptor.File.CSharpOptions.ClsCompliance)
236 writer.WriteLine("[global::System.CLSCompliant(false)]");
237 writer.WriteLine(
238 "public partial class ServerStub : pb::IRpcServerStub, global::System.IDisposable {");
239 writer.Indent();
240 writer.WriteLine("private readonly bool dispose;");
241 writer.WriteLine("private readonly pb::IRpcDispatch implementation;", Descriptor.Name);
242
243 writer.WriteLine("public ServerStub(I{0} implementation) : this(implementation, true) {{",
244 Descriptor.Name);
245 writer.WriteLine("}");
246 writer.WriteLine(
247 "public ServerStub(I{0} implementation, bool dispose) : this(new Dispatch(implementation, dispose), dispose) {{",
248 Descriptor.Name);
249 writer.WriteLine("}");
250
251 writer.WriteLine("public ServerStub(pb::IRpcDispatch implementation) : this(implementation, true) {");
252 writer.WriteLine("}");
253 writer.WriteLine("public ServerStub(pb::IRpcDispatch implementation, bool dispose) {");
254 writer.WriteLine(
255 " if (null == (this.implementation = implementation)) throw new global::System.ArgumentNullException();");
256 writer.WriteLine(" this.dispose = dispose && implementation is global::System.IDisposable;");
257 writer.WriteLine("}");
258 writer.WriteLine();
259
260 writer.WriteLine("public void Dispose() {");
261 writer.WriteLine(" if (dispose) ((global::System.IDisposable)implementation).Dispose();");
262 writer.WriteLine("}");
263 writer.WriteLine();
264
265 writer.WriteLine(
266 "public pb::IMessageLite CallMethod(string methodName, pb::CodedInputStream input, pb::ExtensionRegistry registry) {{",
267 Descriptor.Name);
268 writer.Indent();
269 writer.WriteLine("switch(methodName) {");
270 writer.Indent();
271
272 foreach (MethodDescriptor method in Descriptor.Methods)
273 {
274 writer.WriteLine(
275 "case \"{0}\": return implementation.CallMethod(methodName, {1}.ParseFrom(input, registry), {2}.CreateBuilder());",
276 method.Name, GetClassName(method.InputType), GetClassName(method.OutputType));
277 }
278 writer.WriteLine(
279 "default: throw new global::System.MissingMethodException(typeof(ISearchService).FullName, methodName);");
280 writer.Outdent();
281 writer.WriteLine("}"); //end switch
282 writer.Outdent();
283 writer.WriteLine("}"); //end invoke
284 writer.Outdent();
285 writer.WriteLine("}"); //end server
286 }
287
288 writer.Outdent();
289 writer.WriteLine("}");
290 }
291 }
csharptest68d831e2011-05-03 13:47:34 -0500292 }
csharptest71f662c2011-05-20 15:15:34 -0500293}