• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #include "src/compiler/cpp_generator.h"
20 
21 #include <map>
22 #include <sstream>
23 #include <vector>
24 
25 namespace grpc_cpp_generator {
26 namespace {
27 
28 template <class T>
as_string(T x)29 std::string as_string(T x) {
30   std::ostringstream out;
31   out << x;
32   return out.str();
33 }
34 
ClientOnlyStreaming(const grpc_generator::Method * method)35 inline bool ClientOnlyStreaming(const grpc_generator::Method* method) {
36   return method->ClientStreaming() && !method->ServerStreaming();
37 }
38 
ServerOnlyStreaming(const grpc_generator::Method * method)39 inline bool ServerOnlyStreaming(const grpc_generator::Method* method) {
40   return !method->ClientStreaming() && method->ServerStreaming();
41 }
42 
FilenameIdentifier(const std::string & filename)43 std::string FilenameIdentifier(const std::string& filename) {
44   std::string result;
45   for (unsigned i = 0; i < filename.size(); i++) {
46     char c = filename[i];
47     if (isalnum(c)) {
48       result.push_back(c);
49     } else {
50       static char hex[] = "0123456789abcdef";
51       result.push_back('_');
52       result.push_back(hex[(c >> 4) & 0xf]);
53       result.push_back(hex[c & 0xf]);
54     }
55   }
56   return result;
57 }
58 
59 }  // namespace
60 
61 template <class T, size_t N>
array_end(T (& array)[N])62 T* array_end(T (&array)[N]) {
63   return array + N;
64 }
65 
PrintIncludes(grpc_generator::Printer * printer,const std::vector<std::string> & headers,bool use_system_headers,const std::string & search_path)66 void PrintIncludes(grpc_generator::Printer* printer,
67                    const std::vector<std::string>& headers,
68                    bool use_system_headers, const std::string& search_path) {
69   std::map<std::string, std::string> vars;
70 
71   vars["l"] = use_system_headers ? '<' : '"';
72   vars["r"] = use_system_headers ? '>' : '"';
73 
74   if (!search_path.empty()) {
75     vars["l"] += search_path;
76     if (search_path[search_path.size() - 1] != '/') {
77       vars["l"] += '/';
78     }
79   }
80 
81   for (auto i = headers.begin(); i != headers.end(); i++) {
82     vars["h"] = *i;
83     printer->Print(vars, "#include $l$$h$$r$\n");
84   }
85 }
86 
GetHeaderPrologue(grpc_generator::File * file,const Parameters & params)87 std::string GetHeaderPrologue(grpc_generator::File* file,
88                               const Parameters& params) {
89   std::string output;
90   {
91     // Scope the output stream so it closes and finalizes output to the string.
92     auto printer = file->CreatePrinter(&output);
93     std::map<std::string, std::string> vars;
94 
95     vars["filename"] = file->filename();
96     vars["filename_identifier"] = FilenameIdentifier(file->filename());
97     vars["filename_base"] = file->filename_without_ext();
98     vars["message_header_ext"] = params.message_header_extension.empty()
99                                      ? kCppGeneratorMessageHeaderExt
100                                      : params.message_header_extension;
101 
102     printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
103     printer->Print(vars,
104                    "// If you make any local change, they will be lost.\n");
105     printer->Print(vars, "// source: $filename$\n");
106     std::string leading_comments = file->GetLeadingComments("//");
107     if (!leading_comments.empty()) {
108       printer->Print(vars, "// Original file comments:\n");
109       printer->PrintRaw(leading_comments.c_str());
110     }
111     printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
112     printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
113     printer->Print(vars, "\n");
114     printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
115     printer->Print(vars, file->additional_headers().c_str());
116     printer->Print(vars, "\n");
117   }
118   return output;
119 }
120 
121 // Convert from "a/b/c.proto" to "#include \"a/b/c$message_header_ext$\"\n"
ImportInludeFromProtoName(const std::string & proto_name)122 std::string ImportInludeFromProtoName(const std::string& proto_name) {
123   return std::string("#include \"") +
124          proto_name.substr(0, proto_name.size() - 6) +
125          std::string("$message_header_ext$\"\n");
126 }
127 
GetHeaderIncludes(grpc_generator::File * file,const Parameters & params)128 std::string GetHeaderIncludes(grpc_generator::File* file,
129                               const Parameters& params) {
130   std::string output;
131   {
132     // Scope the output stream so it closes and finalizes output to the string.
133     auto printer = file->CreatePrinter(&output);
134     std::map<std::string, std::string> vars;
135 
136     if (!params.additional_header_includes.empty()) {
137       PrintIncludes(printer.get(), params.additional_header_includes, false,
138                     "");
139     }
140     static const char* headers_strs[] = {
141         "functional",
142         "grpcpp/generic/async_generic_service.h",
143         "grpcpp/support/async_stream.h",
144         "grpcpp/support/async_unary_call.h",
145         "grpcpp/support/client_callback.h",
146         "grpcpp/client_context.h",
147         "grpcpp/completion_queue.h",
148         "grpcpp/support/message_allocator.h",
149         "grpcpp/support/method_handler.h",
150         "grpcpp/impl/proto_utils.h",
151         "grpcpp/impl/rpc_method.h",
152         "grpcpp/support/server_callback.h",
153         "grpcpp/impl/server_callback_handlers.h",
154         "grpcpp/server_context.h",
155         "grpcpp/impl/service_type.h",
156         "grpcpp/support/status.h",
157         "grpcpp/support/stub_options.h",
158         "grpcpp/support/sync_stream.h",
159     };
160     std::vector<std::string> headers(headers_strs, array_end(headers_strs));
161     PrintIncludes(printer.get(), headers, params.use_system_headers,
162                   params.grpc_search_path);
163     printer->Print(vars, "\n");
164 
165     vars["message_header_ext"] = params.message_header_extension.empty()
166                                      ? kCppGeneratorMessageHeaderExt
167                                      : params.message_header_extension;
168 
169     if (params.include_import_headers) {
170       const std::vector<std::string> import_names = file->GetImportNames();
171       for (const auto& import_name : import_names) {
172         const std::string include_name = ImportInludeFromProtoName(import_name);
173         printer->Print(vars, include_name.c_str());
174       }
175       printer->PrintRaw("\n");
176     }
177 
178     if (!file->package().empty()) {
179       std::vector<std::string> parts = file->package_parts();
180 
181       for (auto part = parts.begin(); part != parts.end(); part++) {
182         vars["part"] = *part;
183         printer->Print(vars, "namespace $part$ {\n");
184       }
185       printer->Print(vars, "\n");
186     }
187   }
188   return output;
189 }
190 
PrintHeaderClientMethodInterfaces(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars,bool is_public)191 void PrintHeaderClientMethodInterfaces(grpc_generator::Printer* printer,
192                                        const grpc_generator::Method* method,
193                                        const Parameters& params,
194                                        std::map<std::string, std::string>* vars,
195                                        bool is_public) {
196   (*vars)["Method"] = method->name();
197   (*vars)["Request"] = method->input_type_name();
198   (*vars)["Response"] = method->output_type_name();
199 
200   struct {
201     std::string prefix;
202     std::string method_params;  // extra arguments to method
203     std::string raw_args;       // extra arguments to raw version of method
204   } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
205                         {"PrepareAsync", "", ""}};
206 
207   if (is_public) {
208     if (method->NoStreaming()) {
209       printer->Print(
210           *vars,
211           "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
212           "const $Request$& request, $Response$* response) = 0;\n");
213       if (params.allow_cq_api) {
214         for (const auto& async_prefix : async_prefixes) {
215           (*vars)["AsyncPrefix"] = async_prefix.prefix;
216           printer->Print(
217               *vars,
218               "std::unique_ptr< "
219               "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
220               "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
221               "const $Request$& request, "
222               "::grpc::CompletionQueue* cq) {\n");
223           printer->Indent();
224           printer->Print(
225               *vars,
226               "return std::unique_ptr< "
227               "::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
228               "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
229           printer->Outdent();
230           printer->Print("}\n");
231         }
232       }
233     } else if (ClientOnlyStreaming(method)) {
234       printer->Print(
235           *vars,
236           "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
237           " $Method$("
238           "::grpc::ClientContext* context, $Response$* response) {\n");
239       printer->Indent();
240       printer->Print(
241           *vars,
242           "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
243           "($Method$Raw(context, response));\n");
244       printer->Outdent();
245       printer->Print("}\n");
246       if (params.allow_cq_api) {
247         for (const auto& async_prefix : async_prefixes) {
248           (*vars)["AsyncPrefix"] = async_prefix.prefix;
249           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
250           (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
251           printer->Print(
252               *vars,
253               "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
254               " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
255               "$Response$* "
256               "response, "
257               "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
258           printer->Indent();
259           printer->Print(*vars,
260                          "return std::unique_ptr< "
261                          "::grpc::ClientAsyncWriterInterface< $Request$>>("
262                          "$AsyncPrefix$$Method$Raw(context, response, "
263                          "cq$AsyncRawArgs$));\n");
264           printer->Outdent();
265           printer->Print("}\n");
266         }
267       }
268     } else if (ServerOnlyStreaming(method)) {
269       printer->Print(
270           *vars,
271           "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
272           " $Method$(::grpc::ClientContext* context, const $Request$& request)"
273           " {\n");
274       printer->Indent();
275       printer->Print(
276           *vars,
277           "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
278           "($Method$Raw(context, request));\n");
279       printer->Outdent();
280       printer->Print("}\n");
281       if (params.allow_cq_api) {
282         for (const auto& async_prefix : async_prefixes) {
283           (*vars)["AsyncPrefix"] = async_prefix.prefix;
284           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
285           (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
286           printer->Print(
287               *vars,
288               "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< "
289               "$Response$>> "
290               "$AsyncPrefix$$Method$("
291               "::grpc::ClientContext* context, const $Request$& request, "
292               "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
293           printer->Indent();
294           printer->Print(*vars,
295                          "return std::unique_ptr< "
296                          "::grpc::ClientAsyncReaderInterface< $Response$>>("
297                          "$AsyncPrefix$$Method$Raw(context, request, "
298                          "cq$AsyncRawArgs$));\n");
299           printer->Outdent();
300           printer->Print("}\n");
301         }
302       }
303     } else if (method->BidiStreaming()) {
304       printer->Print(*vars,
305                      "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
306                      "$Request$, $Response$>> "
307                      "$Method$(::grpc::ClientContext* context) {\n");
308       printer->Indent();
309       printer->Print(
310           *vars,
311           "return std::unique_ptr< "
312           "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
313           "$Method$Raw(context));\n");
314       printer->Outdent();
315       printer->Print("}\n");
316       if (params.allow_cq_api) {
317         for (const auto& async_prefix : async_prefixes) {
318           (*vars)["AsyncPrefix"] = async_prefix.prefix;
319           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
320           (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
321           printer->Print(
322               *vars,
323               "std::unique_ptr< "
324               "::grpc::ClientAsyncReaderWriterInterface< $Request$, "
325               "$Response$>> "
326               "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
327               "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
328           printer->Indent();
329           printer->Print(
330               *vars,
331               "return std::unique_ptr< "
332               "::grpc::ClientAsyncReaderWriterInterface< $Request$, "
333               "$Response$>>("
334               "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
335           printer->Outdent();
336           printer->Print("}\n");
337         }
338       }
339     }
340   } else {
341     if (method->NoStreaming()) {
342       if (params.allow_cq_api) {
343         for (const auto& async_prefix : async_prefixes) {
344           (*vars)["AsyncPrefix"] = async_prefix.prefix;
345           printer->Print(
346               *vars,
347               "virtual ::grpc::ClientAsyncResponseReaderInterface< "
348               "$Response$>* "
349               "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
350               "const $Request$& request, "
351               "::grpc::CompletionQueue* cq) = 0;\n");
352         }
353       }
354     } else if (ClientOnlyStreaming(method)) {
355       printer->Print(
356           *vars,
357           "virtual ::grpc::ClientWriterInterface< $Request$>*"
358           " $Method$Raw("
359           "::grpc::ClientContext* context, $Response$* response) = 0;\n");
360       if (params.allow_cq_api) {
361         for (const auto& async_prefix : async_prefixes) {
362           (*vars)["AsyncPrefix"] = async_prefix.prefix;
363           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
364           printer->Print(
365               *vars,
366               "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
367               " $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
368               "$Response$* response, "
369               "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
370         }
371       }
372     } else if (ServerOnlyStreaming(method)) {
373       printer->Print(
374           *vars,
375           "virtual ::grpc::ClientReaderInterface< $Response$>* "
376           "$Method$Raw("
377           "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
378       if (params.allow_cq_api) {
379         for (const auto& async_prefix : async_prefixes) {
380           (*vars)["AsyncPrefix"] = async_prefix.prefix;
381           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
382           printer->Print(
383               *vars,
384               "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
385               "$AsyncPrefix$$Method$Raw("
386               "::grpc::ClientContext* context, const $Request$& request, "
387               "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
388         }
389       }
390     } else if (method->BidiStreaming()) {
391       printer->Print(*vars,
392                      "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
393                      "$Response$>* "
394                      "$Method$Raw(::grpc::ClientContext* context) = 0;\n");
395       if (params.allow_cq_api) {
396         for (const auto& async_prefix : async_prefixes) {
397           (*vars)["AsyncPrefix"] = async_prefix.prefix;
398           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
399           printer->Print(
400               *vars,
401               "virtual ::grpc::ClientAsyncReaderWriterInterface< "
402               "$Request$, $Response$>* "
403               "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
404               "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
405         }
406       }
407     }
408   }
409 }
410 
PrintHeaderClientMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars,bool is_public)411 void PrintHeaderClientMethod(grpc_generator::Printer* printer,
412                              const grpc_generator::Method* method,
413                              const Parameters& params,
414                              std::map<std::string, std::string>* vars,
415                              bool is_public) {
416   (*vars)["Method"] = method->name();
417   (*vars)["Request"] = method->input_type_name();
418   (*vars)["Response"] = method->output_type_name();
419   struct {
420     std::string prefix;
421     std::string method_params;  // extra arguments to method
422     std::string raw_args;       // extra arguments to raw version of method
423   } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
424                         {"PrepareAsync", "", ""}};
425 
426   if (is_public) {
427     if (method->NoStreaming()) {
428       printer->Print(
429           *vars,
430           "::grpc::Status $Method$(::grpc::ClientContext* context, "
431           "const $Request$& request, $Response$* response) override;\n");
432       if (params.allow_cq_api) {
433         for (const auto& async_prefix : async_prefixes) {
434           (*vars)["AsyncPrefix"] = async_prefix.prefix;
435           printer->Print(
436               *vars,
437               "std::unique_ptr< ::grpc::ClientAsyncResponseReader< "
438               "$Response$>> "
439               "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
440               "const $Request$& request, "
441               "::grpc::CompletionQueue* cq) {\n");
442           printer->Indent();
443           printer->Print(*vars,
444                          "return std::unique_ptr< "
445                          "::grpc::ClientAsyncResponseReader< $Response$>>("
446                          "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
447           printer->Outdent();
448           printer->Print("}\n");
449         }
450       }
451     } else if (ClientOnlyStreaming(method)) {
452       printer->Print(
453           *vars,
454           "std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
455           " $Method$("
456           "::grpc::ClientContext* context, $Response$* response) {\n");
457       printer->Indent();
458       printer->Print(*vars,
459                      "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
460                      "($Method$Raw(context, response));\n");
461       printer->Outdent();
462       printer->Print("}\n");
463       if (params.allow_cq_api) {
464         for (const auto& async_prefix : async_prefixes) {
465           (*vars)["AsyncPrefix"] = async_prefix.prefix;
466           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
467           (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
468           printer->Print(
469               *vars,
470               "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
471               " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
472               "$Response$* response, "
473               "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
474           printer->Indent();
475           printer->Print(
476               *vars,
477               "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
478               "$AsyncPrefix$$Method$Raw(context, response, "
479               "cq$AsyncRawArgs$));\n");
480           printer->Outdent();
481           printer->Print("}\n");
482         }
483       }
484     } else if (ServerOnlyStreaming(method)) {
485       printer->Print(
486           *vars,
487           "std::unique_ptr< ::grpc::ClientReader< $Response$>>"
488           " $Method$(::grpc::ClientContext* context, const $Request$& request)"
489           " {\n");
490       printer->Indent();
491       printer->Print(
492           *vars,
493           "return std::unique_ptr< ::grpc::ClientReader< $Response$>>"
494           "($Method$Raw(context, request));\n");
495       printer->Outdent();
496       printer->Print("}\n");
497       if (params.allow_cq_api) {
498         for (const auto& async_prefix : async_prefixes) {
499           (*vars)["AsyncPrefix"] = async_prefix.prefix;
500           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
501           (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
502           printer->Print(
503               *vars,
504               "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
505               "$AsyncPrefix$$Method$("
506               "::grpc::ClientContext* context, const $Request$& request, "
507               "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
508           printer->Indent();
509           printer->Print(
510               *vars,
511               "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
512               "$AsyncPrefix$$Method$Raw(context, request, "
513               "cq$AsyncRawArgs$));\n");
514           printer->Outdent();
515           printer->Print("}\n");
516         }
517       }
518     } else if (method->BidiStreaming()) {
519       printer->Print(
520           *vars,
521           "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
522           " $Method$(::grpc::ClientContext* context) {\n");
523       printer->Indent();
524       printer->Print(*vars,
525                      "return std::unique_ptr< "
526                      "::grpc::ClientReaderWriter< $Request$, $Response$>>("
527                      "$Method$Raw(context));\n");
528       printer->Outdent();
529       printer->Print("}\n");
530       if (params.allow_cq_api) {
531         for (const auto& async_prefix : async_prefixes) {
532           (*vars)["AsyncPrefix"] = async_prefix.prefix;
533           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
534           (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
535           printer->Print(
536               *vars,
537               "std::unique_ptr<  ::grpc::ClientAsyncReaderWriter< "
538               "$Request$, $Response$>> "
539               "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
540               "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
541           printer->Indent();
542           printer->Print(
543               *vars,
544               "return std::unique_ptr< "
545               "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
546               "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
547           printer->Outdent();
548           printer->Print("}\n");
549         }
550       }
551     }
552   } else {
553     if (method->NoStreaming()) {
554       if (params.allow_cq_api) {
555         for (const auto& async_prefix : async_prefixes) {
556           (*vars)["AsyncPrefix"] = async_prefix.prefix;
557           printer->Print(
558               *vars,
559               "::grpc::ClientAsyncResponseReader< $Response$>* "
560               "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
561               "const $Request$& request, "
562               "::grpc::CompletionQueue* cq) override;\n");
563         }
564       }
565     } else if (ClientOnlyStreaming(method)) {
566       printer->Print(*vars,
567                      "::grpc::ClientWriter< $Request$>* $Method$Raw("
568                      "::grpc::ClientContext* context, $Response$* response) "
569                      "override;\n");
570       if (params.allow_cq_api) {
571         for (const auto& async_prefix : async_prefixes) {
572           (*vars)["AsyncPrefix"] = async_prefix.prefix;
573           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
574           (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
575           printer->Print(
576               *vars,
577               "::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
578               "::grpc::ClientContext* context, $Response$* response, "
579               "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
580         }
581       }
582     } else if (ServerOnlyStreaming(method)) {
583       printer->Print(*vars,
584                      "::grpc::ClientReader< $Response$>* $Method$Raw("
585                      "::grpc::ClientContext* context, const $Request$& request)"
586                      " override;\n");
587       if (params.allow_cq_api) {
588         for (const auto& async_prefix : async_prefixes) {
589           (*vars)["AsyncPrefix"] = async_prefix.prefix;
590           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
591           (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
592           printer->Print(
593               *vars,
594               "::grpc::ClientAsyncReader< $Response$>* "
595               "$AsyncPrefix$$Method$Raw("
596               "::grpc::ClientContext* context, const $Request$& request, "
597               "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
598         }
599       }
600     } else if (method->BidiStreaming()) {
601       printer->Print(*vars,
602                      "::grpc::ClientReaderWriter< $Request$, $Response$>* "
603                      "$Method$Raw(::grpc::ClientContext* context) override;\n");
604       if (params.allow_cq_api) {
605         for (const auto& async_prefix : async_prefixes) {
606           (*vars)["AsyncPrefix"] = async_prefix.prefix;
607           (*vars)["AsyncMethodParams"] = async_prefix.method_params;
608           (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
609           printer->Print(
610               *vars,
611               "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
612               "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
613               "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
614         }
615       }
616     }
617   }
618 }
619 
PrintHeaderClientMethodCallbackInterfacesStart(grpc_generator::Printer * printer,std::map<std::string,std::string> *)620 void PrintHeaderClientMethodCallbackInterfacesStart(
621     grpc_generator::Printer* printer,
622     std::map<std::string, std::string>* /*vars*/) {
623   // This declares the interface for the callback-based API. The components
624   // are pure; even though this is new (post-1.0) API, it can be pure because
625   // it is an entirely new interface that happens to be scoped within
626   // StubInterface, not new additions to StubInterface itself
627   printer->Print("class async_interface {\n");
628   // All methods in this new interface are public. There is no need for private
629   // "Raw" methods since the callback-based API returns unowned raw pointers
630   printer->Print(" public:\n");
631   printer->Indent();
632   printer->Print("virtual ~async_interface() {}\n");
633 }
634 
PrintHeaderClientMethodCallbackInterfaces(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)635 void PrintHeaderClientMethodCallbackInterfaces(
636     grpc_generator::Printer* printer, const grpc_generator::Method* method,
637     std::map<std::string, std::string>* vars) {
638   (*vars)["Method"] = method->name();
639   (*vars)["Request"] = method->input_type_name();
640   (*vars)["Response"] = method->output_type_name();
641 
642   if (method->NoStreaming()) {
643     printer->Print(*vars,
644                    "virtual void $Method$(::grpc::ClientContext* context, "
645                    "const $Request$* request, $Response$* response, "
646                    "std::function<void(::grpc::Status)>) = 0;\n");
647     printer->Print(*vars,
648                    "virtual void $Method$(::grpc::ClientContext* context, "
649                    "const $Request$* request, $Response$* response, "
650                    "::grpc::ClientUnaryReactor* reactor) = 0;\n");
651   } else if (ClientOnlyStreaming(method)) {
652     printer->Print(*vars,
653                    "virtual void $Method$(::grpc::ClientContext* context, "
654                    "$Response$* response, "
655                    "::grpc::ClientWriteReactor< $Request$>* "
656                    "reactor) = 0;\n");
657   } else if (ServerOnlyStreaming(method)) {
658     printer->Print(*vars,
659                    "virtual void $Method$(::grpc::ClientContext* context, "
660                    "const $Request$* request, "
661                    "::grpc::ClientReadReactor< $Response$>* "
662                    "reactor) = 0;\n");
663   } else if (method->BidiStreaming()) {
664     printer->Print(*vars,
665                    "virtual void $Method$(::grpc::ClientContext* context, "
666                    "::grpc::ClientBidiReactor< "
667                    "$Request$,$Response$>* reactor) = 0;\n");
668   }
669 }
670 
PrintHeaderClientMethodCallbackInterfacesEnd(grpc_generator::Printer * printer,std::map<std::string,std::string> *)671 void PrintHeaderClientMethodCallbackInterfacesEnd(
672     grpc_generator::Printer* printer,
673     std::map<std::string, std::string>* /*vars*/) {
674   printer->Outdent();
675   printer->Print("};\n");
676   // TODO: Remove typedef when all uses of experimental_async are migrated off.
677   printer->Print(
678       "typedef class async_interface experimental_async_interface;\n");
679 
680   // Declare a function to give the async stub contents. It can't be pure
681   // since this is a new API in StubInterface, but it is meaningless by default
682   // (since any stub that wants to use it must have its own implementation of
683   // the callback functions therein), so make the default return value nullptr.
684   // Intentionally include the word "class" to avoid possible shadowing.
685   // TODO: Remove experimental_async call when possible, replace with nullptr.
686   printer->Print(
687       "virtual class async_interface* async() { return nullptr; }\n");
688 
689   // TODO: Remove experimental_async call when possible.
690   printer->Print(
691       "class async_interface* experimental_async() { return async(); }\n");
692 }
693 
PrintHeaderClientMethodCallbackStart(grpc_generator::Printer * printer,std::map<std::string,std::string> *)694 void PrintHeaderClientMethodCallbackStart(
695     grpc_generator::Printer* printer,
696     std::map<std::string, std::string>* /*vars*/) {
697   // This declares the stub entry for the callback-based API.
698   printer->Print("class async final :\n");
699   printer->Print("  public StubInterface::async_interface {\n");
700   printer->Print(" public:\n");
701   printer->Indent();
702 }
703 
PrintHeaderClientMethodCallback(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)704 void PrintHeaderClientMethodCallback(grpc_generator::Printer* printer,
705                                      const grpc_generator::Method* method,
706                                      std::map<std::string, std::string>* vars) {
707   (*vars)["Method"] = method->name();
708   (*vars)["Request"] = method->input_type_name();
709   (*vars)["Response"] = method->output_type_name();
710 
711   if (method->NoStreaming()) {
712     printer->Print(*vars,
713                    "void $Method$(::grpc::ClientContext* context, "
714                    "const $Request$* request, $Response$* response, "
715                    "std::function<void(::grpc::Status)>) override;\n");
716     printer->Print(*vars,
717                    "void $Method$(::grpc::ClientContext* context, "
718                    "const $Request$* request, $Response$* response, "
719                    "::grpc::ClientUnaryReactor* reactor) override;\n");
720   } else if (ClientOnlyStreaming(method)) {
721     printer->Print(*vars,
722                    "void $Method$(::grpc::ClientContext* context, "
723                    "$Response$* response, "
724                    "::grpc::ClientWriteReactor< $Request$>* "
725                    "reactor) override;\n");
726   } else if (ServerOnlyStreaming(method)) {
727     printer->Print(*vars,
728                    "void $Method$(::grpc::ClientContext* context, "
729                    "const $Request$* request, "
730                    "::grpc::ClientReadReactor< $Response$>* "
731                    "reactor) override;\n");
732 
733   } else if (method->BidiStreaming()) {
734     printer->Print(*vars,
735                    "void $Method$(::grpc::ClientContext* context, "
736                    "::grpc::ClientBidiReactor< "
737                    "$Request$,$Response$>* reactor) override;\n");
738   }
739 }
740 
PrintHeaderClientMethodCallbackEnd(grpc_generator::Printer * printer,std::map<std::string,std::string> *)741 void PrintHeaderClientMethodCallbackEnd(
742     grpc_generator::Printer* printer,
743     std::map<std::string, std::string>* /*vars*/) {
744   printer->Outdent();
745   printer->Print(" private:\n");
746   printer->Indent();
747   printer->Print("friend class Stub;\n");
748   printer->Print("explicit async(Stub* stub): stub_(stub) { }\n");
749   // include a function with a phony use of stub_ to avoid an unused
750   // private member warning for service with no methods
751   printer->Print("Stub* stub() { return stub_; }\n");
752   printer->Print("Stub* stub_;\n");
753   printer->Outdent();
754   printer->Print("};\n");
755 
756   printer->Print(
757       "class async* async() override { "
758       "return &async_stub_; }\n");
759 }
760 
PrintHeaderClientMethodData(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)761 void PrintHeaderClientMethodData(grpc_generator::Printer* printer,
762                                  const grpc_generator::Method* method,
763                                  std::map<std::string, std::string>* vars) {
764   (*vars)["Method"] = method->name();
765   printer->Print(*vars,
766                  "const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
767 }
768 
PrintHeaderServerMethodSync(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars)769 void PrintHeaderServerMethodSync(grpc_generator::Printer* printer,
770                                  const grpc_generator::Method* method,
771                                  const Parameters& params,
772                                  std::map<std::string, std::string>* vars) {
773   (*vars)["Method"] = method->name();
774   (*vars)["Request"] = method->input_type_name();
775   (*vars)["Response"] = method->output_type_name();
776   printer->Print(method->GetLeadingComments("//").c_str());
777   if (params.allow_sync_server_api) {
778     printer->Print("virtual ");
779   }
780   if (method->NoStreaming()) {
781     printer->Print(*vars,
782                    "::grpc::Status $Method$("
783                    "::grpc::ServerContext* context, const $Request$* request, "
784                    "$Response$* response);\n");
785   } else if (ClientOnlyStreaming(method)) {
786     printer->Print(*vars,
787                    "::grpc::Status $Method$("
788                    "::grpc::ServerContext* context, "
789                    "::grpc::ServerReader< $Request$>* reader, "
790                    "$Response$* response);\n");
791   } else if (ServerOnlyStreaming(method)) {
792     printer->Print(*vars,
793                    "::grpc::Status $Method$("
794                    "::grpc::ServerContext* context, const $Request$* request, "
795                    "::grpc::ServerWriter< $Response$>* writer);\n");
796   } else if (method->BidiStreaming()) {
797     printer->Print(
798         *vars,
799         "::grpc::Status $Method$("
800         "::grpc::ServerContext* context, "
801         "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
802         "\n");
803   }
804   printer->Print(method->GetTrailingComments("//").c_str());
805 }
806 
807 // Helper generator. Disables the sync API for Request and Response, then adds
808 // in an async API for RealRequest and RealResponse types. This is to be used
809 // to generate async and raw async APIs.
PrintHeaderServerAsyncMethodsHelper(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars)810 void PrintHeaderServerAsyncMethodsHelper(
811     grpc_generator::Printer* printer, const grpc_generator::Method* method,
812     const Parameters& params, std::map<std::string, std::string>* vars) {
813   if (method->NoStreaming()) {
814     if (params.allow_sync_server_api) {
815       printer->Print(
816           *vars,
817           "// disable synchronous version of this method\n"
818           "::grpc::Status $Method$("
819           "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
820           "$Response$* /*response*/) override {\n"
821           "  abort();\n"
822           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
823           "}\n");
824     }
825     printer->Print(
826         *vars,
827         "void Request$Method$("
828         "::grpc::ServerContext* context, $RealRequest$* request, "
829         "::grpc::ServerAsyncResponseWriter< $RealResponse$>* response, "
830         "::grpc::CompletionQueue* new_call_cq, "
831         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
832     printer->Print(*vars,
833                    "  ::grpc::Service::RequestAsyncUnary($Idx$, context, "
834                    "request, response, new_call_cq, notification_cq, tag);\n");
835     printer->Print("}\n");
836   } else if (ClientOnlyStreaming(method)) {
837     if (params.allow_sync_server_api) {
838       printer->Print(
839           *vars,
840           "// disable synchronous version of this method\n"
841           "::grpc::Status $Method$("
842           "::grpc::ServerContext* /*context*/, "
843           "::grpc::ServerReader< $Request$>* /*reader*/, "
844           "$Response$* /*response*/) override {\n"
845           "  abort();\n"
846           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
847           "}\n");
848     }
849     printer->Print(
850         *vars,
851         "void Request$Method$("
852         "::grpc::ServerContext* context, "
853         "::grpc::ServerAsyncReader< $RealResponse$, $RealRequest$>* reader, "
854         "::grpc::CompletionQueue* new_call_cq, "
855         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
856     printer->Print(*vars,
857                    "  ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
858                    "context, reader, new_call_cq, notification_cq, tag);\n");
859     printer->Print("}\n");
860   } else if (ServerOnlyStreaming(method)) {
861     if (params.allow_sync_server_api) {
862       printer->Print(
863           *vars,
864           "// disable synchronous version of this method\n"
865           "::grpc::Status $Method$("
866           "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
867           "::grpc::ServerWriter< $Response$>* /*writer*/) override "
868           "{\n"
869           "  abort();\n"
870           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
871           "}\n");
872     }
873     printer->Print(
874         *vars,
875         "void Request$Method$("
876         "::grpc::ServerContext* context, $RealRequest$* request, "
877         "::grpc::ServerAsyncWriter< $RealResponse$>* writer, "
878         "::grpc::CompletionQueue* new_call_cq, "
879         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
880     printer->Print(
881         *vars,
882         "  ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
883         "context, request, writer, new_call_cq, notification_cq, tag);\n");
884     printer->Print("}\n");
885   } else if (method->BidiStreaming()) {
886     if (params.allow_sync_server_api) {
887       printer->Print(
888           *vars,
889           "// disable synchronous version of this method\n"
890           "::grpc::Status $Method$("
891           "::grpc::ServerContext* /*context*/, "
892           "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
893           " override {\n"
894           "  abort();\n"
895           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
896           "}\n");
897     }
898     printer->Print(
899         *vars,
900         "void Request$Method$("
901         "::grpc::ServerContext* context, "
902         "::grpc::ServerAsyncReaderWriter< $RealResponse$, $RealRequest$>* "
903         "stream, "
904         "::grpc::CompletionQueue* new_call_cq, "
905         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
906     printer->Print(*vars,
907                    "  ::grpc::Service::RequestAsyncBidiStreaming($Idx$, "
908                    "context, stream, new_call_cq, notification_cq, tag);\n");
909     printer->Print("}\n");
910   }
911 }
912 
PrintHeaderServerMethodAsync(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars)913 void PrintHeaderServerMethodAsync(grpc_generator::Printer* printer,
914                                   const grpc_generator::Method* method,
915                                   const Parameters& params,
916                                   std::map<std::string, std::string>* vars) {
917   (*vars)["Method"] = method->name();
918   // These will be disabled
919   (*vars)["Request"] = method->input_type_name();
920   (*vars)["Response"] = method->output_type_name();
921   // These will be used for the async API
922   (*vars)["RealRequest"] = method->input_type_name();
923   (*vars)["RealResponse"] = method->output_type_name();
924   printer->Print(*vars, "template <class BaseClass>\n");
925   printer->Print(*vars,
926                  "class WithAsyncMethod_$Method$ : public BaseClass {\n");
927   printer->Print(
928       " private:\n"
929       "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
930       "{}\n");
931   printer->Print(" public:\n");
932   printer->Indent();
933   printer->Print(*vars,
934                  "WithAsyncMethod_$Method$() {\n"
935                  "  ::grpc::Service::MarkMethodAsync($Idx$);\n"
936                  "}\n");
937   printer->Print(*vars,
938                  "~WithAsyncMethod_$Method$() override {\n"
939                  "  BaseClassMustBeDerivedFromService(this);\n"
940                  "}\n");
941   PrintHeaderServerAsyncMethodsHelper(printer, method, params, vars);
942   printer->Outdent();
943   printer->Print(*vars, "};\n");
944 }
945 
946 // Helper generator. Disables the sync API for Request and Response, then adds
947 // in a callback API for RealRequest and RealResponse types. This is to be used
948 // to generate callback and raw callback APIs.
PrintHeaderServerCallbackMethodsHelper(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars)949 void PrintHeaderServerCallbackMethodsHelper(
950     grpc_generator::Printer* printer, const grpc_generator::Method* method,
951     const Parameters& params, std::map<std::string, std::string>* vars) {
952   if (method->NoStreaming()) {
953     if (params.allow_sync_server_api) {
954       printer->Print(
955           *vars,
956           "// disable synchronous version of this method\n"
957           "::grpc::Status $Method$("
958           "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
959           "$Response$* /*response*/) override {\n"
960           "  abort();\n"
961           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
962           "}\n");
963     }
964     printer->Print(*vars,
965                    "virtual ::grpc::ServerUnaryReactor* $Method$(\n"
966                    "  ::grpc::CallbackServerContext* /*context*/, "
967                    "const $RealRequest$* /*request*/, "
968                    "$RealResponse$* /*response*/)"
969                    "  { return nullptr; }\n");
970   } else if (ClientOnlyStreaming(method)) {
971     if (params.allow_sync_server_api) {
972       printer->Print(
973           *vars,
974           "// disable synchronous version of this method\n"
975           "::grpc::Status $Method$("
976           "::grpc::ServerContext* /*context*/, "
977           "::grpc::ServerReader< $Request$>* /*reader*/, "
978           "$Response$* /*response*/) override {\n"
979           "  abort();\n"
980           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
981           "}\n");
982     }
983     printer->Print(*vars,
984                    "virtual ::grpc::ServerReadReactor< "
985                    "$RealRequest$>* $Method$(\n"
986                    "  ::grpc::CallbackServerContext* "
987                    "/*context*/, $RealResponse$* /*response*/)"
988                    "  { return nullptr; }\n");
989   } else if (ServerOnlyStreaming(method)) {
990     if (params.allow_sync_server_api) {
991       printer->Print(
992           *vars,
993           "// disable synchronous version of this method\n"
994           "::grpc::Status $Method$("
995           "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
996           "::grpc::ServerWriter< $Response$>* /*writer*/) override "
997           "{\n"
998           "  abort();\n"
999           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1000           "}\n");
1001     }
1002     printer->Print(
1003         *vars,
1004         "virtual ::grpc::ServerWriteReactor< $RealResponse$>* $Method$(\n"
1005         "  ::grpc::CallbackServerContext* "
1006         "/*context*/, const $RealRequest$* /*request*/)"
1007         "  { return nullptr; }\n");
1008   } else if (method->BidiStreaming()) {
1009     if (params.allow_sync_server_api) {
1010       printer->Print(
1011           *vars,
1012           "// disable synchronous version of this method\n"
1013           "::grpc::Status $Method$("
1014           "::grpc::ServerContext* /*context*/, "
1015           "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
1016           " override {\n"
1017           "  abort();\n"
1018           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1019           "}\n");
1020     }
1021     printer->Print(
1022         *vars,
1023         "virtual ::grpc::ServerBidiReactor< $RealRequest$, $RealResponse$>* "
1024         "$Method$(\n"
1025         "  ::grpc::CallbackServerContext* /*context*/)\n"
1026         "  { return nullptr; }\n");
1027   }
1028 }
1029 
PrintHeaderServerMethodCallback(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars)1030 void PrintHeaderServerMethodCallback(grpc_generator::Printer* printer,
1031                                      const grpc_generator::Method* method,
1032                                      const Parameters& params,
1033                                      std::map<std::string, std::string>* vars) {
1034   (*vars)["Method"] = method->name();
1035   // These will be disabled
1036   (*vars)["Request"] = method->input_type_name();
1037   (*vars)["Response"] = method->output_type_name();
1038   // These will be used for the callback API
1039   (*vars)["RealRequest"] = method->input_type_name();
1040   (*vars)["RealResponse"] = method->output_type_name();
1041   printer->Print(*vars, "template <class BaseClass>\n");
1042   printer->Print(*vars,
1043                  "class WithCallbackMethod_$Method$ : public BaseClass {\n");
1044   printer->Print(
1045       " private:\n"
1046       "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1047       "{}\n");
1048   printer->Print(" public:\n");
1049   printer->Indent();
1050   printer->Print(*vars, "WithCallbackMethod_$Method$() {\n");
1051   if (method->NoStreaming()) {
1052     printer->Print(
1053         *vars,
1054         "  ::grpc::Service::MarkMethodCallback($Idx$,\n"
1055         "      new ::grpc::internal::CallbackUnaryHandler< "
1056         "$RealRequest$, $RealResponse$>(\n"
1057         "        [this](\n"
1058         "               ::grpc::CallbackServerContext* context, "
1059         "const $RealRequest$* "
1060         "request, "
1061         "$RealResponse$* response) { "
1062         "return this->$Method$(context, request, response); }));}\n");
1063     printer->Print(*vars,
1064                    "void SetMessageAllocatorFor_$Method$(\n"
1065                    "    ::grpc::MessageAllocator< "
1066                    "$RealRequest$, $RealResponse$>* allocator) {\n"
1067                    "  ::grpc::internal::MethodHandler* const handler = "
1068                    "::grpc::Service::GetHandler($Idx$);\n"
1069                    "  static_cast<::grpc::internal::CallbackUnaryHandler< "
1070                    "$RealRequest$, $RealResponse$>*>(handler)\n"
1071                    "          ->SetMessageAllocator(allocator);\n");
1072   } else if (ClientOnlyStreaming(method)) {
1073     printer->Print(
1074         *vars,
1075         "  ::grpc::Service::MarkMethodCallback($Idx$,\n"
1076         "      new ::grpc::internal::CallbackClientStreamingHandler< "
1077         "$RealRequest$, $RealResponse$>(\n"
1078         "        [this](\n"
1079         "               ::grpc::CallbackServerContext* context, "
1080         "$RealResponse$* "
1081         "response) { "
1082         "return this->$Method$(context, response); }));\n");
1083   } else if (ServerOnlyStreaming(method)) {
1084     printer->Print(
1085         *vars,
1086         "  ::grpc::Service::MarkMethodCallback($Idx$,\n"
1087         "      new ::grpc::internal::CallbackServerStreamingHandler< "
1088         "$RealRequest$, $RealResponse$>(\n"
1089         "        [this](\n"
1090         "               ::grpc::CallbackServerContext* context, "
1091         "const $RealRequest$* "
1092         "request) { "
1093         "return this->$Method$(context, request); }));\n");
1094   } else if (method->BidiStreaming()) {
1095     printer->Print(*vars,
1096                    "  ::grpc::Service::MarkMethodCallback($Idx$,\n"
1097                    "      new ::grpc::internal::CallbackBidiHandler< "
1098                    "$RealRequest$, $RealResponse$>(\n"
1099                    "        [this](\n"
1100                    "               ::grpc::CallbackServerContext* context) "
1101                    "{ return this->$Method$(context); }));\n");
1102   }
1103   printer->Print(*vars, "}\n");
1104   printer->Print(*vars,
1105                  "~WithCallbackMethod_$Method$() override {\n"
1106                  "  BaseClassMustBeDerivedFromService(this);\n"
1107                  "}\n");
1108   PrintHeaderServerCallbackMethodsHelper(printer, method, params, vars);
1109   printer->Outdent();
1110   printer->Print(*vars, "};\n");
1111 }
1112 
PrintHeaderServerMethodRawCallback(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars)1113 void PrintHeaderServerMethodRawCallback(
1114     grpc_generator::Printer* printer, const grpc_generator::Method* method,
1115     const Parameters& params, std::map<std::string, std::string>* vars) {
1116   (*vars)["Method"] = method->name();
1117   // These will be disabled
1118   (*vars)["Request"] = method->input_type_name();
1119   (*vars)["Response"] = method->output_type_name();
1120   // These will be used for raw API
1121   (*vars)["RealRequest"] = "::grpc::ByteBuffer";
1122   (*vars)["RealResponse"] = "::grpc::ByteBuffer";
1123   printer->Print(*vars, "template <class BaseClass>\n");
1124   printer->Print(*vars,
1125                  "class WithRawCallbackMethod_$Method$ : public "
1126                  "BaseClass {\n");
1127   printer->Print(
1128       " private:\n"
1129       "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1130       "{}\n");
1131   printer->Print(" public:\n");
1132   printer->Indent();
1133   printer->Print(*vars, "WithRawCallbackMethod_$Method$() {\n");
1134   if (method->NoStreaming()) {
1135     printer->Print(*vars,
1136                    "  ::grpc::Service::MarkMethodRawCallback($Idx$,\n"
1137                    "      new ::grpc::internal::CallbackUnaryHandler< "
1138                    "$RealRequest$, $RealResponse$>(\n"
1139                    "        [this](\n"
1140                    "               ::grpc::CallbackServerContext* context, "
1141                    "const $RealRequest$* "
1142                    "request, "
1143                    "$RealResponse$* response) { return "
1144                    "this->$Method$(context, request, response); }));\n");
1145   } else if (ClientOnlyStreaming(method)) {
1146     printer->Print(
1147         *vars,
1148         "  ::grpc::Service::MarkMethodRawCallback($Idx$,\n"
1149         "      new ::grpc::internal::CallbackClientStreamingHandler< "
1150         "$RealRequest$, $RealResponse$>(\n"
1151         "        [this](\n"
1152         "               ::grpc::CallbackServerContext* context, "
1153         "$RealResponse$* response) "
1154         "{ return this->$Method$(context, response); }));\n");
1155   } else if (ServerOnlyStreaming(method)) {
1156     printer->Print(
1157         *vars,
1158         "  ::grpc::Service::MarkMethodRawCallback($Idx$,\n"
1159         "      new ::grpc::internal::CallbackServerStreamingHandler< "
1160         "$RealRequest$, $RealResponse$>(\n"
1161         "        [this](\n"
1162         "               ::grpc::CallbackServerContext* context, "
1163         "const"
1164         "$RealRequest$* request) { return "
1165         "this->$Method$(context, request); }));\n");
1166   } else if (method->BidiStreaming()) {
1167     printer->Print(*vars,
1168                    "  ::grpc::Service::MarkMethodRawCallback($Idx$,\n"
1169                    "      new ::grpc::internal::CallbackBidiHandler< "
1170                    "$RealRequest$, $RealResponse$>(\n"
1171                    "        [this](\n"
1172                    "               ::grpc::CallbackServerContext* context) "
1173                    "{ return this->$Method$(context); }));\n");
1174   }
1175   printer->Print(*vars, "}\n");
1176   printer->Print(*vars,
1177                  "~WithRawCallbackMethod_$Method$() override {\n"
1178                  "  BaseClassMustBeDerivedFromService(this);\n"
1179                  "}\n");
1180   PrintHeaderServerCallbackMethodsHelper(printer, method, params, vars);
1181   printer->Outdent();
1182   printer->Print(*vars, "};\n");
1183 }
1184 
PrintHeaderServerMethodStreamedUnary(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)1185 void PrintHeaderServerMethodStreamedUnary(
1186     grpc_generator::Printer* printer, const grpc_generator::Method* method,
1187     std::map<std::string, std::string>* vars) {
1188   (*vars)["Method"] = method->name();
1189   (*vars)["Request"] = method->input_type_name();
1190   (*vars)["Response"] = method->output_type_name();
1191   if (method->NoStreaming()) {
1192     printer->Print(*vars, "template <class BaseClass>\n");
1193     printer->Print(*vars,
1194                    "class WithStreamedUnaryMethod_$Method$ : "
1195                    "public BaseClass {\n");
1196     printer->Print(
1197         " private:\n"
1198         "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1199         "{}\n");
1200     printer->Print(" public:\n");
1201     printer->Indent();
1202     printer->Print(*vars,
1203                    "WithStreamedUnaryMethod_$Method$() {\n"
1204                    "  ::grpc::Service::MarkMethodStreamed($Idx$,\n"
1205                    "    new ::grpc::internal::StreamedUnaryHandler<\n"
1206                    "      $Request$, $Response$>(\n"
1207                    "        [this](::grpc::ServerContext* context,\n"
1208                    "               ::grpc::ServerUnaryStreamer<\n"
1209                    "                 $Request$, $Response$>* streamer) {\n"
1210                    "                   return this->Streamed$Method$(context,\n"
1211                    "                     streamer);\n"
1212                    "              }));\n"
1213                    "}\n");
1214     printer->Print(*vars,
1215                    "~WithStreamedUnaryMethod_$Method$() override {\n"
1216                    "  BaseClassMustBeDerivedFromService(this);\n"
1217                    "}\n");
1218     printer->Print(
1219         *vars,
1220         "// disable regular version of this method\n"
1221         "::grpc::Status $Method$("
1222         "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
1223         "$Response$* /*response*/) override {\n"
1224         "  abort();\n"
1225         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1226         "}\n");
1227     printer->Print(*vars,
1228                    "// replace default version of method with streamed unary\n"
1229                    "virtual ::grpc::Status Streamed$Method$("
1230                    "::grpc::ServerContext* context, "
1231                    "::grpc::ServerUnaryStreamer< "
1232                    "$Request$,$Response$>* server_unary_streamer)"
1233                    " = 0;\n");
1234     printer->Outdent();
1235     printer->Print(*vars, "};\n");
1236   }
1237 }
1238 
PrintHeaderServerMethodSplitStreaming(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)1239 void PrintHeaderServerMethodSplitStreaming(
1240     grpc_generator::Printer* printer, const grpc_generator::Method* method,
1241     std::map<std::string, std::string>* vars) {
1242   (*vars)["Method"] = method->name();
1243   (*vars)["Request"] = method->input_type_name();
1244   (*vars)["Response"] = method->output_type_name();
1245   if (ServerOnlyStreaming(method)) {
1246     printer->Print(*vars, "template <class BaseClass>\n");
1247     printer->Print(*vars,
1248                    "class WithSplitStreamingMethod_$Method$ : "
1249                    "public BaseClass {\n");
1250     printer->Print(
1251         " private:\n"
1252         "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1253         "{}\n");
1254     printer->Print(" public:\n");
1255     printer->Indent();
1256     printer->Print(*vars,
1257                    "WithSplitStreamingMethod_$Method$() {\n"
1258                    "  ::grpc::Service::MarkMethodStreamed($Idx$,\n"
1259                    "    new ::grpc::internal::SplitServerStreamingHandler<\n"
1260                    "      $Request$, $Response$>(\n"
1261                    "        [this](::grpc::ServerContext* context,\n"
1262                    "               ::grpc::ServerSplitStreamer<\n"
1263                    "                 $Request$, $Response$>* streamer) {\n"
1264                    "                   return this->Streamed$Method$(context,\n"
1265                    "                     streamer);\n"
1266                    "              }));\n"
1267                    "}\n");
1268     printer->Print(*vars,
1269                    "~WithSplitStreamingMethod_$Method$() override {\n"
1270                    "  BaseClassMustBeDerivedFromService(this);\n"
1271                    "}\n");
1272     printer->Print(
1273         *vars,
1274         "// disable regular version of this method\n"
1275         "::grpc::Status $Method$("
1276         "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
1277         "::grpc::ServerWriter< $Response$>* /*writer*/) override "
1278         "{\n"
1279         "  abort();\n"
1280         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1281         "}\n");
1282     printer->Print(*vars,
1283                    "// replace default version of method with split streamed\n"
1284                    "virtual ::grpc::Status Streamed$Method$("
1285                    "::grpc::ServerContext* context, "
1286                    "::grpc::ServerSplitStreamer< "
1287                    "$Request$,$Response$>* server_split_streamer)"
1288                    " = 0;\n");
1289     printer->Outdent();
1290     printer->Print(*vars, "};\n");
1291   }
1292 }
1293 
PrintHeaderServerMethodGeneric(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars)1294 void PrintHeaderServerMethodGeneric(grpc_generator::Printer* printer,
1295                                     const grpc_generator::Method* method,
1296                                     const Parameters& params,
1297                                     std::map<std::string, std::string>* vars) {
1298   (*vars)["Method"] = method->name();
1299   (*vars)["Request"] = method->input_type_name();
1300   (*vars)["Response"] = method->output_type_name();
1301   printer->Print(*vars, "template <class BaseClass>\n");
1302   printer->Print(*vars,
1303                  "class WithGenericMethod_$Method$ : public BaseClass {\n");
1304   printer->Print(
1305       " private:\n"
1306       "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1307       "{}\n");
1308   printer->Print(" public:\n");
1309   printer->Indent();
1310   printer->Print(*vars,
1311                  "WithGenericMethod_$Method$() {\n"
1312                  "  ::grpc::Service::MarkMethodGeneric($Idx$);\n"
1313                  "}\n");
1314   printer->Print(*vars,
1315                  "~WithGenericMethod_$Method$() override {\n"
1316                  "  BaseClassMustBeDerivedFromService(this);\n"
1317                  "}\n");
1318   if (params.allow_sync_server_api) {
1319     if (method->NoStreaming()) {
1320       printer->Print(
1321           *vars,
1322           "// disable synchronous version of this method\n"
1323           "::grpc::Status $Method$("
1324           "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
1325           "$Response$* /*response*/) override {\n"
1326           "  abort();\n"
1327           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1328           "}\n");
1329     } else if (ClientOnlyStreaming(method)) {
1330       printer->Print(
1331           *vars,
1332           "// disable synchronous version of this method\n"
1333           "::grpc::Status $Method$("
1334           "::grpc::ServerContext* /*context*/, "
1335           "::grpc::ServerReader< $Request$>* /*reader*/, "
1336           "$Response$* /*response*/) override {\n"
1337           "  abort();\n"
1338           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1339           "}\n");
1340     } else if (ServerOnlyStreaming(method)) {
1341       printer->Print(
1342           *vars,
1343           "// disable synchronous version of this method\n"
1344           "::grpc::Status $Method$("
1345           "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
1346           "::grpc::ServerWriter< $Response$>* /*writer*/) override "
1347           "{\n"
1348           "  abort();\n"
1349           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1350           "}\n");
1351     } else if (method->BidiStreaming()) {
1352       printer->Print(
1353           *vars,
1354           "// disable synchronous version of this method\n"
1355           "::grpc::Status $Method$("
1356           "::grpc::ServerContext* /*context*/, "
1357           "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
1358           " override {\n"
1359           "  abort();\n"
1360           "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1361           "}\n");
1362     }
1363   }
1364   printer->Outdent();
1365   printer->Print(*vars, "};\n");
1366 }
1367 
PrintHeaderServerMethodRaw(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars)1368 void PrintHeaderServerMethodRaw(grpc_generator::Printer* printer,
1369                                 const grpc_generator::Method* method,
1370                                 const Parameters& params,
1371                                 std::map<std::string, std::string>* vars) {
1372   (*vars)["Method"] = method->name();
1373   // These will be disabled
1374   (*vars)["Request"] = method->input_type_name();
1375   (*vars)["Response"] = method->output_type_name();
1376   // These will be used for raw API
1377   (*vars)["RealRequest"] = "::grpc::ByteBuffer";
1378   (*vars)["RealResponse"] = "::grpc::ByteBuffer";
1379   printer->Print(*vars, "template <class BaseClass>\n");
1380   printer->Print(*vars, "class WithRawMethod_$Method$ : public BaseClass {\n");
1381   printer->Print(
1382       " private:\n"
1383       "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1384       "{}\n");
1385   printer->Print(" public:\n");
1386   printer->Indent();
1387   printer->Print(*vars,
1388                  "WithRawMethod_$Method$() {\n"
1389                  "  ::grpc::Service::MarkMethodRaw($Idx$);\n"
1390                  "}\n");
1391   printer->Print(*vars,
1392                  "~WithRawMethod_$Method$() override {\n"
1393                  "  BaseClassMustBeDerivedFromService(this);\n"
1394                  "}\n");
1395   PrintHeaderServerAsyncMethodsHelper(printer, method, params, vars);
1396   printer->Outdent();
1397   printer->Print(*vars, "};\n");
1398 }
1399 
PrintHeaderService(grpc_generator::Printer * printer,const grpc_generator::Service * service,const Parameters & params,std::map<std::string,std::string> * vars)1400 void PrintHeaderService(grpc_generator::Printer* printer,
1401                         const grpc_generator::Service* service,
1402                         const Parameters& params,
1403                         std::map<std::string, std::string>* vars) {
1404   (*vars)["Service"] = service->name();
1405 
1406   printer->Print(service->GetLeadingComments("//").c_str());
1407   printer->Print(*vars,
1408                  "class $Service$ final {\n"
1409                  " public:\n");
1410   printer->Indent();
1411 
1412   // Service metadata
1413   printer->Print(*vars,
1414                  "static constexpr char const* service_full_name() {\n"
1415                  "  return \"$Package$$Service$\";\n"
1416                  "}\n");
1417 
1418   // Client side
1419   printer->Print(
1420       "class StubInterface {\n"
1421       " public:\n");
1422   printer->Indent();
1423   printer->Print("virtual ~StubInterface() {}\n");
1424   for (int i = 0; i < service->method_count(); ++i) {
1425     printer->Print(service->method(i)->GetLeadingComments("//").c_str());
1426     PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), params,
1427                                       vars, true);
1428     printer->Print(service->method(i)->GetTrailingComments("//").c_str());
1429   }
1430   PrintHeaderClientMethodCallbackInterfacesStart(printer, vars);
1431   for (int i = 0; i < service->method_count(); ++i) {
1432     printer->Print(service->method(i)->GetLeadingComments("//").c_str());
1433     PrintHeaderClientMethodCallbackInterfaces(printer, service->method(i).get(),
1434                                               vars);
1435     printer->Print(service->method(i)->GetTrailingComments("//").c_str());
1436   }
1437   PrintHeaderClientMethodCallbackInterfacesEnd(printer, vars);
1438   printer->Outdent();
1439   printer->Print(" private:\n");
1440   printer->Indent();
1441   for (int i = 0; i < service->method_count(); ++i) {
1442     PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), params,
1443                                       vars, false);
1444   }
1445   printer->Outdent();
1446   printer->Print("};\n");
1447   printer->Print(
1448       "class Stub final : public StubInterface"
1449       " {\n public:\n");
1450   printer->Indent();
1451   printer->Print(
1452       "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
1453       "channel, const ::grpc::StubOptions& options = "
1454       "::grpc::StubOptions());\n");
1455   for (int i = 0; i < service->method_count(); ++i) {
1456     PrintHeaderClientMethod(printer, service->method(i).get(), params, vars,
1457                             true);
1458   }
1459   PrintHeaderClientMethodCallbackStart(printer, vars);
1460   for (int i = 0; i < service->method_count(); ++i) {
1461     PrintHeaderClientMethodCallback(printer, service->method(i).get(), vars);
1462   }
1463   PrintHeaderClientMethodCallbackEnd(printer, vars);
1464   printer->Outdent();
1465   printer->Print("\n private:\n");
1466   printer->Indent();
1467   printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
1468   printer->Print("class async async_stub_{this};\n");
1469   for (int i = 0; i < service->method_count(); ++i) {
1470     PrintHeaderClientMethod(printer, service->method(i).get(), params, vars,
1471                             false);
1472   }
1473   for (int i = 0; i < service->method_count(); ++i) {
1474     PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
1475   }
1476   printer->Outdent();
1477   printer->Print("};\n");
1478   printer->Print(
1479       "static std::unique_ptr<Stub> NewStub(const std::shared_ptr< "
1480       "::grpc::ChannelInterface>& channel, "
1481       "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n");
1482 
1483   printer->Print("\n");
1484 
1485   // Server side - base
1486   printer->Print(
1487       "class Service : public ::grpc::Service {\n"
1488       " public:\n");
1489   printer->Indent();
1490   printer->Print("Service();\n");
1491   printer->Print("virtual ~Service();\n");
1492   for (int i = 0; i < service->method_count(); ++i) {
1493     PrintHeaderServerMethodSync(printer, service->method(i).get(), params,
1494                                 vars);
1495   }
1496   printer->Outdent();
1497   printer->Print("};\n");
1498 
1499   if (params.allow_cq_api) {
1500     // Server side - Asynchronous
1501     for (int i = 0; i < service->method_count(); ++i) {
1502       (*vars)["Idx"] = as_string(i);
1503       PrintHeaderServerMethodAsync(printer, service->method(i).get(), params,
1504                                    vars);
1505     }
1506 
1507     printer->Print("typedef ");
1508 
1509     for (int i = 0; i < service->method_count(); ++i) {
1510       (*vars)["method_name"] = service->method(i)->name();
1511       printer->Print(*vars, "WithAsyncMethod_$method_name$<");
1512     }
1513     printer->Print("Service");
1514     for (int i = 0; i < service->method_count(); ++i) {
1515       printer->Print(" >");
1516     }
1517     printer->Print(" AsyncService;\n");
1518   }
1519 
1520   // Server side - Callback
1521   for (int i = 0; i < service->method_count(); ++i) {
1522     (*vars)["Idx"] = as_string(i);
1523     PrintHeaderServerMethodCallback(printer, service->method(i).get(), params,
1524                                     vars);
1525   }
1526 
1527   printer->Print("typedef ");
1528 
1529   for (int i = 0; i < service->method_count(); ++i) {
1530     (*vars)["method_name"] = service->method(i)->name();
1531     printer->Print(*vars, "WithCallbackMethod_$method_name$<");
1532   }
1533   printer->Print("Service");
1534   for (int i = 0; i < service->method_count(); ++i) {
1535     printer->Print(" >");
1536   }
1537   printer->Print(" CallbackService;\n");
1538 
1539   // TODO: Remove following typedef once all uses of ExperimentalCallbackService
1540   //       are migrated to CallbackService
1541   printer->Print("typedef CallbackService ExperimentalCallbackService;\n");
1542 
1543   // Server side - Generic
1544   for (int i = 0; i < service->method_count(); ++i) {
1545     (*vars)["Idx"] = as_string(i);
1546     PrintHeaderServerMethodGeneric(printer, service->method(i).get(), params,
1547                                    vars);
1548   }
1549 
1550   // Server side - Raw Async
1551   if (params.allow_cq_api) {
1552     for (int i = 0; i < service->method_count(); ++i) {
1553       (*vars)["Idx"] = as_string(i);
1554       PrintHeaderServerMethodRaw(printer, service->method(i).get(), params,
1555                                  vars);
1556     }
1557   }
1558 
1559   // Server side - Raw Callback
1560   for (int i = 0; i < service->method_count(); ++i) {
1561     (*vars)["Idx"] = as_string(i);
1562     PrintHeaderServerMethodRawCallback(printer, service->method(i).get(),
1563                                        params, vars);
1564   }
1565 
1566   if (params.allow_sync_server_api) {
1567     // Server side - Streamed Unary
1568     for (int i = 0; i < service->method_count(); ++i) {
1569       (*vars)["Idx"] = as_string(i);
1570       PrintHeaderServerMethodStreamedUnary(printer, service->method(i).get(),
1571                                            vars);
1572     }
1573 
1574     printer->Print("typedef ");
1575     for (int i = 0; i < service->method_count(); ++i) {
1576       (*vars)["method_name"] = service->method(i)->name();
1577       if (service->method(i)->NoStreaming()) {
1578         printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1579       }
1580     }
1581     printer->Print("Service");
1582     for (int i = 0; i < service->method_count(); ++i) {
1583       if (service->method(i)->NoStreaming()) {
1584         printer->Print(" >");
1585       }
1586     }
1587     printer->Print(" StreamedUnaryService;\n");
1588 
1589     // Server side - controlled server-side streaming
1590     for (int i = 0; i < service->method_count(); ++i) {
1591       (*vars)["Idx"] = as_string(i);
1592       PrintHeaderServerMethodSplitStreaming(printer, service->method(i).get(),
1593                                             vars);
1594     }
1595 
1596     printer->Print("typedef ");
1597     for (int i = 0; i < service->method_count(); ++i) {
1598       (*vars)["method_name"] = service->method(i)->name();
1599       auto method = service->method(i);
1600       if (ServerOnlyStreaming(method.get())) {
1601         printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1602       }
1603     }
1604     printer->Print("Service");
1605     for (int i = 0; i < service->method_count(); ++i) {
1606       auto method = service->method(i);
1607       if (ServerOnlyStreaming(method.get())) {
1608         printer->Print(" >");
1609       }
1610     }
1611     printer->Print(" SplitStreamedService;\n");
1612 
1613     // Server side - typedef for controlled both unary and server-side streaming
1614     printer->Print("typedef ");
1615     for (int i = 0; i < service->method_count(); ++i) {
1616       (*vars)["method_name"] = service->method(i)->name();
1617       auto method = service->method(i);
1618       if (ServerOnlyStreaming(method.get())) {
1619         printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1620       }
1621       if (service->method(i)->NoStreaming()) {
1622         printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1623       }
1624     }
1625     printer->Print("Service");
1626     for (int i = 0; i < service->method_count(); ++i) {
1627       auto method = service->method(i);
1628       if (service->method(i)->NoStreaming() ||
1629           ServerOnlyStreaming(method.get())) {
1630         printer->Print(" >");
1631       }
1632     }
1633     printer->Print(" StreamedService;\n");
1634   }
1635 
1636   printer->Outdent();
1637   printer->Print("};\n");
1638   printer->Print(service->GetTrailingComments("//").c_str());
1639 }
1640 
GetHeaderServices(grpc_generator::File * file,const Parameters & params)1641 std::string GetHeaderServices(grpc_generator::File* file,
1642                               const Parameters& params) {
1643   std::string output;
1644   {
1645     // Scope the output stream so it closes and finalizes output to the string.
1646     auto printer = file->CreatePrinter(&output);
1647     std::map<std::string, std::string> vars;
1648     // Package string is empty or ends with a dot. It is used to fully qualify
1649     // method names.
1650     vars["Package"] = file->package();
1651     if (!file->package().empty()) {
1652       vars["Package"].append(".");
1653     }
1654 
1655     if (!params.services_namespace.empty()) {
1656       vars["services_namespace"] = params.services_namespace;
1657       printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
1658     }
1659 
1660     for (int i = 0; i < file->service_count(); ++i) {
1661       PrintHeaderService(printer.get(), file->service(i).get(), params, &vars);
1662       printer->Print("\n");
1663     }
1664 
1665     if (!params.services_namespace.empty()) {
1666       printer->Print(vars, "}  // namespace $services_namespace$\n\n");
1667     }
1668   }
1669   return output;
1670 }
1671 
GetHeaderEpilogue(grpc_generator::File * file,const Parameters &)1672 std::string GetHeaderEpilogue(grpc_generator::File* file,
1673                               const Parameters& /*params*/) {
1674   std::string output;
1675   {
1676     // Scope the output stream so it closes and finalizes output to the string.
1677     auto printer = file->CreatePrinter(&output);
1678     std::map<std::string, std::string> vars;
1679 
1680     vars["filename"] = file->filename();
1681     vars["filename_identifier"] = FilenameIdentifier(file->filename());
1682 
1683     if (!file->package().empty()) {
1684       std::vector<std::string> parts = file->package_parts();
1685 
1686       for (auto part = parts.rbegin(); part != parts.rend(); part++) {
1687         vars["part"] = *part;
1688         printer->Print(vars, "}  // namespace $part$\n");
1689       }
1690       printer->Print(vars, "\n");
1691     }
1692 
1693     printer->Print(vars, "\n");
1694     printer->Print(vars, "#endif  // GRPC_$filename_identifier$__INCLUDED\n");
1695 
1696     printer->Print(file->GetTrailingComments("//").c_str());
1697   }
1698   return output;
1699 }
1700 
GetSourcePrologue(grpc_generator::File * file,const Parameters & params)1701 std::string GetSourcePrologue(grpc_generator::File* file,
1702                               const Parameters& params) {
1703   std::string output;
1704   {
1705     // Scope the output stream so it closes and finalizes output to the string.
1706     auto printer = file->CreatePrinter(&output);
1707     std::map<std::string, std::string> vars;
1708 
1709     vars["filename"] = file->filename();
1710     vars["filename_base"] = file->filename_without_ext();
1711     vars["message_header_ext"] = params.message_header_extension.empty()
1712                                      ? kCppGeneratorMessageHeaderExt
1713                                      : params.message_header_extension;
1714     vars["service_header_ext"] = kCppGeneratorServiceHeaderExt;
1715 
1716     printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
1717     printer->Print(vars,
1718                    "// If you make any local change, they will be lost.\n");
1719     printer->Print(vars, "// source: $filename$\n\n");
1720 
1721     printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
1722     printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
1723     printer->Print(vars, "\n");
1724   }
1725   return output;
1726 }
1727 
GetSourceIncludes(grpc_generator::File * file,const Parameters & params)1728 std::string GetSourceIncludes(grpc_generator::File* file,
1729                               const Parameters& params) {
1730   std::string output;
1731   {
1732     // Scope the output stream so it closes and finalizes output to the string.
1733     auto printer = file->CreatePrinter(&output);
1734     std::map<std::string, std::string> vars;
1735     static const char* headers_strs[] = {
1736         "functional",
1737         "grpcpp/support/async_stream.h",
1738         "grpcpp/support/async_unary_call.h",
1739         "grpcpp/impl/channel_interface.h",
1740         "grpcpp/impl/client_unary_call.h",
1741         "grpcpp/support/client_callback.h",
1742         "grpcpp/support/message_allocator.h",
1743         "grpcpp/support/method_handler.h",
1744         "grpcpp/impl/rpc_service_method.h",
1745         "grpcpp/support/server_callback.h",
1746         "grpcpp/impl/server_callback_handlers.h",
1747         "grpcpp/server_context.h",
1748         "grpcpp/impl/service_type.h",
1749         "grpcpp/support/sync_stream.h"};
1750     std::vector<std::string> headers(headers_strs, array_end(headers_strs));
1751     PrintIncludes(printer.get(), headers, params.use_system_headers,
1752                   params.grpc_search_path);
1753 
1754     if (!file->package().empty()) {
1755       std::vector<std::string> parts = file->package_parts();
1756 
1757       for (auto part = parts.begin(); part != parts.end(); part++) {
1758         vars["part"] = *part;
1759         printer->Print(vars, "namespace $part$ {\n");
1760       }
1761     }
1762 
1763     printer->Print(vars, "\n");
1764   }
1765   return output;
1766 }
1767 
PrintSourceClientMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars)1768 void PrintSourceClientMethod(grpc_generator::Printer* printer,
1769                              const grpc_generator::Method* method,
1770                              const Parameters& params,
1771                              std::map<std::string, std::string>* vars) {
1772   (*vars)["Method"] = method->name();
1773   (*vars)["Request"] = method->input_type_name();
1774   (*vars)["Response"] = method->output_type_name();
1775   struct {
1776     std::string prefix;
1777     std::string start;          // bool literal expressed as string
1778     std::string method_params;  // extra arguments to method
1779     std::string create_args;    // extra arguments to creator
1780   } async_prefixes[] = {{"Async", "true", ", void* tag", ", tag"},
1781                         {"PrepareAsync", "false", "", ", nullptr"}};
1782   if (method->NoStreaming()) {
1783     printer->Print(*vars,
1784                    "::grpc::Status $ns$$Service$::Stub::$Method$("
1785                    "::grpc::ClientContext* context, "
1786                    "const $Request$& request, $Response$* response) {\n");
1787     printer->Print(*vars,
1788                    "  return ::grpc::internal::BlockingUnaryCall"
1789                    "< $Request$, $Response$, ::grpc::protobuf::MessageLite, "
1790                    "::grpc::protobuf::MessageLite>"
1791                    "(channel_.get(), rpcmethod_$Method$_, "
1792                    "context, request, response);\n}\n\n");
1793 
1794     printer->Print(*vars,
1795                    "void $ns$$Service$::Stub::async::$Method$("
1796                    "::grpc::ClientContext* context, "
1797                    "const $Request$* request, $Response$* response, "
1798                    "std::function<void(::grpc::Status)> f) {\n");
1799     printer->Print(*vars,
1800                    "  ::grpc::internal::CallbackUnaryCall"
1801                    "< $Request$, $Response$, ::grpc::protobuf::MessageLite, "
1802                    "::grpc::protobuf::MessageLite>"
1803                    "(stub_->channel_.get(), stub_->rpcmethod_$Method$_, "
1804                    "context, request, response, std::move(f));\n}\n\n");
1805 
1806     printer->Print(*vars,
1807                    "void $ns$$Service$::Stub::async::$Method$("
1808                    "::grpc::ClientContext* context, "
1809                    "const $Request$* request, $Response$* response, "
1810                    "::grpc::ClientUnaryReactor* reactor) {\n");
1811     printer->Print(*vars,
1812                    "  ::grpc::internal::ClientCallbackUnaryFactory::Create"
1813                    "< ::grpc::protobuf::MessageLite, "
1814                    "::grpc::protobuf::MessageLite>"
1815                    "(stub_->channel_.get(), stub_->rpcmethod_$Method$_, "
1816                    "context, request, response, reactor);\n}\n\n");
1817 
1818     if (params.allow_cq_api) {
1819       printer->Print(*vars,
1820                      "::grpc::ClientAsyncResponseReader< $Response$>* "
1821                      "$ns$$Service$::Stub::PrepareAsync$Method$Raw(::grpc::"
1822                      "ClientContext* context, "
1823                      "const $Request$& request, "
1824                      "::grpc::CompletionQueue* cq) {\n");
1825       printer->Print(*vars,
1826                      "  return "
1827                      "::grpc::internal::ClientAsyncResponseReaderHelper::Create"
1828                      "< $Response$, $Request$, ::grpc::protobuf::MessageLite, "
1829                      "::grpc::protobuf::MessageLite>"
1830                      "(channel_.get(), cq, rpcmethod_$Method$_, "
1831                      "context, request);\n"
1832                      "}\n\n");
1833       printer->Print(*vars,
1834                      "::grpc::ClientAsyncResponseReader< $Response$>* "
1835                      "$ns$$Service$::Stub::Async$Method$Raw(::grpc::"
1836                      "ClientContext* context, "
1837                      "const $Request$& request, "
1838                      "::grpc::CompletionQueue* cq) {\n");
1839       printer->Print(
1840           *vars,
1841           "  auto* result =\n"
1842           "    this->PrepareAsync$Method$Raw(context, request, cq);\n"
1843           "  result->StartCall();\n"
1844           "  return result;\n"
1845           "}\n\n");
1846     }
1847   } else if (ClientOnlyStreaming(method)) {
1848     printer->Print(*vars,
1849                    "::grpc::ClientWriter< $Request$>* "
1850                    "$ns$$Service$::Stub::$Method$Raw("
1851                    "::grpc::ClientContext* context, $Response$* response) {\n");
1852     printer->Print(*vars,
1853                    "  return ::grpc::internal::ClientWriterFactory< "
1854                    "$Request$>::Create("
1855                    "channel_.get(), "
1856                    "rpcmethod_$Method$_, "
1857                    "context, response);\n"
1858                    "}\n\n");
1859 
1860     printer->Print(*vars,
1861                    "void $ns$$Service$::"
1862                    "Stub::async::$Method$(::grpc::ClientContext* context, "
1863                    "$Response$* response, "
1864                    "::grpc::ClientWriteReactor< $Request$>* reactor) {\n");
1865     printer->Print(*vars,
1866                    "  ::grpc::internal::ClientCallbackWriterFactory< "
1867                    "$Request$>::Create("
1868                    "stub_->channel_.get(), "
1869                    "stub_->rpcmethod_$Method$_, "
1870                    "context, response, reactor);\n"
1871                    "}\n\n");
1872 
1873     if (params.allow_cq_api) {
1874       for (const auto& async_prefix : async_prefixes) {
1875         (*vars)["AsyncPrefix"] = async_prefix.prefix;
1876         (*vars)["AsyncStart"] = async_prefix.start;
1877         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1878         (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1879         printer->Print(*vars,
1880                        "::grpc::ClientAsyncWriter< $Request$>* "
1881                        "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
1882                        "::grpc::ClientContext* context, $Response$* response, "
1883                        "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1884         printer->Print(
1885             *vars,
1886             "  return ::grpc::internal::ClientAsyncWriterFactory< $Request$>"
1887             "::Create(channel_.get(), cq, "
1888             "rpcmethod_$Method$_, "
1889             "context, response, $AsyncStart$$AsyncCreateArgs$);\n"
1890             "}\n\n");
1891       }
1892     }
1893   } else if (ServerOnlyStreaming(method)) {
1894     printer->Print(
1895         *vars,
1896         "::grpc::ClientReader< $Response$>* "
1897         "$ns$$Service$::Stub::$Method$Raw("
1898         "::grpc::ClientContext* context, const $Request$& request) {\n");
1899     printer->Print(*vars,
1900                    "  return ::grpc::internal::ClientReaderFactory< "
1901                    "$Response$>::Create("
1902                    "channel_.get(), "
1903                    "rpcmethod_$Method$_, "
1904                    "context, request);\n"
1905                    "}\n\n");
1906 
1907     printer->Print(*vars,
1908                    "void $ns$$Service$::Stub::async::$Method$(::grpc::"
1909                    "ClientContext* context, "
1910                    "const $Request$* request, "
1911                    "::grpc::ClientReadReactor< $Response$>* reactor) {\n");
1912     printer->Print(*vars,
1913                    "  ::grpc::internal::ClientCallbackReaderFactory< "
1914                    "$Response$>::Create("
1915                    "stub_->channel_.get(), "
1916                    "stub_->rpcmethod_$Method$_, "
1917                    "context, request, reactor);\n"
1918                    "}\n\n");
1919 
1920     if (params.allow_cq_api) {
1921       for (const auto& async_prefix : async_prefixes) {
1922         (*vars)["AsyncPrefix"] = async_prefix.prefix;
1923         (*vars)["AsyncStart"] = async_prefix.start;
1924         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1925         (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1926         printer->Print(
1927             *vars,
1928             "::grpc::ClientAsyncReader< $Response$>* "
1929             "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
1930             "::grpc::ClientContext* context, const $Request$& request, "
1931             "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1932         printer->Print(*vars,
1933                        "  return ::grpc::internal::ClientAsyncReaderFactory< "
1934                        "$Response$>"
1935                        "::Create(channel_.get(), cq, "
1936                        "rpcmethod_$Method$_, "
1937                        "context, request, $AsyncStart$$AsyncCreateArgs$);\n"
1938                        "}\n\n");
1939       }
1940     }
1941   } else if (method->BidiStreaming()) {
1942     printer->Print(
1943         *vars,
1944         "::grpc::ClientReaderWriter< $Request$, $Response$>* "
1945         "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
1946     printer->Print(*vars,
1947                    "  return ::grpc::internal::ClientReaderWriterFactory< "
1948                    "$Request$, $Response$>::Create("
1949                    "channel_.get(), "
1950                    "rpcmethod_$Method$_, "
1951                    "context);\n"
1952                    "}\n\n");
1953 
1954     printer->Print(*vars,
1955                    "void $ns$$Service$::Stub::async::$Method$(::grpc::"
1956                    "ClientContext* context, "
1957                    "::grpc::ClientBidiReactor< $Request$,$Response$>* "
1958                    "reactor) {\n");
1959     printer->Print(*vars,
1960                    "  ::grpc::internal::ClientCallbackReaderWriterFactory< "
1961                    "$Request$,$Response$>::Create("
1962                    "stub_->channel_.get(), "
1963                    "stub_->rpcmethod_$Method$_, "
1964                    "context, reactor);\n"
1965                    "}\n\n");
1966 
1967     if (params.allow_cq_api) {
1968       for (const auto& async_prefix : async_prefixes) {
1969         (*vars)["AsyncPrefix"] = async_prefix.prefix;
1970         (*vars)["AsyncStart"] = async_prefix.start;
1971         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1972         (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1973         printer->Print(
1974             *vars,
1975             "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
1976             "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
1977             "ClientContext* context, "
1978             "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1979         printer->Print(*vars,
1980                        "  return "
1981                        "::grpc::internal::ClientAsyncReaderWriterFactory< "
1982                        "$Request$, $Response$>::Create("
1983                        "channel_.get(), cq, "
1984                        "rpcmethod_$Method$_, "
1985                        "context, $AsyncStart$$AsyncCreateArgs$);\n"
1986                        "}\n\n");
1987       }
1988     }
1989   }
1990 }
1991 
PrintSourceServerMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars)1992 void PrintSourceServerMethod(grpc_generator::Printer* printer,
1993                              const grpc_generator::Method* method,
1994                              const Parameters& params,
1995                              std::map<std::string, std::string>* vars) {
1996   (*vars)["Method"] = method->name();
1997   (*vars)["Request"] = method->input_type_name();
1998   (*vars)["Response"] = method->output_type_name();
1999   if (method->NoStreaming()) {
2000     printer->Print(*vars,
2001                    "::grpc::Status $ns$$Service$::Service::$Method$("
2002                    "::grpc::ServerContext* context, "
2003                    "const $Request$* request, $Response$* response) {\n");
2004     if (!params.allow_sync_server_api) {
2005       printer->Print("  abort();\n");
2006     }
2007     printer->Print("  (void) context;\n");
2008     printer->Print("  (void) request;\n");
2009     printer->Print("  (void) response;\n");
2010     printer->Print(
2011         "  return ::grpc::Status("
2012         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
2013     printer->Print("}\n\n");
2014   } else if (ClientOnlyStreaming(method)) {
2015     printer->Print(*vars,
2016                    "::grpc::Status $ns$$Service$::Service::$Method$("
2017                    "::grpc::ServerContext* context, "
2018                    "::grpc::ServerReader< $Request$>* reader, "
2019                    "$Response$* response) {\n");
2020     if (!params.allow_sync_server_api) {
2021       printer->Print("  abort();\n");
2022     }
2023     printer->Print("  (void) context;\n");
2024     printer->Print("  (void) reader;\n");
2025     printer->Print("  (void) response;\n");
2026     printer->Print(
2027         "  return ::grpc::Status("
2028         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
2029     printer->Print("}\n\n");
2030   } else if (ServerOnlyStreaming(method)) {
2031     printer->Print(*vars,
2032                    "::grpc::Status $ns$$Service$::Service::$Method$("
2033                    "::grpc::ServerContext* context, "
2034                    "const $Request$* request, "
2035                    "::grpc::ServerWriter< $Response$>* writer) {\n");
2036     if (!params.allow_sync_server_api) {
2037       printer->Print("  abort();\n");
2038     }
2039     printer->Print("  (void) context;\n");
2040     printer->Print("  (void) request;\n");
2041     printer->Print("  (void) writer;\n");
2042     printer->Print(
2043         "  return ::grpc::Status("
2044         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
2045     printer->Print("}\n\n");
2046   } else if (method->BidiStreaming()) {
2047     printer->Print(*vars,
2048                    "::grpc::Status $ns$$Service$::Service::$Method$("
2049                    "::grpc::ServerContext* context, "
2050                    "::grpc::ServerReaderWriter< $Response$, $Request$>* "
2051                    "stream) {\n");
2052     if (!params.allow_sync_server_api) {
2053       printer->Print("  abort();\n");
2054     }
2055     printer->Print("  (void) context;\n");
2056     printer->Print("  (void) stream;\n");
2057     printer->Print(
2058         "  return ::grpc::Status("
2059         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
2060     printer->Print("}\n\n");
2061   }
2062 }
2063 
PrintSourceService(grpc_generator::Printer * printer,const grpc_generator::Service * service,const Parameters & params,std::map<std::string,std::string> * vars)2064 void PrintSourceService(grpc_generator::Printer* printer,
2065                         const grpc_generator::Service* service,
2066                         const Parameters& params,
2067                         std::map<std::string, std::string>* vars) {
2068   (*vars)["Service"] = service->name();
2069 
2070   if (service->method_count() > 0) {
2071     printer->Print(*vars,
2072                    "static const char* $prefix$$Service$_method_names[] = {\n");
2073     for (int i = 0; i < service->method_count(); ++i) {
2074       (*vars)["Method"] = service->method(i)->name();
2075       printer->Print(*vars, "  \"/$Package$$Service$/$Method$\",\n");
2076     }
2077     printer->Print(*vars, "};\n\n");
2078   }
2079 
2080   printer->Print(*vars,
2081                  "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
2082                  "const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
2083                  "const ::grpc::StubOptions& options) {\n"
2084                  "  (void)options;\n"
2085                  "  std::unique_ptr< $ns$$Service$::Stub> stub(new "
2086                  "$ns$$Service$::Stub(channel, options));\n"
2087                  "  return stub;\n"
2088                  "}\n\n");
2089   printer->Print(*vars,
2090                  "$ns$$Service$::Stub::Stub(const std::shared_ptr< "
2091                  "::grpc::ChannelInterface>& channel, const "
2092                  "::grpc::StubOptions& options)\n");
2093   printer->Indent();
2094   printer->Print(": channel_(channel)");
2095   for (int i = 0; i < service->method_count(); ++i) {
2096     auto method = service->method(i);
2097     (*vars)["Method"] = method->name();
2098     (*vars)["Idx"] = as_string(i);
2099     if (method->NoStreaming()) {
2100       (*vars)["StreamingType"] = "NORMAL_RPC";
2101       // NOTE: There is no reason to consider streamed-unary as a separate
2102       // category here since this part is setting up the client-side stub
2103       // and this appears as a NORMAL_RPC from the client-side.
2104     } else if (ClientOnlyStreaming(method.get())) {
2105       (*vars)["StreamingType"] = "CLIENT_STREAMING";
2106     } else if (ServerOnlyStreaming(method.get())) {
2107       (*vars)["StreamingType"] = "SERVER_STREAMING";
2108     } else {
2109       (*vars)["StreamingType"] = "BIDI_STREAMING";
2110     }
2111     printer->Print(
2112         *vars,
2113         ", rpcmethod_$Method$_("
2114         "$prefix$$Service$_method_names[$Idx$], options.suffix_for_stats(),"
2115         "::grpc::internal::RpcMethod::$StreamingType$, "
2116         "channel"
2117         ")\n");
2118   }
2119   printer->Print("{}\n\n");
2120   printer->Outdent();
2121 
2122   for (int i = 0; i < service->method_count(); ++i) {
2123     (*vars)["Idx"] = as_string(i);
2124     PrintSourceClientMethod(printer, service->method(i).get(), params, vars);
2125   }
2126 
2127   printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
2128   printer->Indent();
2129   for (int i = 0; i < service->method_count(); ++i) {
2130     auto method = service->method(i);
2131     (*vars)["Idx"] = as_string(i);
2132     (*vars)["Method"] = method->name();
2133     (*vars)["Request"] = method->input_type_name();
2134     (*vars)["Response"] = method->output_type_name();
2135     if (method->NoStreaming()) {
2136       printer->Print(
2137           *vars,
2138           "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
2139           "    $prefix$$Service$_method_names[$Idx$],\n"
2140           "    ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
2141           "    new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
2142           "$Request$, $Response$, ::grpc::protobuf::MessageLite, "
2143           "::grpc::protobuf::MessageLite>(\n"
2144           "        []($ns$$Service$::Service* service,\n"
2145           "           ::grpc::ServerContext* ctx,\n"
2146           "           const $Request$* req,\n"
2147           "           $Response$* resp) {\n"
2148           "             return service->$Method$(ctx, req, resp);\n"
2149           "           }, this)));\n");
2150     } else if (ClientOnlyStreaming(method.get())) {
2151       printer->Print(
2152           *vars,
2153           "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
2154           "    $prefix$$Service$_method_names[$Idx$],\n"
2155           "    ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
2156           "    new ::grpc::internal::ClientStreamingHandler< "
2157           "$ns$$Service$::Service, $Request$, $Response$>(\n"
2158           "        []($ns$$Service$::Service* service,\n"
2159           "           ::grpc::ServerContext* ctx,\n"
2160           "           ::grpc::ServerReader<$Request$>* reader,\n"
2161           "           $Response$* resp) {\n"
2162           "             return service->$Method$(ctx, reader, resp);\n"
2163           "           }, this)));\n");
2164     } else if (ServerOnlyStreaming(method.get())) {
2165       printer->Print(
2166           *vars,
2167           "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
2168           "    $prefix$$Service$_method_names[$Idx$],\n"
2169           "    ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
2170           "    new ::grpc::internal::ServerStreamingHandler< "
2171           "$ns$$Service$::Service, $Request$, $Response$>(\n"
2172           "        []($ns$$Service$::Service* service,\n"
2173           "           ::grpc::ServerContext* ctx,\n"
2174           "           const $Request$* req,\n"
2175           "           ::grpc::ServerWriter<$Response$>* writer) {\n"
2176           "             return service->$Method$(ctx, req, writer);\n"
2177           "           }, this)));\n");
2178     } else if (method->BidiStreaming()) {
2179       printer->Print(*vars,
2180                      "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
2181                      "    $prefix$$Service$_method_names[$Idx$],\n"
2182                      "    ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
2183                      "    new ::grpc::internal::BidiStreamingHandler< "
2184                      "$ns$$Service$::Service, $Request$, $Response$>(\n"
2185                      "        []($ns$$Service$::Service* service,\n"
2186                      "           ::grpc::ServerContext* ctx,\n"
2187                      "           ::grpc::ServerReaderWriter<$Response$,\n"
2188                      "           $Request$>* stream) {\n"
2189                      "             return service->$Method$(ctx, stream);\n"
2190                      "           }, this)));\n");
2191     }
2192   }
2193   printer->Outdent();
2194   printer->Print(*vars, "}\n\n");
2195   printer->Print(*vars,
2196                  "$ns$$Service$::Service::~Service() {\n"
2197                  "}\n\n");
2198   for (int i = 0; i < service->method_count(); ++i) {
2199     (*vars)["Idx"] = as_string(i);
2200     PrintSourceServerMethod(printer, service->method(i).get(), params, vars);
2201   }
2202 }
2203 
GetSourceServices(grpc_generator::File * file,const Parameters & params)2204 std::string GetSourceServices(grpc_generator::File* file,
2205                               const Parameters& params) {
2206   std::string output;
2207   {
2208     // Scope the output stream so it closes and finalizes output to the string.
2209     auto printer = file->CreatePrinter(&output);
2210     std::map<std::string, std::string> vars;
2211     // Package string is empty or ends with a dot. It is used to fully qualify
2212     // method names.
2213     vars["Package"] = file->package();
2214     if (!file->package().empty()) {
2215       vars["Package"].append(".");
2216     }
2217     if (!params.services_namespace.empty()) {
2218       vars["ns"] = params.services_namespace + "::";
2219       vars["prefix"] = params.services_namespace;
2220     } else {
2221       vars["ns"] = "";
2222       vars["prefix"] = "";
2223     }
2224 
2225     for (int i = 0; i < file->service_count(); ++i) {
2226       PrintSourceService(printer.get(), file->service(i).get(), params, &vars);
2227       printer->Print("\n");
2228     }
2229   }
2230   return output;
2231 }
2232 
GetSourceEpilogue(grpc_generator::File * file,const Parameters &)2233 std::string GetSourceEpilogue(grpc_generator::File* file,
2234                               const Parameters& /*params*/) {
2235   std::string temp;
2236 
2237   if (!file->package().empty()) {
2238     std::vector<std::string> parts = file->package_parts();
2239 
2240     for (auto part = parts.begin(); part != parts.end(); part++) {
2241       temp.append("}  // namespace ");
2242       temp.append(*part);
2243       temp.append("\n");
2244     }
2245     temp.append("\n");
2246   }
2247 
2248   return temp;
2249 }
2250 
2251 // TODO(mmukhi): Make sure we need parameters or not.
GetMockPrologue(grpc_generator::File * file,const Parameters & params)2252 std::string GetMockPrologue(grpc_generator::File* file,
2253                             const Parameters& params) {
2254   std::string output;
2255   {
2256     // Scope the output stream so it closes and finalizes output to the string.
2257     auto printer = file->CreatePrinter(&output);
2258     std::map<std::string, std::string> vars;
2259 
2260     vars["filename"] = file->filename();
2261     vars["filename_identifier"] = FilenameIdentifier(file->filename());
2262     vars["filename_base"] = file->filename_without_ext();
2263     vars["message_header_ext"] = params.message_header_extension.empty()
2264                                      ? kCppGeneratorMessageHeaderExt
2265                                      : params.message_header_extension;
2266     vars["service_header_ext"] = kCppGeneratorServiceHeaderExt;
2267 
2268     printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
2269     printer->Print(vars,
2270                    "// If you make any local change, they will be lost.\n");
2271     printer->Print(vars, "// source: $filename$\n\n");
2272 
2273     printer->Print(vars, "#ifndef GRPC_MOCK_$filename_identifier$__INCLUDED\n");
2274     printer->Print(vars, "#define GRPC_MOCK_$filename_identifier$__INCLUDED\n");
2275     printer->Print(vars, "\n");
2276     printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
2277     printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
2278     if (params.include_import_headers) {
2279       const std::vector<std::string> import_names = file->GetImportNames();
2280       for (const auto& import_name : import_names) {
2281         const std::string include_name = ImportInludeFromProtoName(import_name);
2282         printer->Print(vars, include_name.c_str());
2283       }
2284       printer->PrintRaw("\n");
2285     }
2286     printer->Print(vars, file->additional_headers().c_str());
2287     printer->Print(vars, "\n");
2288   }
2289   return output;
2290 }
2291 
2292 // TODO(mmukhi): Add client-stream and completion-queue headers.
GetMockIncludes(grpc_generator::File * file,const Parameters & params)2293 std::string GetMockIncludes(grpc_generator::File* file,
2294                             const Parameters& params) {
2295   std::string output;
2296   {
2297     // Scope the output stream so it closes and finalizes output to the string.
2298     auto printer = file->CreatePrinter(&output);
2299     std::map<std::string, std::string> vars;
2300 
2301     static const char* headers_strs[] = {
2302         "grpcpp/support/async_stream.h",
2303         "grpcpp/support/sync_stream.h",
2304     };
2305     std::vector<std::string> headers(headers_strs, array_end(headers_strs));
2306     PrintIncludes(printer.get(), headers, params.use_system_headers,
2307                   params.grpc_search_path);
2308 
2309     std::vector<std::string> gmock_header;
2310     if (params.gmock_search_path.empty()) {
2311       gmock_header.push_back("gmock/gmock.h");
2312       PrintIncludes(printer.get(), gmock_header, params.use_system_headers,
2313                     params.grpc_search_path);
2314     } else {
2315       gmock_header.push_back("gmock.h");
2316       // We use local includes when a gmock_search_path is given
2317       PrintIncludes(printer.get(), gmock_header, false,
2318                     params.gmock_search_path);
2319     }
2320 
2321     if (!file->package().empty()) {
2322       std::vector<std::string> parts = file->package_parts();
2323 
2324       for (auto part = parts.begin(); part != parts.end(); part++) {
2325         vars["part"] = *part;
2326         printer->Print(vars, "namespace $part$ {\n");
2327       }
2328     }
2329 
2330     printer->Print(vars, "\n");
2331   }
2332   return output;
2333 }
2334 
PrintMockClientMethods(grpc_generator::Printer * printer,const grpc_generator::Method * method,const Parameters & params,std::map<std::string,std::string> * vars)2335 void PrintMockClientMethods(grpc_generator::Printer* printer,
2336                             const grpc_generator::Method* method,
2337                             const Parameters& params,
2338                             std::map<std::string, std::string>* vars) {
2339   (*vars)["Method"] = method->name();
2340   (*vars)["Request"] = method->input_type_name();
2341   (*vars)["Response"] = method->output_type_name();
2342 
2343   struct {
2344     std::string prefix;
2345     std::string method_params;  // extra arguments to method
2346     int extra_method_param_count;
2347   } async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
2348 
2349   if (method->NoStreaming()) {
2350     printer->Print(
2351         *vars,
2352         "MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
2353         "const $Request$& request, $Response$* response));\n");
2354     if (params.allow_cq_api) {
2355       for (const auto& async_prefix : async_prefixes) {
2356         (*vars)["AsyncPrefix"] = async_prefix.prefix;
2357         printer->Print(
2358             *vars,
2359             "MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
2360             "::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
2361             "(::grpc::ClientContext* context, const $Request$& request, "
2362             "::grpc::CompletionQueue* cq));\n");
2363       }
2364     }
2365   } else if (ClientOnlyStreaming(method)) {
2366     printer->Print(
2367         *vars,
2368         "MOCK_METHOD2($Method$Raw, "
2369         "::grpc::ClientWriterInterface< $Request$>*"
2370         "(::grpc::ClientContext* context, $Response$* response));\n");
2371     if (params.allow_cq_api) {
2372       for (const auto& async_prefix : async_prefixes) {
2373         (*vars)["AsyncPrefix"] = async_prefix.prefix;
2374         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
2375         (*vars)["MockArgs"] =
2376             std::to_string(3 + async_prefix.extra_method_param_count);
2377         printer->Print(*vars,
2378                        "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
2379                        "::grpc::ClientAsyncWriterInterface< $Request$>*"
2380                        "(::grpc::ClientContext* context, $Response$* response, "
2381                        "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
2382       }
2383     }
2384   } else if (ServerOnlyStreaming(method)) {
2385     printer->Print(
2386         *vars,
2387         "MOCK_METHOD2($Method$Raw, "
2388         "::grpc::ClientReaderInterface< $Response$>*"
2389         "(::grpc::ClientContext* context, const $Request$& request));\n");
2390     if (params.allow_cq_api) {
2391       for (const auto& async_prefix : async_prefixes) {
2392         (*vars)["AsyncPrefix"] = async_prefix.prefix;
2393         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
2394         (*vars)["MockArgs"] =
2395             std::to_string(3 + async_prefix.extra_method_param_count);
2396         printer->Print(
2397             *vars,
2398             "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
2399             "::grpc::ClientAsyncReaderInterface< $Response$>*"
2400             "(::grpc::ClientContext* context, const $Request$& request, "
2401             "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
2402       }
2403     }
2404   } else if (method->BidiStreaming()) {
2405     printer->Print(
2406         *vars,
2407         "MOCK_METHOD1($Method$Raw, "
2408         "::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
2409         "(::grpc::ClientContext* context));\n");
2410     if (params.allow_cq_api) {
2411       for (const auto& async_prefix : async_prefixes) {
2412         (*vars)["AsyncPrefix"] = async_prefix.prefix;
2413         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
2414         (*vars)["MockArgs"] =
2415             std::to_string(2 + async_prefix.extra_method_param_count);
2416         printer->Print(
2417             *vars,
2418             "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
2419             "::grpc::ClientAsyncReaderWriterInterface<$Request$, "
2420             "$Response$>*"
2421             "(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
2422             "$AsyncMethodParams$));\n");
2423       }
2424     }
2425   }
2426 }
2427 
PrintMockService(grpc_generator::Printer * printer,const grpc_generator::Service * service,const Parameters & params,std::map<std::string,std::string> * vars)2428 void PrintMockService(grpc_generator::Printer* printer,
2429                       const grpc_generator::Service* service,
2430                       const Parameters& params,
2431                       std::map<std::string, std::string>* vars) {
2432   (*vars)["Service"] = service->name();
2433 
2434   printer->Print(*vars,
2435                  "class Mock$Service$Stub : public $Service$::StubInterface {\n"
2436                  " public:\n");
2437   printer->Indent();
2438   for (int i = 0; i < service->method_count(); ++i) {
2439     PrintMockClientMethods(printer, service->method(i).get(), params, vars);
2440   }
2441   printer->Outdent();
2442   printer->Print("};\n");
2443 }
2444 
GetMockServices(grpc_generator::File * file,const Parameters & params)2445 std::string GetMockServices(grpc_generator::File* file,
2446                             const Parameters& params) {
2447   std::string output;
2448   {
2449     // Scope the output stream so it closes and finalizes output to the string.
2450     auto printer = file->CreatePrinter(&output);
2451     std::map<std::string, std::string> vars;
2452     // Package string is empty or ends with a dot. It is used to fully qualify
2453     // method names.
2454     vars["Package"] = file->package();
2455     if (!file->package().empty()) {
2456       vars["Package"].append(".");
2457     }
2458 
2459     if (!params.services_namespace.empty()) {
2460       vars["services_namespace"] = params.services_namespace;
2461       printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
2462     }
2463 
2464     for (int i = 0; i < file->service_count(); i++) {
2465       PrintMockService(printer.get(), file->service(i).get(), params, &vars);
2466       printer->Print("\n");
2467     }
2468 
2469     if (!params.services_namespace.empty()) {
2470       printer->Print(vars, "} // namespace $services_namespace$\n\n");
2471     }
2472   }
2473   return output;
2474 }
2475 
GetMockEpilogue(grpc_generator::File * file,const Parameters &)2476 std::string GetMockEpilogue(grpc_generator::File* file,
2477                             const Parameters& /*params*/) {
2478   std::string output;
2479   {
2480     // Scope the output stream so it closes and finalizes output to the string.
2481     auto printer = file->CreatePrinter(&output);
2482     std::map<std::string, std::string> vars;
2483     vars["filename_identifier"] = FilenameIdentifier(file->filename());
2484 
2485     if (!file->package().empty()) {
2486       std::vector<std::string> parts = file->package_parts();
2487       for (auto part = parts.rbegin(); part != parts.rend(); part++) {
2488         vars["part"] = *part;
2489         printer->Print(vars, "}  // namespace $part$\n");
2490       }
2491       printer->Print(vars, "\n");
2492     }
2493 
2494     printer->Print(vars, "\n");
2495     printer->Print(vars,
2496                    "#endif  // GRPC_MOCK_$filename_identifier$__INCLUDED\n");
2497   }
2498   return output;
2499 }
2500 
2501 }  // namespace grpc_cpp_generator
2502