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