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