• 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 and/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 
36 #include "src/compiler/cpp_generator.h"
37 #include "flatbuffers/util.h"
38 
39 #include <sstream>
40 
41 namespace grpc_cpp_generator {
42 namespace {
43 
message_header_ext()44 grpc::string message_header_ext() { return "_generated.h"; }
service_header_ext()45 grpc::string service_header_ext() { return ".grpc.fb.h"; }
46 
47 template <class T>
as_string(T x)48 grpc::string as_string(T x) {
49   std::ostringstream out;
50   out << x;
51   return out.str();
52 }
53 
ClientOnlyStreaming(const grpc_generator::Method * method)54 inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
55   return method->ClientStreaming() && !method->ServerStreaming();
56 }
57 
ServerOnlyStreaming(const grpc_generator::Method * method)58 inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
59   return !method->ClientStreaming() && method->ServerStreaming();
60 }
61 
FilenameIdentifier(const grpc::string & filename)62 grpc::string FilenameIdentifier(const grpc::string &filename) {
63   grpc::string result;
64   for (unsigned i = 0; i < filename.size(); i++) {
65     char c = filename[i];
66     if (isalnum(c)) {
67       result.push_back(c);
68     } else {
69       static char hex[] = "0123456789abcdef";
70       result.push_back('_');
71       result.push_back(hex[(c >> 4) & 0xf]);
72       result.push_back(hex[c & 0xf]);
73     }
74   }
75   return result;
76 }
77 }  // namespace
78 
79 template <class T, size_t N>
array_end(T (& array)[N])80 T *array_end(T (&array)[N]) {
81   return array + N;
82 }
83 
PrintIncludes(grpc_generator::Printer * printer,const std::vector<grpc::string> & headers,const Parameters & params)84 void PrintIncludes(grpc_generator::Printer *printer,
85                    const std::vector<grpc::string> &headers,
86                    const Parameters &params) {
87   std::map<grpc::string, grpc::string> vars;
88 
89   vars["l"] = params.use_system_headers ? '<' : '"';
90   vars["r"] = params.use_system_headers ? '>' : '"';
91 
92   auto &s = params.grpc_search_path;
93   if (!s.empty()) {
94     vars["l"] += s;
95     if (s[s.size() - 1] != '/') {
96       vars["l"] += '/';
97     }
98   }
99 
100   for (auto i = headers.begin(); i != headers.end(); i++) {
101     vars["h"] = *i;
102     printer->Print(vars, "#include $l$$h$$r$\n");
103   }
104 }
105 
GetHeaderPrologue(grpc_generator::File * file,const Parameters &)106 grpc::string GetHeaderPrologue(grpc_generator::File *file,
107                                const Parameters & /*params*/) {
108   grpc::string output;
109   {
110     // Scope the output stream so it closes and finalizes output to the string.
111     auto printer = file->CreatePrinter(&output);
112     std::map<grpc::string, grpc::string> vars;
113 
114     vars["filename"] = file->filename();
115     vars["filename_identifier"] = FilenameIdentifier(file->filename());
116     vars["filename_base"] = file->filename_without_ext();
117     vars["message_header_ext"] = message_header_ext();
118 
119     printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
120     printer->Print(vars,
121                    "// If you make any local change, they will be lost.\n");
122     printer->Print(vars, "// source: $filename$\n");
123     grpc::string leading_comments = file->GetLeadingComments("//");
124     if (!leading_comments.empty()) {
125       printer->Print(vars, "// Original file comments:\n");
126       printer->Print(leading_comments.c_str());
127     }
128     printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
129     printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
130     printer->Print(vars, "\n");
131     printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
132     printer->Print(vars, file->additional_headers().c_str());
133     printer->Print(vars, "\n");
134   }
135   return output;
136 }
137 
GetHeaderIncludes(grpc_generator::File * file,const Parameters & params)138 grpc::string GetHeaderIncludes(grpc_generator::File *file,
139                                const Parameters &params) {
140   grpc::string output;
141   {
142     // Scope the output stream so it closes and finalizes output to the string.
143     auto printer = file->CreatePrinter(&output);
144     std::map<grpc::string, grpc::string> vars;
145 
146     static const char *headers_strs[] = {
147         "grpc++/impl/codegen/async_stream.h",
148         "grpc++/impl/codegen/async_unary_call.h",
149         "grpc++/impl/codegen/method_handler_impl.h",
150         "grpc++/impl/codegen/proto_utils.h",
151         "grpc++/impl/codegen/rpc_method.h",
152         "grpc++/impl/codegen/service_type.h",
153         "grpc++/impl/codegen/status.h",
154         "grpc++/impl/codegen/stub_options.h",
155         "grpc++/impl/codegen/sync_stream.h"};
156     std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
157     PrintIncludes(printer.get(), headers, params);
158     printer->Print(vars, "\n");
159     printer->Print(vars, "namespace grpc {\n");
160     printer->Print(vars, "class CompletionQueue;\n");
161     printer->Print(vars, "class Channel;\n");
162     printer->Print(vars, "class ServerCompletionQueue;\n");
163     printer->Print(vars, "class ServerContext;\n");
164     printer->Print(vars, "}  // namespace grpc\n\n");
165 
166     if (!file->package().empty()) {
167       std::vector<grpc::string> parts = file->package_parts();
168 
169       for (auto part = parts.begin(); part != parts.end(); part++) {
170         vars["part"] = *part;
171         printer->Print(vars, "namespace $part$ {\n");
172       }
173       printer->Print(vars, "\n");
174     }
175   }
176   return output;
177 }
178 
PrintHeaderClientMethodInterfaces(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars,bool is_public)179 void PrintHeaderClientMethodInterfaces(
180     grpc_generator::Printer *printer, const grpc_generator::Method *method,
181     std::map<grpc::string, grpc::string> *vars, bool is_public) {
182   (*vars)["Method"] = method->name();
183   (*vars)["Request"] = method->input_type_name();
184   (*vars)["Response"] = method->output_type_name();
185 
186   struct {
187     grpc::string prefix;
188     grpc::string method_params;  // extra arguments to method
189     grpc::string raw_args;       // extra arguments to raw version of method
190   } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
191                         {"PrepareAsync", "", ""}};
192 
193   if (is_public) {
194     if (method->NoStreaming()) {
195       printer->Print(
196           *vars,
197           "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
198           "const $Request$& request, $Response$* response) = 0;\n");
199       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
200         auto& async_prefix = async_prefixes[i];
201         (*vars)["AsyncPrefix"] = async_prefix.prefix;
202         printer->Print(
203             *vars,
204             "std::unique_ptr< "
205             "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
206             "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
207             "const $Request$& request, "
208             "::grpc::CompletionQueue* cq) {\n");
209         printer->Indent();
210         printer->Print(
211             *vars,
212             "return std::unique_ptr< "
213             "::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
214             "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
215         printer->Outdent();
216         printer->Print("}\n");
217       }
218     } else if (ClientOnlyStreaming(method)) {
219       printer->Print(
220           *vars,
221           "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
222           " $Method$("
223           "::grpc::ClientContext* context, $Response$* response) {\n");
224       printer->Indent();
225       printer->Print(
226           *vars,
227           "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
228           "($Method$Raw(context, response));\n");
229       printer->Outdent();
230       printer->Print("}\n");
231       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
232         auto& async_prefix = async_prefixes[i];
233         (*vars)["AsyncPrefix"] = async_prefix.prefix;
234         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
235         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
236         printer->Print(
237             *vars,
238             "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
239             " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
240             "$Response$* "
241             "response, "
242             "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
243         printer->Indent();
244         printer->Print(*vars,
245                        "return std::unique_ptr< "
246                        "::grpc::ClientAsyncWriterInterface< $Request$>>("
247                        "$AsyncPrefix$$Method$Raw(context, response, "
248                        "cq$AsyncRawArgs$));\n");
249         printer->Outdent();
250         printer->Print("}\n");
251       }
252     } else if (ServerOnlyStreaming(method)) {
253       printer->Print(
254           *vars,
255           "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
256           " $Method$(::grpc::ClientContext* context, const $Request$& request)"
257           " {\n");
258       printer->Indent();
259       printer->Print(
260           *vars,
261           "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
262           "($Method$Raw(context, request));\n");
263       printer->Outdent();
264       printer->Print("}\n");
265       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
266         auto& async_prefix = async_prefixes[i];
267         (*vars)["AsyncPrefix"] = async_prefix.prefix;
268         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
269         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
270         printer->Print(
271             *vars,
272             "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
273             "$AsyncPrefix$$Method$("
274             "::grpc::ClientContext* context, const $Request$& request, "
275             "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
276         printer->Indent();
277         printer->Print(
278             *vars,
279             "return std::unique_ptr< "
280             "::grpc::ClientAsyncReaderInterface< $Response$>>("
281             "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
282         printer->Outdent();
283         printer->Print("}\n");
284       }
285     } else if (method->BidiStreaming()) {
286       printer->Print(*vars,
287                      "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
288                      "$Request$, $Response$>> "
289                      "$Method$(::grpc::ClientContext* context) {\n");
290       printer->Indent();
291       printer->Print(
292           *vars,
293           "return std::unique_ptr< "
294           "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
295           "$Method$Raw(context));\n");
296       printer->Outdent();
297       printer->Print("}\n");
298       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
299         auto& async_prefix = async_prefixes[i];
300         (*vars)["AsyncPrefix"] = async_prefix.prefix;
301         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
302         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
303         printer->Print(
304             *vars,
305             "std::unique_ptr< "
306             "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
307             "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
308             "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
309         printer->Indent();
310         printer->Print(
311             *vars,
312             "return std::unique_ptr< "
313             "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
314             "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
315         printer->Outdent();
316         printer->Print("}\n");
317       }
318     }
319   } else {
320     if (method->NoStreaming()) {
321       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
322         auto& async_prefix = async_prefixes[i];
323         (*vars)["AsyncPrefix"] = async_prefix.prefix;
324         printer->Print(
325             *vars,
326             "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
327             "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
328             "const $Request$& request, "
329             "::grpc::CompletionQueue* cq) = 0;\n");
330       }
331     } else if (ClientOnlyStreaming(method)) {
332       printer->Print(
333           *vars,
334           "virtual ::grpc::ClientWriterInterface< $Request$>*"
335           " $Method$Raw("
336           "::grpc::ClientContext* context, $Response$* response) = 0;\n");
337       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
338         auto& async_prefix = async_prefixes[i];
339         (*vars)["AsyncPrefix"] = async_prefix.prefix;
340         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
341         printer->Print(
342             *vars,
343             "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
344             " $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
345             "$Response$* response, "
346             "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
347       }
348     } else if (ServerOnlyStreaming(method)) {
349       printer->Print(
350           *vars,
351           "virtual ::grpc::ClientReaderInterface< $Response$>* "
352           "$Method$Raw("
353           "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
354       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
355         auto& async_prefix = async_prefixes[i];
356         (*vars)["AsyncPrefix"] = async_prefix.prefix;
357         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
358         printer->Print(
359             *vars,
360             "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
361             "$AsyncPrefix$$Method$Raw("
362             "::grpc::ClientContext* context, const $Request$& request, "
363             "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
364       }
365     } else if (method->BidiStreaming()) {
366       printer->Print(*vars,
367                      "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
368                      "$Response$>* "
369                      "$Method$Raw(::grpc::ClientContext* context) = 0;\n");
370       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
371         auto& async_prefix = async_prefixes[i];
372         (*vars)["AsyncPrefix"] = async_prefix.prefix;
373         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
374         printer->Print(
375             *vars,
376             "virtual ::grpc::ClientAsyncReaderWriterInterface< "
377             "$Request$, $Response$>* "
378             "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
379             "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
380       }
381     }
382   }
383 }
384 
PrintHeaderClientMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars,bool is_public)385 void PrintHeaderClientMethod(grpc_generator::Printer *printer,
386                              const grpc_generator::Method *method,
387                              std::map<grpc::string, grpc::string> *vars,
388                              bool is_public) {
389   (*vars)["Method"] = method->name();
390   (*vars)["Request"] = method->input_type_name();
391   (*vars)["Response"] = method->output_type_name();
392   struct {
393     grpc::string prefix;
394     grpc::string method_params;  // extra arguments to method
395     grpc::string raw_args;       // extra arguments to raw version of method
396   } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
397                         {"PrepareAsync", "", ""}};
398 
399   if (is_public) {
400     if (method->NoStreaming()) {
401       printer->Print(
402           *vars,
403           "::grpc::Status $Method$(::grpc::ClientContext* context, "
404           "const $Request$& request, $Response$* response) override;\n");
405     for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
406         auto& async_prefix = async_prefixes[i];
407         (*vars)["AsyncPrefix"] = async_prefix.prefix;
408         printer->Print(
409             *vars,
410             "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
411             "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
412             "const $Request$& request, "
413             "::grpc::CompletionQueue* cq) {\n");
414         printer->Indent();
415         printer->Print(*vars,
416                        "return std::unique_ptr< "
417                        "::grpc::ClientAsyncResponseReader< $Response$>>("
418                        "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
419         printer->Outdent();
420         printer->Print("}\n");
421       }
422     } else if (ClientOnlyStreaming(method)) {
423       printer->Print(
424           *vars,
425           "std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
426           " $Method$("
427           "::grpc::ClientContext* context, $Response$* response) {\n");
428       printer->Indent();
429       printer->Print(*vars,
430                      "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
431                      "($Method$Raw(context, response));\n");
432       printer->Outdent();
433       printer->Print("}\n");
434       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
435         auto& async_prefix = async_prefixes[i];
436         (*vars)["AsyncPrefix"] = async_prefix.prefix;
437         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
438         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
439         printer->Print(*vars,
440                        "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
441                        " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
442                        "$Response$* response, "
443                        "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
444         printer->Indent();
445         printer->Print(
446             *vars,
447             "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
448             "$AsyncPrefix$$Method$Raw(context, response, "
449             "cq$AsyncRawArgs$));\n");
450         printer->Outdent();
451         printer->Print("}\n");
452       }
453     } else if (ServerOnlyStreaming(method)) {
454       printer->Print(
455           *vars,
456           "std::unique_ptr< ::grpc::ClientReader< $Response$>>"
457           " $Method$(::grpc::ClientContext* context, const $Request$& request)"
458           " {\n");
459       printer->Indent();
460       printer->Print(
461           *vars,
462           "return std::unique_ptr< ::grpc::ClientReader< $Response$>>"
463           "($Method$Raw(context, request));\n");
464       printer->Outdent();
465       printer->Print("}\n");
466       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
467         auto& async_prefix = async_prefixes[i];
468         (*vars)["AsyncPrefix"] = async_prefix.prefix;
469         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
470         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
471         printer->Print(
472             *vars,
473             "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
474             "$AsyncPrefix$$Method$("
475             "::grpc::ClientContext* context, const $Request$& request, "
476             "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
477         printer->Indent();
478         printer->Print(
479             *vars,
480             "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
481             "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
482         printer->Outdent();
483         printer->Print("}\n");
484       }
485     } else if (method->BidiStreaming()) {
486       printer->Print(
487           *vars,
488           "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
489           " $Method$(::grpc::ClientContext* context) {\n");
490       printer->Indent();
491       printer->Print(*vars,
492                      "return std::unique_ptr< "
493                      "::grpc::ClientReaderWriter< $Request$, $Response$>>("
494                      "$Method$Raw(context));\n");
495       printer->Outdent();
496       printer->Print("}\n");
497       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
498         auto& async_prefix = async_prefixes[i];
499         (*vars)["AsyncPrefix"] = async_prefix.prefix;
500         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
501         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
502         printer->Print(*vars,
503                        "std::unique_ptr<  ::grpc::ClientAsyncReaderWriter< "
504                        "$Request$, $Response$>> "
505                        "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
506                        "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
507         printer->Indent();
508         printer->Print(
509             *vars,
510             "return std::unique_ptr< "
511             "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
512             "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
513         printer->Outdent();
514         printer->Print("}\n");
515       }
516     }
517   } else {
518     if (method->NoStreaming()) {
519       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
520         auto& async_prefix = async_prefixes[i];
521         (*vars)["AsyncPrefix"] = async_prefix.prefix;
522         printer->Print(
523             *vars,
524             "::grpc::ClientAsyncResponseReader< $Response$>* "
525             "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
526             "const $Request$& request, "
527             "::grpc::CompletionQueue* cq) override;\n");
528       }
529     } else if (ClientOnlyStreaming(method)) {
530       printer->Print(*vars,
531                      "::grpc::ClientWriter< $Request$>* $Method$Raw("
532                      "::grpc::ClientContext* context, $Response$* response) "
533                      "override;\n");
534     for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
535         auto& async_prefix = async_prefixes[i];
536         (*vars)["AsyncPrefix"] = async_prefix.prefix;
537         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
538         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
539         printer->Print(
540             *vars,
541             "::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
542             "::grpc::ClientContext* context, $Response$* response, "
543             "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
544       }
545     } else if (ServerOnlyStreaming(method)) {
546       printer->Print(*vars,
547                      "::grpc::ClientReader< $Response$>* $Method$Raw("
548                      "::grpc::ClientContext* context, const $Request$& request)"
549                      " override;\n");
550     for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
551         auto& async_prefix = async_prefixes[i];
552         (*vars)["AsyncPrefix"] = async_prefix.prefix;
553         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
554         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
555         printer->Print(
556             *vars,
557             "::grpc::ClientAsyncReader< $Response$>* $AsyncPrefix$$Method$Raw("
558             "::grpc::ClientContext* context, const $Request$& request, "
559             "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
560       }
561     } else if (method->BidiStreaming()) {
562       printer->Print(*vars,
563                      "::grpc::ClientReaderWriter< $Request$, $Response$>* "
564                      "$Method$Raw(::grpc::ClientContext* context) override;\n");
565       for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
566         auto& async_prefix = async_prefixes[i];
567         (*vars)["AsyncPrefix"] = async_prefix.prefix;
568         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
569         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
570         printer->Print(
571             *vars,
572             "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
573             "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
574             "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
575       }
576     }
577   }
578 }
579 
PrintHeaderClientMethodData(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)580 void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
581                                  const grpc_generator::Method *method,
582                                  std::map<grpc::string, grpc::string> *vars) {
583   (*vars)["Method"] = method->name();
584   printer->Print(*vars,
585                  "const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
586 }
587 
PrintHeaderServerMethodSync(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)588 void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
589                                  const grpc_generator::Method *method,
590                                  std::map<grpc::string, grpc::string> *vars) {
591   (*vars)["Method"] = method->name();
592   (*vars)["Request"] = method->input_type_name();
593   (*vars)["Response"] = method->output_type_name();
594   printer->Print(method->GetLeadingComments("//").c_str());
595   if (method->NoStreaming()) {
596     printer->Print(*vars,
597                    "virtual ::grpc::Status $Method$("
598                    "::grpc::ServerContext* context, const $Request$* request, "
599                    "$Response$* response);\n");
600   } else if (ClientOnlyStreaming(method)) {
601     printer->Print(*vars,
602                    "virtual ::grpc::Status $Method$("
603                    "::grpc::ServerContext* context, "
604                    "::grpc::ServerReader< $Request$>* reader, "
605                    "$Response$* response);\n");
606   } else if (ServerOnlyStreaming(method)) {
607     printer->Print(*vars,
608                    "virtual ::grpc::Status $Method$("
609                    "::grpc::ServerContext* context, const $Request$* request, "
610                    "::grpc::ServerWriter< $Response$>* writer);\n");
611   } else if (method->BidiStreaming()) {
612     printer->Print(
613         *vars,
614         "virtual ::grpc::Status $Method$("
615         "::grpc::ServerContext* context, "
616         "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
617         "\n");
618   }
619   printer->Print(method->GetTrailingComments("//").c_str());
620 }
621 
PrintHeaderServerMethodAsync(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)622 void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
623                                   const grpc_generator::Method *method,
624                                   std::map<grpc::string, grpc::string> *vars) {
625   (*vars)["Method"] = method->name();
626   (*vars)["Request"] = method->input_type_name();
627   (*vars)["Response"] = method->output_type_name();
628   printer->Print(*vars, "template <class BaseClass>\n");
629   printer->Print(*vars,
630                  "class WithAsyncMethod_$Method$ : public BaseClass {\n");
631   printer->Print(
632       " private:\n"
633       "  void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
634   printer->Print(" public:\n");
635   printer->Indent();
636   printer->Print(*vars,
637                  "WithAsyncMethod_$Method$() {\n"
638                  "  ::grpc::Service::MarkMethodAsync($Idx$);\n"
639                  "}\n");
640   printer->Print(*vars,
641                  "~WithAsyncMethod_$Method$() override {\n"
642                  "  BaseClassMustBeDerivedFromService(this);\n"
643                  "}\n");
644   if (method->NoStreaming()) {
645     printer->Print(
646         *vars,
647         "// disable synchronous version of this method\n"
648         "::grpc::Status $Method$("
649         "::grpc::ServerContext* context, const $Request$* request, "
650         "$Response$* response) final override {\n"
651         "  abort();\n"
652         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
653         "}\n");
654     printer->Print(
655         *vars,
656         "void Request$Method$("
657         "::grpc::ServerContext* context, $Request$* request, "
658         "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
659         "::grpc::CompletionQueue* new_call_cq, "
660         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
661     printer->Print(*vars,
662                    "  ::grpc::Service::RequestAsyncUnary($Idx$, context, "
663                    "request, response, new_call_cq, notification_cq, tag);\n");
664     printer->Print("}\n");
665   } else if (ClientOnlyStreaming(method)) {
666     printer->Print(
667         *vars,
668         "// disable synchronous version of this method\n"
669         "::grpc::Status $Method$("
670         "::grpc::ServerContext* context, "
671         "::grpc::ServerReader< $Request$>* reader, "
672         "$Response$* response) final override {\n"
673         "  abort();\n"
674         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
675         "}\n");
676     printer->Print(
677         *vars,
678         "void Request$Method$("
679         "::grpc::ServerContext* context, "
680         "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
681         "::grpc::CompletionQueue* new_call_cq, "
682         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
683     printer->Print(*vars,
684                    "  ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
685                    "context, reader, new_call_cq, notification_cq, tag);\n");
686     printer->Print("}\n");
687   } else if (ServerOnlyStreaming(method)) {
688     printer->Print(
689         *vars,
690         "// disable synchronous version of this method\n"
691         "::grpc::Status $Method$("
692         "::grpc::ServerContext* context, const $Request$* request, "
693         "::grpc::ServerWriter< $Response$>* writer) final override "
694         "{\n"
695         "  abort();\n"
696         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
697         "}\n");
698     printer->Print(
699         *vars,
700         "void Request$Method$("
701         "::grpc::ServerContext* context, $Request$* request, "
702         "::grpc::ServerAsyncWriter< $Response$>* writer, "
703         "::grpc::CompletionQueue* new_call_cq, "
704         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
705     printer->Print(
706         *vars,
707         "  ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
708         "context, request, writer, new_call_cq, notification_cq, tag);\n");
709     printer->Print("}\n");
710   } else if (method->BidiStreaming()) {
711     printer->Print(
712         *vars,
713         "// disable synchronous version of this method\n"
714         "::grpc::Status $Method$("
715         "::grpc::ServerContext* context, "
716         "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
717         "final override {\n"
718         "  abort();\n"
719         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
720         "}\n");
721     printer->Print(
722         *vars,
723         "void Request$Method$("
724         "::grpc::ServerContext* context, "
725         "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
726         "::grpc::CompletionQueue* new_call_cq, "
727         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
728     printer->Print(*vars,
729                    "  ::grpc::Service::RequestAsyncBidiStreaming($Idx$, "
730                    "context, stream, new_call_cq, notification_cq, tag);\n");
731     printer->Print("}\n");
732   }
733   printer->Outdent();
734   printer->Print(*vars, "};\n");
735 }
736 
PrintHeaderServerMethodStreamedUnary(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)737 void PrintHeaderServerMethodStreamedUnary(
738     grpc_generator::Printer *printer, const grpc_generator::Method *method,
739     std::map<grpc::string, grpc::string> *vars) {
740   (*vars)["Method"] = method->name();
741   (*vars)["Request"] = method->input_type_name();
742   (*vars)["Response"] = method->output_type_name();
743   if (method->NoStreaming()) {
744     printer->Print(*vars, "template <class BaseClass>\n");
745     printer->Print(*vars,
746                    "class WithStreamedUnaryMethod_$Method$ : "
747                    "public BaseClass {\n");
748     printer->Print(
749         " private:\n"
750         "  void BaseClassMustBeDerivedFromService(const Service *service) "
751         "{}\n");
752     printer->Print(" public:\n");
753     printer->Indent();
754     printer->Print(*vars,
755                    "WithStreamedUnaryMethod_$Method$() {\n"
756                    "  ::grpc::Service::MarkMethodStreamed($Idx$,\n"
757                    "    new ::grpc::internal::StreamedUnaryHandler< $Request$, "
758                    "$Response$>(std::bind"
759                    "(&WithStreamedUnaryMethod_$Method$<BaseClass>::"
760                    "Streamed$Method$, this, std::placeholders::_1, "
761                    "std::placeholders::_2)));\n"
762                    "}\n");
763     printer->Print(*vars,
764                    "~WithStreamedUnaryMethod_$Method$() override {\n"
765                    "  BaseClassMustBeDerivedFromService(this);\n"
766                    "}\n");
767     printer->Print(
768         *vars,
769         "// disable regular version of this method\n"
770         "::grpc::Status $Method$("
771         "::grpc::ServerContext* context, const $Request$* request, "
772         "$Response$* response) final override {\n"
773         "  abort();\n"
774         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
775         "}\n");
776     printer->Print(*vars,
777                    "// replace default version of method with streamed unary\n"
778                    "virtual ::grpc::Status Streamed$Method$("
779                    "::grpc::ServerContext* context, "
780                    "::grpc::ServerUnaryStreamer< "
781                    "$Request$,$Response$>* server_unary_streamer)"
782                    " = 0;\n");
783     printer->Outdent();
784     printer->Print(*vars, "};\n");
785   }
786 }
787 
PrintHeaderServerMethodSplitStreaming(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)788 void PrintHeaderServerMethodSplitStreaming(
789     grpc_generator::Printer *printer, const grpc_generator::Method *method,
790     std::map<grpc::string, grpc::string> *vars) {
791   (*vars)["Method"] = method->name();
792   (*vars)["Request"] = method->input_type_name();
793   (*vars)["Response"] = method->output_type_name();
794   if (ServerOnlyStreaming(method)) {
795     printer->Print(*vars, "template <class BaseClass>\n");
796     printer->Print(*vars,
797                    "class WithSplitStreamingMethod_$Method$ : "
798                    "public BaseClass {\n");
799     printer->Print(
800         " private:\n"
801         "  void BaseClassMustBeDerivedFromService(const Service *service) "
802         "{}\n");
803     printer->Print(" public:\n");
804     printer->Indent();
805     printer->Print(
806         *vars,
807         "WithSplitStreamingMethod_$Method$() {\n"
808         "  ::grpc::Service::MarkMethodStreamed($Idx$,\n"
809         "    new ::grpc::internal::SplitServerStreamingHandler< $Request$, "
810         "$Response$>(std::bind"
811         "(&WithSplitStreamingMethod_$Method$<BaseClass>::"
812         "Streamed$Method$, this, std::placeholders::_1, "
813         "std::placeholders::_2)));\n"
814         "}\n");
815     printer->Print(*vars,
816                    "~WithSplitStreamingMethod_$Method$() override {\n"
817                    "  BaseClassMustBeDerivedFromService(this);\n"
818                    "}\n");
819     printer->Print(
820         *vars,
821         "// disable regular version of this method\n"
822         "::grpc::Status $Method$("
823         "::grpc::ServerContext* context, const $Request$* request, "
824         "::grpc::ServerWriter< $Response$>* writer) final override "
825         "{\n"
826         "  abort();\n"
827         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
828         "}\n");
829     printer->Print(*vars,
830                    "// replace default version of method with split streamed\n"
831                    "virtual ::grpc::Status Streamed$Method$("
832                    "::grpc::ServerContext* context, "
833                    "::grpc::ServerSplitStreamer< "
834                    "$Request$,$Response$>* server_split_streamer)"
835                    " = 0;\n");
836     printer->Outdent();
837     printer->Print(*vars, "};\n");
838   }
839 }
840 
PrintHeaderServerMethodGeneric(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)841 void PrintHeaderServerMethodGeneric(
842     grpc_generator::Printer *printer, const grpc_generator::Method *method,
843     std::map<grpc::string, grpc::string> *vars) {
844   (*vars)["Method"] = method->name();
845   (*vars)["Request"] = method->input_type_name();
846   (*vars)["Response"] = method->output_type_name();
847   printer->Print(*vars, "template <class BaseClass>\n");
848   printer->Print(*vars,
849                  "class WithGenericMethod_$Method$ : public BaseClass {\n");
850   printer->Print(
851       " private:\n"
852       "  void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
853   printer->Print(" public:\n");
854   printer->Indent();
855   printer->Print(*vars,
856                  "WithGenericMethod_$Method$() {\n"
857                  "  ::grpc::Service::MarkMethodGeneric($Idx$);\n"
858                  "}\n");
859   printer->Print(*vars,
860                  "~WithGenericMethod_$Method$() override {\n"
861                  "  BaseClassMustBeDerivedFromService(this);\n"
862                  "}\n");
863   if (method->NoStreaming()) {
864     printer->Print(
865         *vars,
866         "// disable synchronous version of this method\n"
867         "::grpc::Status $Method$("
868         "::grpc::ServerContext* context, const $Request$* request, "
869         "$Response$* response) final override {\n"
870         "  abort();\n"
871         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
872         "}\n");
873   } else if (ClientOnlyStreaming(method)) {
874     printer->Print(
875         *vars,
876         "// disable synchronous version of this method\n"
877         "::grpc::Status $Method$("
878         "::grpc::ServerContext* context, "
879         "::grpc::ServerReader< $Request$>* reader, "
880         "$Response$* response) final override {\n"
881         "  abort();\n"
882         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
883         "}\n");
884   } else if (ServerOnlyStreaming(method)) {
885     printer->Print(
886         *vars,
887         "// disable synchronous version of this method\n"
888         "::grpc::Status $Method$("
889         "::grpc::ServerContext* context, const $Request$* request, "
890         "::grpc::ServerWriter< $Response$>* writer) final override "
891         "{\n"
892         "  abort();\n"
893         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
894         "}\n");
895   } else if (method->BidiStreaming()) {
896     printer->Print(
897         *vars,
898         "// disable synchronous version of this method\n"
899         "::grpc::Status $Method$("
900         "::grpc::ServerContext* context, "
901         "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
902         "final override {\n"
903         "  abort();\n"
904         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
905         "}\n");
906   }
907   printer->Outdent();
908   printer->Print(*vars, "};\n");
909 }
910 
PrintHeaderService(grpc_generator::Printer * printer,const grpc_generator::Service * service,std::map<grpc::string,grpc::string> * vars)911 void PrintHeaderService(grpc_generator::Printer *printer,
912                         const grpc_generator::Service *service,
913                         std::map<grpc::string, grpc::string> *vars) {
914   (*vars)["Service"] = service->name();
915 
916   printer->Print(service->GetLeadingComments("//").c_str());
917   printer->Print(*vars,
918                  "class $Service$ final {\n"
919                  " public:\n");
920   printer->Indent();
921 
922   // Service metadata
923   printer->Print(*vars,
924                  "static constexpr char const* service_full_name() {\n"
925                  "  return \"$Package$$Service$\";\n"
926                  "}\n");
927 
928   // Client side
929   printer->Print(
930       "class StubInterface {\n"
931       " public:\n");
932   printer->Indent();
933   printer->Print("virtual ~StubInterface() {}\n");
934   for (int i = 0; i < service->method_count(); ++i) {
935     printer->Print(service->method(i)->GetLeadingComments("//").c_str());
936     PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
937                                       true);
938     printer->Print(service->method(i)->GetTrailingComments("//").c_str());
939   }
940   printer->Outdent();
941   printer->Print("private:\n");
942   printer->Indent();
943   for (int i = 0; i < service->method_count(); ++i) {
944     PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
945                                       false);
946   }
947   printer->Outdent();
948   printer->Print("};\n");
949   printer->Print(
950       "class Stub final : public StubInterface"
951       " {\n public:\n");
952   printer->Indent();
953   printer->Print(
954       "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
955       "channel);\n");
956   for (int i = 0; i < service->method_count(); ++i) {
957     PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
958   }
959   printer->Outdent();
960   printer->Print("\n private:\n");
961   printer->Indent();
962   printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
963   for (int i = 0; i < service->method_count(); ++i) {
964     PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
965   }
966   for (int i = 0; i < service->method_count(); ++i) {
967     PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
968   }
969   printer->Outdent();
970   printer->Print("};\n");
971   printer->Print(
972       "static std::unique_ptr<Stub> NewStub(const std::shared_ptr< "
973       "::grpc::ChannelInterface>& channel, "
974       "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n");
975 
976   printer->Print("\n");
977 
978   // Server side - base
979   printer->Print(
980       "class Service : public ::grpc::Service {\n"
981       " public:\n");
982   printer->Indent();
983   printer->Print("Service();\n");
984   printer->Print("virtual ~Service();\n");
985   for (int i = 0; i < service->method_count(); ++i) {
986     PrintHeaderServerMethodSync(printer, service->method(i).get(), vars);
987   }
988   printer->Outdent();
989   printer->Print("};\n");
990 
991   // Server side - Asynchronous
992   for (int i = 0; i < service->method_count(); ++i) {
993     (*vars)["Idx"] = as_string(i);
994     PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars);
995   }
996 
997   printer->Print("typedef ");
998 
999   for (int i = 0; i < service->method_count(); ++i) {
1000     (*vars)["method_name"] = service->method(i).get()->name();
1001     printer->Print(*vars, "WithAsyncMethod_$method_name$<");
1002   }
1003   printer->Print("Service");
1004   for (int i = 0; i < service->method_count(); ++i) {
1005     printer->Print(" >");
1006   }
1007   printer->Print(" AsyncService;\n");
1008 
1009   // Server side - Generic
1010   for (int i = 0; i < service->method_count(); ++i) {
1011     (*vars)["Idx"] = as_string(i);
1012     PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars);
1013   }
1014 
1015   // Server side - Streamed Unary
1016   for (int i = 0; i < service->method_count(); ++i) {
1017     (*vars)["Idx"] = as_string(i);
1018     PrintHeaderServerMethodStreamedUnary(printer, service->method(i).get(),
1019                                          vars);
1020   }
1021 
1022   printer->Print("typedef ");
1023   for (int i = 0; i < service->method_count(); ++i) {
1024     (*vars)["method_name"] = service->method(i).get()->name();
1025     if (service->method(i)->NoStreaming()) {
1026       printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1027     }
1028   }
1029   printer->Print("Service");
1030   for (int i = 0; i < service->method_count(); ++i) {
1031     if (service->method(i)->NoStreaming()) {
1032       printer->Print(" >");
1033     }
1034   }
1035   printer->Print(" StreamedUnaryService;\n");
1036 
1037   // Server side - controlled server-side streaming
1038   for (int i = 0; i < service->method_count(); ++i) {
1039     (*vars)["Idx"] = as_string(i);
1040     PrintHeaderServerMethodSplitStreaming(printer, service->method(i).get(),
1041                                           vars);
1042   }
1043 
1044   printer->Print("typedef ");
1045   for (int i = 0; i < service->method_count(); ++i) {
1046     (*vars)["method_name"] = service->method(i).get()->name();
1047     auto method = service->method(i);
1048     if (ServerOnlyStreaming(method.get())) {
1049       printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1050     }
1051   }
1052   printer->Print("Service");
1053   for (int i = 0; i < service->method_count(); ++i) {
1054     auto method = service->method(i);
1055     if (ServerOnlyStreaming(method.get())) {
1056       printer->Print(" >");
1057     }
1058   }
1059   printer->Print(" SplitStreamedService;\n");
1060 
1061   // Server side - typedef for controlled both unary and server-side streaming
1062   printer->Print("typedef ");
1063   for (int i = 0; i < service->method_count(); ++i) {
1064     (*vars)["method_name"] = service->method(i).get()->name();
1065     auto method = service->method(i);
1066     if (ServerOnlyStreaming(method.get())) {
1067       printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1068     }
1069     if (service->method(i)->NoStreaming()) {
1070       printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1071     }
1072   }
1073   printer->Print("Service");
1074   for (int i = 0; i < service->method_count(); ++i) {
1075     auto method = service->method(i);
1076     if (service->method(i)->NoStreaming() ||
1077         ServerOnlyStreaming(method.get())) {
1078       printer->Print(" >");
1079     }
1080   }
1081   printer->Print(" StreamedService;\n");
1082 
1083   printer->Outdent();
1084   printer->Print("};\n");
1085   printer->Print(service->GetTrailingComments("//").c_str());
1086 }
1087 
GetHeaderServices(grpc_generator::File * file,const Parameters & params)1088 grpc::string GetHeaderServices(grpc_generator::File *file,
1089                                const Parameters &params) {
1090   grpc::string output;
1091   {
1092     // Scope the output stream so it closes and finalizes output to the string.
1093     auto printer = file->CreatePrinter(&output);
1094     std::map<grpc::string, grpc::string> vars;
1095     // Package string is empty or ends with a dot. It is used to fully qualify
1096     // method names.
1097     vars["Package"] = file->package();
1098     if (!file->package().empty()) {
1099       vars["Package"].append(".");
1100     }
1101 
1102     if (!params.services_namespace.empty()) {
1103       vars["services_namespace"] = params.services_namespace;
1104       printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
1105     }
1106 
1107     for (int i = 0; i < file->service_count(); ++i) {
1108       PrintHeaderService(printer.get(), file->service(i).get(), &vars);
1109       printer->Print("\n");
1110     }
1111 
1112     if (!params.services_namespace.empty()) {
1113       printer->Print(vars, "}  // namespace $services_namespace$\n\n");
1114     }
1115   }
1116   return output;
1117 }
1118 
GetHeaderEpilogue(grpc_generator::File * file,const Parameters &)1119 grpc::string GetHeaderEpilogue(grpc_generator::File *file,
1120                                const Parameters & /*params*/) {
1121   grpc::string output;
1122   {
1123     // Scope the output stream so it closes and finalizes output to the string.
1124     auto printer = file->CreatePrinter(&output);
1125     std::map<grpc::string, grpc::string> vars;
1126 
1127     vars["filename"] = file->filename();
1128     vars["filename_identifier"] = FilenameIdentifier(file->filename());
1129 
1130     if (!file->package().empty()) {
1131       std::vector<grpc::string> parts = file->package_parts();
1132 
1133       for (auto part = parts.rbegin(); part != parts.rend(); part++) {
1134         vars["part"] = *part;
1135         printer->Print(vars, "}  // namespace $part$\n");
1136       }
1137       printer->Print(vars, "\n");
1138     }
1139 
1140     printer->Print(vars, "\n");
1141     printer->Print(vars, "#endif  // GRPC_$filename_identifier$__INCLUDED\n");
1142 
1143     printer->Print(file->GetTrailingComments("//").c_str());
1144   }
1145   return output;
1146 }
1147 
GetSourcePrologue(grpc_generator::File * file,const Parameters &)1148 grpc::string GetSourcePrologue(grpc_generator::File *file,
1149                                const Parameters & /*params*/) {
1150   grpc::string output;
1151   {
1152     // Scope the output stream so it closes and finalizes output to the string.
1153     auto printer = file->CreatePrinter(&output);
1154     std::map<grpc::string, grpc::string> vars;
1155 
1156     vars["filename"] = file->filename();
1157     vars["filename_base"] = file->filename_without_ext();
1158     vars["message_header_ext"] = message_header_ext();
1159     vars["service_header_ext"] = service_header_ext();
1160 
1161     printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
1162     printer->Print(vars,
1163                    "// If you make any local change, they will be lost.\n");
1164     printer->Print(vars, "// source: $filename$\n\n");
1165 
1166     printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
1167     printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
1168     printer->Print(vars, "\n");
1169   }
1170   return output;
1171 }
1172 
GetSourceIncludes(grpc_generator::File * file,const Parameters & params)1173 grpc::string GetSourceIncludes(grpc_generator::File *file,
1174                                const Parameters &params) {
1175   grpc::string output;
1176   {
1177     // Scope the output stream so it closes and finalizes output to the string.
1178     auto printer = file->CreatePrinter(&output);
1179     std::map<grpc::string, grpc::string> vars;
1180 
1181     static const char *headers_strs[] = {
1182         "grpc++/impl/codegen/async_stream.h",
1183         "grpc++/impl/codegen/async_unary_call.h",
1184         "grpc++/impl/codegen/channel_interface.h",
1185         "grpc++/impl/codegen/client_unary_call.h",
1186         "grpc++/impl/codegen/method_handler_impl.h",
1187         "grpc++/impl/codegen/rpc_service_method.h",
1188         "grpc++/impl/codegen/service_type.h",
1189         "grpc++/impl/codegen/sync_stream.h"};
1190     std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
1191     PrintIncludes(printer.get(), headers, params);
1192 
1193     if (!file->package().empty()) {
1194       std::vector<grpc::string> parts = file->package_parts();
1195 
1196       for (auto part = parts.begin(); part != parts.end(); part++) {
1197         vars["part"] = *part;
1198         printer->Print(vars, "namespace $part$ {\n");
1199       }
1200     }
1201 
1202     printer->Print(vars, "\n");
1203   }
1204   return output;
1205 }
1206 
PrintSourceClientMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)1207 void PrintSourceClientMethod(grpc_generator::Printer *printer,
1208                              const grpc_generator::Method *method,
1209                              std::map<grpc::string, grpc::string> *vars) {
1210   (*vars)["Method"] = method->name();
1211   (*vars)["Request"] = method->input_type_name();
1212   (*vars)["Response"] = method->output_type_name();
1213   struct {
1214     grpc::string prefix;
1215     grpc::string start;          // bool literal expressed as string
1216     grpc::string method_params;  // extra arguments to method
1217     grpc::string create_args;    // extra arguments to creator
1218   } async_prefixes[] = {{"Async", "true", ", void* tag", ", tag"},
1219                         {"PrepareAsync", "false", "", ", nullptr"}};
1220   if (method->NoStreaming()) {
1221     printer->Print(*vars,
1222                    "::grpc::Status $ns$$Service$::Stub::$Method$("
1223                    "::grpc::ClientContext* context, "
1224                    "const $Request$& request, $Response$* response) {\n");
1225     printer->Print(*vars,
1226                    "  return ::grpc::internal::BlockingUnaryCall"
1227                    "(channel_.get(), rpcmethod_$Method$_, "
1228                    "context, request, response);\n}\n\n");
1229     for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1230       auto& async_prefix = async_prefixes[i];
1231       (*vars)["AsyncPrefix"] = async_prefix.prefix;
1232       (*vars)["AsyncStart"] = async_prefix.start;
1233       printer->Print(*vars,
1234                      "::grpc::ClientAsyncResponseReader< $Response$>* "
1235                      "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
1236                      "ClientContext* context, "
1237                      "const $Request$& request, "
1238                      "::grpc::CompletionQueue* cq) {\n");
1239       printer->Print(
1240           *vars,
1241           "  return "
1242           "::grpc::internal::ClientAsyncResponseReaderFactory< $Response$>"
1243           "::Create(channel_.get(), cq, "
1244           "rpcmethod_$Method$_, "
1245           "context, request, $AsyncStart$);\n"
1246           "}\n\n");
1247     }
1248   } else if (ClientOnlyStreaming(method)) {
1249     printer->Print(*vars,
1250                    "::grpc::ClientWriter< $Request$>* "
1251                    "$ns$$Service$::Stub::$Method$Raw("
1252                    "::grpc::ClientContext* context, $Response$* response) {\n");
1253     printer->Print(
1254         *vars,
1255         "  return ::grpc::internal::ClientWriterFactory< $Request$>::Create("
1256         "channel_.get(), "
1257         "rpcmethod_$Method$_, "
1258         "context, response);\n"
1259         "}\n\n");
1260     for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1261       auto& async_prefix = async_prefixes[i];
1262       (*vars)["AsyncPrefix"] = async_prefix.prefix;
1263       (*vars)["AsyncStart"] = async_prefix.start;
1264       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1265       (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1266       printer->Print(*vars,
1267                      "::grpc::ClientAsyncWriter< $Request$>* "
1268                      "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
1269                      "::grpc::ClientContext* context, $Response$* response, "
1270                      "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1271       printer->Print(
1272           *vars,
1273           "  return ::grpc::internal::ClientAsyncWriterFactory< $Request$>"
1274           "::Create(channel_.get(), cq, "
1275           "rpcmethod_$Method$_, "
1276           "context, response, $AsyncStart$$AsyncCreateArgs$);\n"
1277           "}\n\n");
1278     }
1279   } else if (ServerOnlyStreaming(method)) {
1280     printer->Print(
1281         *vars,
1282         "::grpc::ClientReader< $Response$>* "
1283         "$ns$$Service$::Stub::$Method$Raw("
1284         "::grpc::ClientContext* context, const $Request$& request) {\n");
1285     printer->Print(
1286         *vars,
1287         "  return ::grpc::internal::ClientReaderFactory< $Response$>::Create("
1288         "channel_.get(), "
1289         "rpcmethod_$Method$_, "
1290         "context, request);\n"
1291         "}\n\n");
1292     for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1293       auto& async_prefix = async_prefixes[i];
1294       (*vars)["AsyncPrefix"] = async_prefix.prefix;
1295       (*vars)["AsyncStart"] = async_prefix.start;
1296       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1297       (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1298       printer->Print(
1299           *vars,
1300           "::grpc::ClientAsyncReader< $Response$>* "
1301           "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
1302           "::grpc::ClientContext* context, const $Request$& request, "
1303           "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1304       printer->Print(
1305           *vars,
1306           "  return ::grpc::internal::ClientAsyncReaderFactory< $Response$>"
1307           "::Create(channel_.get(), cq, "
1308           "rpcmethod_$Method$_, "
1309           "context, request, $AsyncStart$$AsyncCreateArgs$);\n"
1310           "}\n\n");
1311     }
1312   } else if (method->BidiStreaming()) {
1313     printer->Print(
1314         *vars,
1315         "::grpc::ClientReaderWriter< $Request$, $Response$>* "
1316         "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
1317     printer->Print(*vars,
1318                    "  return ::grpc::internal::ClientReaderWriterFactory< "
1319                    "$Request$, $Response$>::Create("
1320                    "channel_.get(), "
1321                    "rpcmethod_$Method$_, "
1322                    "context);\n"
1323                    "}\n\n");
1324     for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1325       auto& async_prefix = async_prefixes[i];
1326       (*vars)["AsyncPrefix"] = async_prefix.prefix;
1327       (*vars)["AsyncStart"] = async_prefix.start;
1328       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1329       (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1330       printer->Print(*vars,
1331                      "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
1332                      "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
1333                      "ClientContext* context, "
1334                      "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1335       printer->Print(*vars,
1336                      "  return "
1337                      "::grpc::internal::ClientAsyncReaderWriterFactory< "
1338                      "$Request$, $Response$>::Create("
1339                      "channel_.get(), cq, "
1340                      "rpcmethod_$Method$_, "
1341                      "context, $AsyncStart$$AsyncCreateArgs$);\n"
1342                      "}\n\n");
1343     }
1344   }
1345 }
1346 
PrintSourceServerMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)1347 void PrintSourceServerMethod(grpc_generator::Printer *printer,
1348                              const grpc_generator::Method *method,
1349                              std::map<grpc::string, grpc::string> *vars) {
1350   (*vars)["Method"] = method->name();
1351   (*vars)["Request"] = method->input_type_name();
1352   (*vars)["Response"] = method->output_type_name();
1353   if (method->NoStreaming()) {
1354     printer->Print(*vars,
1355                    "::grpc::Status $ns$$Service$::Service::$Method$("
1356                    "::grpc::ServerContext* context, "
1357                    "const $Request$* request, $Response$* response) {\n");
1358     printer->Print("  (void) context;\n");
1359     printer->Print("  (void) request;\n");
1360     printer->Print("  (void) response;\n");
1361     printer->Print(
1362         "  return ::grpc::Status("
1363         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1364     printer->Print("}\n\n");
1365   } else if (ClientOnlyStreaming(method)) {
1366     printer->Print(*vars,
1367                    "::grpc::Status $ns$$Service$::Service::$Method$("
1368                    "::grpc::ServerContext* context, "
1369                    "::grpc::ServerReader< $Request$>* reader, "
1370                    "$Response$* response) {\n");
1371     printer->Print("  (void) context;\n");
1372     printer->Print("  (void) reader;\n");
1373     printer->Print("  (void) response;\n");
1374     printer->Print(
1375         "  return ::grpc::Status("
1376         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1377     printer->Print("}\n\n");
1378   } else if (ServerOnlyStreaming(method)) {
1379     printer->Print(*vars,
1380                    "::grpc::Status $ns$$Service$::Service::$Method$("
1381                    "::grpc::ServerContext* context, "
1382                    "const $Request$* request, "
1383                    "::grpc::ServerWriter< $Response$>* writer) {\n");
1384     printer->Print("  (void) context;\n");
1385     printer->Print("  (void) request;\n");
1386     printer->Print("  (void) writer;\n");
1387     printer->Print(
1388         "  return ::grpc::Status("
1389         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1390     printer->Print("}\n\n");
1391   } else if (method->BidiStreaming()) {
1392     printer->Print(*vars,
1393                    "::grpc::Status $ns$$Service$::Service::$Method$("
1394                    "::grpc::ServerContext* context, "
1395                    "::grpc::ServerReaderWriter< $Response$, $Request$>* "
1396                    "stream) {\n");
1397     printer->Print("  (void) context;\n");
1398     printer->Print("  (void) stream;\n");
1399     printer->Print(
1400         "  return ::grpc::Status("
1401         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1402     printer->Print("}\n\n");
1403   }
1404 }
1405 
PrintSourceService(grpc_generator::Printer * printer,const grpc_generator::Service * service,std::map<grpc::string,grpc::string> * vars)1406 void PrintSourceService(grpc_generator::Printer *printer,
1407                         const grpc_generator::Service *service,
1408                         std::map<grpc::string, grpc::string> *vars) {
1409   (*vars)["Service"] = service->name();
1410 
1411   if (service->method_count() > 0) {
1412     printer->Print(*vars,
1413                    "static const char* $prefix$$Service$_method_names[] = {\n");
1414     for (int i = 0; i < service->method_count(); ++i) {
1415       (*vars)["Method"] = service->method(i).get()->name();
1416       printer->Print(*vars, "  \"/$Package$$Service$/$Method$\",\n");
1417     }
1418     printer->Print(*vars, "};\n\n");
1419   }
1420 
1421   printer->Print(*vars,
1422                  "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
1423                  "const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
1424                  "const ::grpc::StubOptions& options) {\n"
1425                  "  std::unique_ptr< $ns$$Service$::Stub> stub(new "
1426                  "$ns$$Service$::Stub(channel));\n"
1427                  "  return stub;\n"
1428                  "}\n\n");
1429   printer->Print(*vars,
1430                  "$ns$$Service$::Stub::Stub(const std::shared_ptr< "
1431                  "::grpc::ChannelInterface>& channel)\n");
1432   printer->Indent();
1433   printer->Print(": channel_(channel)");
1434   for (int i = 0; i < service->method_count(); ++i) {
1435     auto method = service->method(i);
1436     (*vars)["Method"] = method->name();
1437     (*vars)["Idx"] = as_string(i);
1438     if (method->NoStreaming()) {
1439       (*vars)["StreamingType"] = "NORMAL_RPC";
1440       // NOTE: There is no reason to consider streamed-unary as a separate
1441       // category here since this part is setting up the client-side stub
1442       // and this appears as a NORMAL_RPC from the client-side.
1443     } else if (ClientOnlyStreaming(method.get())) {
1444       (*vars)["StreamingType"] = "CLIENT_STREAMING";
1445     } else if (ServerOnlyStreaming(method.get())) {
1446       (*vars)["StreamingType"] = "SERVER_STREAMING";
1447     } else {
1448       (*vars)["StreamingType"] = "BIDI_STREAMING";
1449     }
1450     printer->Print(*vars,
1451                    ", rpcmethod_$Method$_("
1452                    "$prefix$$Service$_method_names[$Idx$], "
1453                    "::grpc::internal::RpcMethod::$StreamingType$, "
1454                    "channel"
1455                    ")\n");
1456   }
1457   printer->Print("{}\n\n");
1458   printer->Outdent();
1459 
1460   for (int i = 0; i < service->method_count(); ++i) {
1461     (*vars)["Idx"] = as_string(i);
1462     PrintSourceClientMethod(printer, service->method(i).get(), vars);
1463   }
1464 
1465   printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
1466   printer->Indent();
1467   for (int i = 0; i < service->method_count(); ++i) {
1468     auto method = service->method(i);
1469     (*vars)["Idx"] = as_string(i);
1470     (*vars)["Method"] = method->name();
1471     (*vars)["Request"] = method->input_type_name();
1472     (*vars)["Response"] = method->output_type_name();
1473     if (method->NoStreaming()) {
1474       printer->Print(
1475           *vars,
1476           "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1477           "    $prefix$$Service$_method_names[$Idx$],\n"
1478           "    ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
1479           "    new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
1480           "$Request$, "
1481           "$Response$>(\n"
1482           "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1483     } else if (ClientOnlyStreaming(method.get())) {
1484       printer->Print(
1485           *vars,
1486           "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1487           "    $prefix$$Service$_method_names[$Idx$],\n"
1488           "    ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
1489           "    new ::grpc::internal::ClientStreamingHandler< "
1490           "$ns$$Service$::Service, $Request$, $Response$>(\n"
1491           "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1492     } else if (ServerOnlyStreaming(method.get())) {
1493       printer->Print(
1494           *vars,
1495           "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1496           "    $prefix$$Service$_method_names[$Idx$],\n"
1497           "    ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
1498           "    new ::grpc::internal::ServerStreamingHandler< "
1499           "$ns$$Service$::Service, $Request$, $Response$>(\n"
1500           "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1501     } else if (method->BidiStreaming()) {
1502       printer->Print(
1503           *vars,
1504           "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1505           "    $prefix$$Service$_method_names[$Idx$],\n"
1506           "    ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
1507           "    new ::grpc::internal::BidiStreamingHandler< "
1508           "$ns$$Service$::Service, $Request$, $Response$>(\n"
1509           "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1510     }
1511   }
1512   printer->Outdent();
1513   printer->Print(*vars, "}\n\n");
1514   printer->Print(*vars,
1515                  "$ns$$Service$::Service::~Service() {\n"
1516                  "}\n\n");
1517   for (int i = 0; i < service->method_count(); ++i) {
1518     (*vars)["Idx"] = as_string(i);
1519     PrintSourceServerMethod(printer, service->method(i).get(), vars);
1520   }
1521 }
1522 
GetSourceServices(grpc_generator::File * file,const Parameters & params)1523 grpc::string GetSourceServices(grpc_generator::File *file,
1524                                const Parameters &params) {
1525   grpc::string output;
1526   {
1527     // Scope the output stream so it closes and finalizes output to the string.
1528     auto printer = file->CreatePrinter(&output);
1529     std::map<grpc::string, grpc::string> vars;
1530     // Package string is empty or ends with a dot. It is used to fully qualify
1531     // method names.
1532     vars["Package"] = file->package();
1533     if (!file->package().empty()) {
1534       vars["Package"].append(".");
1535     }
1536     if (!params.services_namespace.empty()) {
1537       vars["ns"] = params.services_namespace + "::";
1538       vars["prefix"] = params.services_namespace;
1539     } else {
1540       vars["ns"] = "";
1541       vars["prefix"] = "";
1542     }
1543 
1544     for (int i = 0; i < file->service_count(); ++i) {
1545       PrintSourceService(printer.get(), file->service(i).get(), &vars);
1546       printer->Print("\n");
1547     }
1548   }
1549   return output;
1550 }
1551 
GetSourceEpilogue(grpc_generator::File * file,const Parameters &)1552 grpc::string GetSourceEpilogue(grpc_generator::File *file,
1553                                const Parameters & /*params*/) {
1554   grpc::string temp;
1555 
1556   if (!file->package().empty()) {
1557     std::vector<grpc::string> parts = file->package_parts();
1558 
1559     for (auto part = parts.begin(); part != parts.end(); part++) {
1560       temp.append("}  // namespace ");
1561       temp.append(*part);
1562       temp.append("\n");
1563     }
1564     temp.append("\n");
1565   }
1566 
1567   return temp;
1568 }
1569 
1570 // TODO(mmukhi): Make sure we need parameters or not.
GetMockPrologue(grpc_generator::File * file,const Parameters &)1571 grpc::string GetMockPrologue(grpc_generator::File *file,
1572                              const Parameters & /*params*/) {
1573   grpc::string output;
1574   {
1575     // Scope the output stream so it closes and finalizes output to the string.
1576     auto printer = file->CreatePrinter(&output);
1577     std::map<grpc::string, grpc::string> vars;
1578 
1579     vars["filename"] = file->filename();
1580     vars["filename_base"] = file->filename_without_ext();
1581     vars["message_header_ext"] = message_header_ext();
1582     vars["service_header_ext"] = service_header_ext();
1583 
1584     printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
1585     printer->Print(vars,
1586                    "// If you make any local change, they will be lost.\n");
1587     printer->Print(vars, "// source: $filename$\n\n");
1588 
1589     printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
1590     printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
1591     printer->Print(vars, file->additional_headers().c_str());
1592     printer->Print(vars, "\n");
1593   }
1594   return output;
1595 }
1596 
1597 // TODO(mmukhi): Add client-stream and completion-queue headers.
GetMockIncludes(grpc_generator::File * file,const Parameters & params)1598 grpc::string GetMockIncludes(grpc_generator::File *file,
1599                              const Parameters &params) {
1600   grpc::string output;
1601   {
1602     // Scope the output stream so it closes and finalizes output to the string.
1603     auto printer = file->CreatePrinter(&output);
1604     std::map<grpc::string, grpc::string> vars;
1605 
1606     static const char *headers_strs[] = {
1607         "grpc++/impl/codegen/async_stream.h",
1608         "grpc++/impl/codegen/sync_stream.h",
1609         "gmock/gmock.h",
1610     };
1611     std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
1612     PrintIncludes(printer.get(), headers, params);
1613 
1614     if (!file->package().empty()) {
1615       std::vector<grpc::string> parts = file->package_parts();
1616 
1617       for (auto part = parts.begin(); part != parts.end(); part++) {
1618         vars["part"] = *part;
1619         printer->Print(vars, "namespace $part$ {\n");
1620       }
1621     }
1622 
1623     printer->Print(vars, "\n");
1624   }
1625   return output;
1626 }
1627 
PrintMockClientMethods(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)1628 void PrintMockClientMethods(grpc_generator::Printer *printer,
1629                             const grpc_generator::Method *method,
1630                             std::map<grpc::string, grpc::string> *vars) {
1631   (*vars)["Method"] = method->name();
1632   (*vars)["Request"] = method->input_type_name();
1633   (*vars)["Response"] = method->output_type_name();
1634 
1635   struct {
1636     grpc::string prefix;
1637     grpc::string method_params;  // extra arguments to method
1638     int extra_method_param_count;
1639   } async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
1640 
1641   if (method->NoStreaming()) {
1642     printer->Print(
1643         *vars,
1644         "MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
1645         "const $Request$& request, $Response$* response));\n");
1646     for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1647       auto& async_prefix = async_prefixes[i];
1648       (*vars)["AsyncPrefix"] = async_prefix.prefix;
1649       printer->Print(
1650           *vars,
1651           "MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
1652           "::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
1653           "(::grpc::ClientContext* context, const $Request$& request, "
1654           "::grpc::CompletionQueue* cq));\n");
1655     }
1656   } else if (ClientOnlyStreaming(method)) {
1657     printer->Print(
1658         *vars,
1659         "MOCK_METHOD2($Method$Raw, "
1660         "::grpc::ClientWriterInterface< $Request$>*"
1661         "(::grpc::ClientContext* context, $Response$* response));\n");
1662     for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1663       auto& async_prefix = async_prefixes[i];
1664       (*vars)["AsyncPrefix"] = async_prefix.prefix;
1665       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1666       (*vars)["MockArgs"] =
1667         flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
1668       printer->Print(*vars,
1669                      "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1670                      "::grpc::ClientAsyncWriterInterface< $Request$>*"
1671                      "(::grpc::ClientContext* context, $Response$* response, "
1672                      "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
1673     }
1674   } else if (ServerOnlyStreaming(method)) {
1675     printer->Print(
1676         *vars,
1677         "MOCK_METHOD2($Method$Raw, "
1678         "::grpc::ClientReaderInterface< $Response$>*"
1679         "(::grpc::ClientContext* context, const $Request$& request));\n");
1680     for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1681       auto& async_prefix = async_prefixes[i];
1682       (*vars)["AsyncPrefix"] = async_prefix.prefix;
1683       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1684       (*vars)["MockArgs"] =
1685           flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
1686       printer->Print(
1687           *vars,
1688           "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1689           "::grpc::ClientAsyncReaderInterface< $Response$>*"
1690           "(::grpc::ClientContext* context, const $Request$& request, "
1691           "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
1692     }
1693   } else if (method->BidiStreaming()) {
1694     printer->Print(
1695         *vars,
1696         "MOCK_METHOD1($Method$Raw, "
1697         "::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
1698         "(::grpc::ClientContext* context));\n");
1699     for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1700       auto& async_prefix = async_prefixes[i];
1701       (*vars)["AsyncPrefix"] = async_prefix.prefix;
1702       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1703       (*vars)["MockArgs"] =
1704           flatbuffers::NumToString(2 + async_prefix.extra_method_param_count);
1705       printer->Print(
1706           *vars,
1707           "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1708           "::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
1709           "(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
1710           "$AsyncMethodParams$));\n");
1711     }
1712   }
1713 }
1714 
PrintMockService(grpc_generator::Printer * printer,const grpc_generator::Service * service,std::map<grpc::string,grpc::string> * vars)1715 void PrintMockService(grpc_generator::Printer *printer,
1716                       const grpc_generator::Service *service,
1717                       std::map<grpc::string, grpc::string> *vars) {
1718   (*vars)["Service"] = service->name();
1719 
1720   printer->Print(*vars,
1721                  "class Mock$Service$Stub : public $Service$::StubInterface {\n"
1722                  " public:\n");
1723   printer->Indent();
1724   for (int i = 0; i < service->method_count(); ++i) {
1725     PrintMockClientMethods(printer, service->method(i).get(), vars);
1726   }
1727   printer->Outdent();
1728   printer->Print("};\n");
1729 }
1730 
GetMockServices(grpc_generator::File * file,const Parameters & params)1731 grpc::string GetMockServices(grpc_generator::File *file,
1732                              const Parameters &params) {
1733   grpc::string output;
1734   {
1735     // Scope the output stream so it closes and finalizes output to the string.
1736     auto printer = file->CreatePrinter(&output);
1737     std::map<grpc::string, grpc::string> vars;
1738     // Package string is empty or ends with a dot. It is used to fully qualify
1739     // method names.
1740     vars["Package"] = file->package();
1741     if (!file->package().empty()) {
1742       vars["Package"].append(".");
1743     }
1744 
1745     if (!params.services_namespace.empty()) {
1746       vars["services_namespace"] = params.services_namespace;
1747       printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
1748     }
1749 
1750     for (int i = 0; i < file->service_count(); i++) {
1751       PrintMockService(printer.get(), file->service(i).get(), &vars);
1752       printer->Print("\n");
1753     }
1754 
1755     if (!params.services_namespace.empty()) {
1756       printer->Print(vars, "} // namespace $services_namespace$\n\n");
1757     }
1758   }
1759   return output;
1760 }
1761 
GetMockEpilogue(grpc_generator::File * file,const Parameters &)1762 grpc::string GetMockEpilogue(grpc_generator::File *file,
1763                              const Parameters & /*params*/) {
1764   grpc::string temp;
1765 
1766   if (!file->package().empty()) {
1767     std::vector<grpc::string> parts = file->package_parts();
1768 
1769     for (auto part = parts.begin(); part != parts.end(); part++) {
1770       temp.append("} // namespace ");
1771       temp.append(*part);
1772       temp.append("\n");
1773     }
1774     temp.append("\n");
1775   }
1776 
1777   return temp;
1778 }
1779 
1780 }  // namespace grpc_cpp_generator
1781