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