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