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