• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015, Google Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation AN/or other materials provided with the
15  * distribution.
16  *     * Neither the name of Google Inc. nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 
34 #include <map>
35 #include <cctype>
36 #include <sstream>
37 
38 #include "src/compiler/go_generator.h"
39 
40 template <class T>
as_string(T x)41 grpc::string as_string(T x) {
42 	std::ostringstream out;
43 	out << x;
44 	return out.str();
45 }
46 
ClientOnlyStreaming(const grpc_generator::Method * method)47 inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
48   return method->ClientStreaming() && !method->ServerStreaming();
49 }
50 
ServerOnlyStreaming(const grpc_generator::Method * method)51 inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
52   return !method->ClientStreaming() && method->ServerStreaming();
53 }
54 
55 namespace grpc_go_generator {
56 
57 // Returns string with first letter to lowerCase
unexportName(grpc::string s)58 grpc::string unexportName(grpc::string s) {
59 	if (s.empty())
60 		return s;
61 	s[0] = static_cast<char>(std::tolower(s[0]));
62 	return s;
63 }
64 
65 // Returns string with first letter to uppercase
exportName(grpc::string s)66 grpc::string exportName(grpc::string s) {
67 	if (s.empty())
68 		return s;
69 	s[0] = static_cast<char>(std::toupper(s[0]));
70 	return s;
71 }
72 
GenerateError(grpc_generator::Printer * printer,std::map<grpc::string,grpc::string> vars,const bool multiple_return=true)73 void GenerateError(grpc_generator::Printer *printer,
74                    std::map<grpc::string, grpc::string> vars,
75                    const bool multiple_return = true) {
76   printer->Print(vars, "if $Error_Check$ {\n");
77   printer->Indent();
78   vars["Return"] = multiple_return ? "nil, err" : "err";
79   printer->Print(vars, "return $Return$\n");
80   printer->Outdent();
81   printer->Print("}\n");
82 }
83 
84 // Generates imports for the service
GenerateImports(grpc_generator::File * file,grpc_generator::Printer * printer,std::map<grpc::string,grpc::string> vars)85 void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printer,
86                      std::map<grpc::string, grpc::string> vars) {
87 	vars["filename"] = file->filename();
88 	printer->Print("//Generated by gRPC Go plugin\n");
89 	printer->Print("//If you make any local changes, they will be lost\n");
90 	printer->Print(vars, "//source: $filename$\n\n");
91 	printer->Print(vars, "package $Package$\n\n");
92 	printer->Print("import (\n");
93 	printer->Indent();
94 	printer->Print(vars, "$context$ \"context\"\n");
95   printer->Print("flatbuffers \"github.com/google/flatbuffers/go\"\n");
96 	printer->Print(vars, "$grpc$ \"google.golang.org/grpc\"\n");
97   printer->Print("\"google.golang.org/grpc/codes\"\n");
98   printer->Print("\"google.golang.org/grpc/status\"\n");
99 	printer->Outdent();
100 	printer->Print(")\n\n");
101 }
102 
103 // Generates Server method signature source
GenerateServerMethodSignature(const grpc_generator::Method * method,grpc_generator::Printer * printer,std::map<grpc::string,grpc::string> vars)104 void GenerateServerMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
105                                    std::map<grpc::string, grpc::string> vars) {
106   vars["Method"] = exportName(method->name());
107 	vars["Request"] = method->get_input_type_name();
108 	vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
109 	if (method->NoStreaming()) {
110 		printer->Print(vars, "$Method$($context$.Context, *$Request$) (*$Response$, error)$Ending$");
111 	} else if (ServerOnlyStreaming(method)) {
112 		printer->Print(vars, "$Method$(*$Request$, $Service$_$Method$Server) error$Ending$");
113 	} else {
114 		printer->Print(vars, "$Method$($Service$_$Method$Server) error$Ending$");
115 	}
116 }
117 
GenerateServerMethod(const grpc_generator::Method * method,grpc_generator::Printer * printer,std::map<grpc::string,grpc::string> vars)118 void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer,
119                           std::map<grpc::string, grpc::string> vars) {
120 	vars["Method"] = exportName(method->name());
121 	vars["Request"] = method->get_input_type_name();
122 	vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
123 	vars["FullMethodName"] = "/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"];
124 	vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
125 	if (method->NoStreaming()) {
126 		printer->Print(vars, "func $Handler$(srv interface{}, ctx $context$.Context,\n\tdec func(interface{}) error, interceptor $grpc$.UnaryServerInterceptor) (interface{}, error) {\n");
127 		printer->Indent();
128 		printer->Print(vars, "in := new($Request$)\n");
129     vars["Error_Check"] = "err := dec(in); err != nil";
130     GenerateError(printer, vars);
131     printer->Print("if interceptor == nil {\n");
132     printer->Indent();
133     printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, in)\n");
134     printer->Outdent();
135     printer->Print("}\n");
136 		printer->Print(vars, "info := &$grpc$.UnaryServerInfo{\n");
137 		printer->Indent();
138 		printer->Print("Server:     srv,\n");
139 		printer->Print(vars, "FullMethod: \"$FullMethodName$\",\n");
140 		printer->Outdent();
141 		printer->Print("}\n");
142     printer->Outdent();
143     printer->Print("\n");
144     printer->Indent();
145 		printer->Print(vars, "handler := func(ctx $context$.Context, req interface{}) (interface{}, error) {\n");
146 		printer->Indent();
147 		printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, req.(*$Request$))\n");
148 		printer->Outdent();
149 		printer->Print("}\n");
150 		printer->Print("return interceptor(ctx, in, info, handler)\n");
151 		printer->Outdent();
152 		printer->Print("}\n");
153 		return;
154 	}
155 	vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Server";
156 	printer->Print(vars, "func $Handler$(srv interface{}, stream $grpc$.ServerStream) error {\n");
157 	printer->Indent();
158 	if (ServerOnlyStreaming(method)) {
159 		printer->Print(vars, "m := new($Request$)\n");
160     vars["Error_Check"] = "err := stream.RecvMsg(m); err != nil";
161     GenerateError(printer, vars, false);
162 		printer->Print(vars, "return srv.($Service$Server).$Method$(m, &$StreamType${stream})\n");
163 	} else {
164 		printer->Print(vars, "return srv.($Service$Server).$Method$(&$StreamType${stream})\n");
165 	}
166 	printer->Outdent();
167 	printer->Print("}\n\n");
168 
169 	bool genSend = method->BidiStreaming() || ServerOnlyStreaming(method);
170 	bool genRecv = method->BidiStreaming() || ClientOnlyStreaming(method);
171 	bool genSendAndClose = ClientOnlyStreaming(method);
172 
173 	printer->Print(vars, "type $Service$_$Method$Server interface {\n");
174 	printer->Indent();
175 	if (genSend) {
176 		printer->Print(vars, "Send(*$Response$) error\n");
177 	}
178 	if (genRecv) {
179 		printer->Print(vars, "Recv() (*$Request$, error)\n");
180 	}
181 	if (genSendAndClose) {
182 		printer->Print(vars, "SendAndClose(*$Response$) error\n");
183 	}
184 	printer->Print(vars, "$grpc$.ServerStream\n");
185 	printer->Outdent();
186 	printer->Print("}\n\n");
187 
188 	printer->Print(vars, "type $StreamType$ struct {\n");
189 	printer->Indent();
190 	printer->Print(vars, "$grpc$.ServerStream\n");
191 	printer->Outdent();
192 	printer->Print("}\n\n");
193 
194 	if (genSend) {
195 		printer->Print(vars, "func (x *$StreamType$) Send(m *$Response$) error {\n");
196 		printer->Indent();
197 		printer->Print("return x.ServerStream.SendMsg(m)\n");
198 		printer->Outdent();
199 		printer->Print("}\n\n");
200 	}
201 	if (genRecv) {
202 		printer->Print(vars, "func (x *$StreamType$) Recv() (*$Request$, error) {\n");
203 		printer->Indent();
204 		printer->Print(vars, "m := new($Request$)\n");
205     vars["Error_Check"] = "err := x.ServerStream.RecvMsg(m); err != nil";
206     GenerateError(printer, vars);
207 		printer->Print("return m, nil\n");
208 		printer->Outdent();
209 		printer->Print("}\n\n");
210 	}
211 	if (genSendAndClose) {
212 		printer->Print(vars, "func (x *$StreamType$) SendAndClose(m *$Response$) error {\n");
213 		printer->Indent();
214 		printer->Print("return x.ServerStream.SendMsg(m)\n");
215 		printer->Outdent();
216 		printer->Print("}\n\n");
217 	}
218 
219 }
220 
221 // Generates Client method signature source
GenerateClientMethodSignature(const grpc_generator::Method * method,grpc_generator::Printer * printer,std::map<grpc::string,grpc::string> vars)222 void GenerateClientMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
223                                    std::map<grpc::string, grpc::string> vars) {
224 	vars["Method"] = exportName(method->name());
225 	vars["Request"] = ", in *" + ((vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"]);
226 	if (ClientOnlyStreaming(method) || method->BidiStreaming()) {
227 		vars["Request"] = "";
228 	}
229 	vars["Response"] = "*" + method->get_output_type_name();
230 	if (ClientOnlyStreaming(method) || method->BidiStreaming() || ServerOnlyStreaming(method)) {
231 		vars["Response"] = vars["Service"] + "_" + vars["Method"] + "Client" ;
232 	}
233 	printer->Print(vars, "$Method$(ctx $context$.Context$Request$,\n\topts ...$grpc$.CallOption) ($Response$, error)$Ending$");
234 }
235 
236 // Generates Client method source
GenerateClientMethod(const grpc_generator::Method * method,grpc_generator::Printer * printer,std::map<grpc::string,grpc::string> vars)237 void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer,
238                           std::map<grpc::string, grpc::string> vars) {
239 	printer->Print(vars, "func (c *$ServiceUnexported$Client) ");
240   vars["Ending"] = " {\n";
241 	GenerateClientMethodSignature(method, printer, vars);
242 	printer->Indent();
243 	vars["Method"] = exportName(method->name());
244 	vars["Request"] = (vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"];
245 	vars["Response"] = method->get_output_type_name();
246 	vars["FullMethodName"] = "/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"];
247 	if (method->NoStreaming()) {
248 		printer->Print(vars, "out := new($Response$)\n");
249 		printer->Print(vars, "err := c.cc.Invoke(ctx, \"$FullMethodName$\", in, out, opts...)\n");
250     vars["Error_Check"] = "err != nil";
251     GenerateError(printer, vars);
252 		printer->Print("return out, nil\n");
253 		printer->Outdent();
254 		printer->Print("}\n\n");
255 		return;
256 	}
257 	vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Client";
258 	printer->Print(vars, "stream, err := c.cc.NewStream(ctx, &$MethodDesc$, \"$FullMethodName$\", opts...)\n");
259   vars["Error_Check"] = "err != nil";
260   GenerateError(printer, vars);
261 
262 	printer->Print(vars, "x := &$StreamType${stream}\n");
263 	if (ServerOnlyStreaming(method)) {
264     vars["Error_Check"] = "err := x.ClientStream.SendMsg(in); err != nil";
265     GenerateError(printer, vars);
266     vars["Error_Check"] = "err := x.ClientStream.CloseSend(); err != nil";
267     GenerateError(printer, vars);
268 	}
269 	printer->Print("return x, nil\n");
270 	printer->Outdent();
271 	printer->Print("}\n\n");
272 
273 	bool genSend = method->BidiStreaming() || ClientOnlyStreaming(method);
274 	bool genRecv = method->BidiStreaming() || ServerOnlyStreaming(method);
275 	bool genCloseAndRecv = ClientOnlyStreaming(method);
276 
277 	//Stream interface
278 	printer->Print(vars, "type $Service$_$Method$Client interface {\n");
279 	printer->Indent();
280 	if (genSend) {
281 		printer->Print(vars, "Send(*$Request$) error\n");
282 	}
283 	if (genRecv) {
284 		printer->Print(vars, "Recv() (*$Response$, error)\n");
285 	}
286 	if (genCloseAndRecv) {
287 		printer->Print(vars, "CloseAndRecv() (*$Response$, error)\n");
288 	}
289 	printer->Print(vars, "$grpc$.ClientStream\n");
290 	printer->Outdent();
291 	printer->Print("}\n\n");
292 
293 	//Stream Client
294 	printer->Print(vars, "type $StreamType$ struct {\n");
295 	printer->Indent();
296 	printer->Print(vars, "$grpc$.ClientStream\n");
297 	printer->Outdent();
298 	printer->Print("}\n\n");
299 
300 	if (genSend) {
301 		printer->Print(vars, "func (x *$StreamType$) Send(m *$Request$) error {\n");
302 		printer->Indent();
303 		printer->Print("return x.ClientStream.SendMsg(m)\n");
304 		printer->Outdent();
305 		printer->Print("}\n\n");
306 	}
307 
308 	if (genRecv) {
309 		printer->Print(vars, "func (x *$StreamType$) Recv() (*$Response$, error) {\n");
310 		printer->Indent();
311 		printer->Print(vars, "m := new($Response$)\n");
312     vars["Error_Check"] = "err := x.ClientStream.RecvMsg(m); err != nil";
313     GenerateError(printer, vars);
314 		printer->Print("return m, nil\n");
315 		printer->Outdent();
316 		printer->Print("}\n\n");
317 	}
318 
319 	if (genCloseAndRecv) {
320 		printer->Print(vars, "func (x *$StreamType$) CloseAndRecv() (*$Response$, error) {\n");
321 		printer->Indent();
322     vars["Error_Check"] = "err := x.ClientStream.CloseSend(); err != nil";
323     GenerateError(printer, vars);
324 		printer->Print(vars, "m := new($Response$)\n");
325     vars["Error_Check"] = "err := x.ClientStream.RecvMsg(m); err != nil";
326     GenerateError(printer, vars);
327 		printer->Print("return m, nil\n");
328 		printer->Outdent();
329 		printer->Print("}\n\n");
330 	}
331 }
332 
333 // Generates client API for the service
GenerateService(const grpc_generator::Service * service,grpc_generator::Printer * printer,std::map<grpc::string,grpc::string> vars)334 void GenerateService(const grpc_generator::Service *service, grpc_generator::Printer* printer,
335                      std::map<grpc::string, grpc::string> vars) {
336 	vars["Service"] = exportName(service->name());
337 	// Client Interface
338 	printer->Print(vars, "// Client API for $Service$ service\n");
339 	printer->Print(vars, "type $Service$Client interface {\n");
340 	printer->Indent();
341   vars["Ending"] = "\n";
342 	for (int i = 0; i < service->method_count(); i++) {
343 		GenerateClientMethodSignature(service->method(i).get(), printer, vars);
344 	}
345 	printer->Outdent();
346 	printer->Print("}\n\n");
347 
348 	// Client structure
349 	vars["ServiceUnexported"] = unexportName(vars["Service"]);
350 	printer->Print(vars, "type $ServiceUnexported$Client struct {\n");
351 	printer->Indent();
352 	printer->Print(vars, "cc $grpc$.ClientConnInterface\n");
353 	printer->Outdent();
354 	printer->Print("}\n\n");
355 
356 	// NewClient
357 	printer->Print(vars, "func New$Service$Client(cc $grpc$.ClientConnInterface) $Service$Client {\n");
358 	printer->Indent();
359 	printer->Print(vars, "return &$ServiceUnexported$Client{cc}");
360 	printer->Outdent();
361 	printer->Print("\n}\n\n");
362 
363 	int unary_methods = 0, streaming_methods = 0;
364 	vars["ServiceDesc"] = "_" + vars["Service"] + "_serviceDesc";
365 	for (int i = 0; i < service->method_count(); i++) {
366 		auto method = service->method(i);
367 		if (method->NoStreaming()) {
368 			vars["MethodDesc"] = vars["ServiceDesc"] + ".Method[" + as_string(unary_methods) + "]";
369 			unary_methods++;
370 		} else {
371 			vars["MethodDesc"] = vars["ServiceDesc"] + ".Streams[" + as_string(streaming_methods) + "]";
372 			streaming_methods++;
373 		}
374 		GenerateClientMethod(method.get(), printer, vars);
375 	}
376 
377 	//Server Interface
378 	printer->Print(vars, "// Server API for $Service$ service\n");
379 	printer->Print(vars, "type $Service$Server interface {\n");
380 	printer->Indent();
381   vars["Ending"] = "\n";
382 	for (int i = 0; i < service->method_count(); i++) {
383 		GenerateServerMethodSignature(service->method(i).get(), printer, vars);
384 	}
385   printer->Print(vars, "mustEmbedUnimplemented$Service$Server()\n");
386 	printer->Outdent();
387 	printer->Print("}\n\n");
388 
389   printer->Print(vars, "type Unimplemented$Service$Server struct {\n");
390   printer->Print("}\n\n");
391 
392   vars["Ending"] = " {\n";
393   for (int i = 0; i < service->method_count(); i++) {
394     auto method = service->method(i);
395     vars["Method"] = exportName(method->name());
396     vars["Nil"] = method->NoStreaming() ? "nil, " : "";
397     printer->Print(vars, "func (Unimplemented$Service$Server) ");
398     GenerateServerMethodSignature(method.get(), printer, vars);
399     printer->Indent();
400     printer->Print(vars, "return $Nil$status.Errorf(codes.Unimplemented, \"method $Method$ not implemented\")\n");
401     printer->Outdent();
402     printer->Print("}\n");
403     printer->Print("\n");
404   }
405 
406   printer->Print(vars, "func (Unimplemented$Service$Server) mustEmbedUnimplemented$Service$Server() {}");
407   printer->Print("\n\n");
408 
409   printer->Print(vars, "type Unsafe$Service$Server interface {\n");
410   printer->Indent();
411   printer->Print(vars, "mustEmbedUnimplemented$Service$Server()\n");
412   printer->Outdent();
413   printer->Print("}\n\n");
414 	// Server registration.
415 	printer->Print(vars, "func Register$Service$Server(s $grpc$.ServiceRegistrar, srv $Service$Server) {\n");
416 	printer->Indent();
417 	printer->Print(vars, "s.RegisterService(&$ServiceDesc$, srv)\n");
418 	printer->Outdent();
419 	printer->Print("}\n\n");
420 
421 	for (int i = 0; i < service->method_count(); i++) {
422 		GenerateServerMethod(service->method(i).get(), printer, vars);
423 	}
424 
425 
426 	//Service Descriptor
427 	printer->Print(vars, "var $ServiceDesc$ = $grpc$.ServiceDesc{\n");
428 	printer->Indent();
429 	printer->Print(vars, "ServiceName: \"$ServicePrefix$$Service$\",\n");
430 	printer->Print(vars, "HandlerType: (*$Service$Server)(nil),\n");
431 	printer->Print(vars, "Methods: []$grpc$.MethodDesc{\n");
432 	printer->Indent();
433 	for (int i = 0; i < service->method_count(); i++) {
434 		auto method = service->method(i);
435 		vars["Method"] = exportName(method->name());
436 		vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
437 		if (method->NoStreaming()) {
438 			printer->Print("{\n");
439 			printer->Indent();
440 			printer->Print(vars, "MethodName: \"$Method$\",\n");
441 			printer->Print(vars, "Handler:    $Handler$,\n");
442 			printer->Outdent();
443 			printer->Print("},\n");
444 		}
445 	}
446 	printer->Outdent();
447 	printer->Print("},\n");
448 	printer->Print(vars, "Streams: []$grpc$.StreamDesc{\n");
449 	printer->Indent();
450 	for (int i = 0; i < service->method_count(); i++) {
451 		auto method = service->method(i);
452 		vars["Method"] = exportName(method->name());
453 		vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
454 		if (!method->NoStreaming()) {
455 			printer->Print("{\n");
456 			printer->Indent();
457 			printer->Print(vars, "StreamName:    \"$Method$\",\n");
458 			printer->Print(vars, "Handler:       $Handler$,\n");
459 			if (ClientOnlyStreaming(method.get())) {
460 				printer->Print("ClientStreams: true,\n");
461 			} else if (ServerOnlyStreaming(method.get())) {
462 				printer->Print("ServerStreams: true,\n");
463 			} else {
464 				printer->Print("ServerStreams: true,\n");
465 				printer->Print("ClientStreams: true,\n");
466 			}
467 			printer->Outdent();
468 			printer->Print("},\n");
469 		}
470 	}
471 	printer->Outdent();
472 	printer->Print("},\n");
473 	printer->Outdent();
474 	printer->Print("}\n");
475 
476 }
477 
478 
479 // Returns source for the service
GenerateServiceSource(grpc_generator::File * file,const grpc_generator::Service * service,grpc_go_generator::Parameters * parameters)480 grpc::string GenerateServiceSource(grpc_generator::File *file,
481                                    const grpc_generator::Service *service,
482                                    grpc_go_generator::Parameters *parameters) {
483 	grpc::string out;
484 	auto p = file->CreatePrinter(&out, '\t');
485   p->SetIndentationSize(1);
486 	auto printer = p.get();
487 	std::map<grpc::string, grpc::string> vars;
488 	vars["Package"] = parameters->package_name;
489 	vars["ServicePrefix"] = parameters->service_prefix;
490   if (!parameters->service_prefix.empty())
491     vars["ServicePrefix"].append(".");
492 	vars["grpc"] = "grpc";
493 	vars["context"] = "context";
494 	GenerateImports(file, printer, vars);
495 	if (parameters->custom_method_io_type != "") {
496 		vars["CustomMethodIO"] = parameters->custom_method_io_type;
497 	}
498 	GenerateService(service, printer, vars);
499 	return out;
500 }
501 }// Namespace grpc_go_generator
502