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