objective_c_generator.cc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. #include <map>
  19. #include <sstream>
  20. #include "src/compiler/config.h"
  21. #include "src/compiler/objective_c_generator.h"
  22. #include "src/compiler/objective_c_generator_helpers.h"
  23. #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
  24. using ::google::protobuf::compiler::objectivec::ClassName;
  25. using ::grpc::protobuf::io::Printer;
  26. using ::grpc::protobuf::MethodDescriptor;
  27. using ::grpc::protobuf::ServiceDescriptor;
  28. using ::std::map;
  29. namespace grpc_objective_c_generator {
  30. namespace {
  31. void PrintProtoRpcDeclarationAsPragma(
  32. Printer *printer, const MethodDescriptor *method,
  33. map< ::grpc::string, ::grpc::string> vars) {
  34. vars["client_stream"] = method->client_streaming() ? "stream " : "";
  35. vars["server_stream"] = method->server_streaming() ? "stream " : "";
  36. printer->Print(vars,
  37. "#pragma mark $method_name$($client_stream$$request_type$)"
  38. " returns ($server_stream$$response_type$)\n\n");
  39. }
  40. template <typename DescriptorType>
  41. static void PrintAllComments(const DescriptorType *desc, Printer *printer) {
  42. std::vector<grpc::string> comments;
  43. grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING_DETACHED,
  44. &comments);
  45. grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING,
  46. &comments);
  47. grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_TRAILING,
  48. &comments);
  49. if (comments.empty()) {
  50. return;
  51. }
  52. printer->Print("/**\n");
  53. for (auto it = comments.begin(); it != comments.end(); ++it) {
  54. printer->Print(" * ");
  55. size_t start_pos = it->find_first_not_of(' ');
  56. if (start_pos != grpc::string::npos) {
  57. printer->Print(it->c_str() + start_pos);
  58. }
  59. printer->Print("\n");
  60. }
  61. printer->Print(" */\n");
  62. }
  63. void PrintMethodSignature(Printer *printer, const MethodDescriptor *method,
  64. const map< ::grpc::string, ::grpc::string> &vars) {
  65. // Print comment
  66. PrintAllComments(method, printer);
  67. printer->Print(vars, "- ($return_type$)$method_name$With");
  68. if (method->client_streaming()) {
  69. printer->Print("RequestsWriter:(GRXWriter *)requestWriter");
  70. } else {
  71. printer->Print(vars, "Request:($request_class$ *)request");
  72. }
  73. // TODO(jcanizales): Put this on a new line and align colons.
  74. if (method->server_streaming()) {
  75. printer->Print(vars,
  76. " eventHandler:(void(^)(BOOL done, "
  77. "$response_class$ *_Nullable response, NSError *_Nullable "
  78. "error))eventHandler");
  79. } else {
  80. printer->Print(vars,
  81. " handler:(void(^)($response_class$ *_Nullable response, "
  82. "NSError *_Nullable error))handler");
  83. }
  84. }
  85. void PrintSimpleSignature(Printer *printer, const MethodDescriptor *method,
  86. map< ::grpc::string, ::grpc::string> vars) {
  87. vars["method_name"] =
  88. grpc_generator::LowercaseFirstLetter(vars["method_name"]);
  89. vars["return_type"] = "void";
  90. PrintMethodSignature(printer, method, vars);
  91. }
  92. void PrintAdvancedSignature(Printer *printer, const MethodDescriptor *method,
  93. map< ::grpc::string, ::grpc::string> vars) {
  94. vars["method_name"] = "RPCTo" + vars["method_name"];
  95. vars["return_type"] = "GRPCProtoCall *";
  96. PrintMethodSignature(printer, method, vars);
  97. }
  98. inline map< ::grpc::string, ::grpc::string> GetMethodVars(
  99. const MethodDescriptor *method) {
  100. map< ::grpc::string, ::grpc::string> res;
  101. res["method_name"] = method->name();
  102. res["request_type"] = method->input_type()->name();
  103. res["response_type"] = method->output_type()->name();
  104. res["request_class"] = ClassName(method->input_type());
  105. res["response_class"] = ClassName(method->output_type());
  106. return res;
  107. }
  108. void PrintMethodDeclarations(Printer *printer, const MethodDescriptor *method) {
  109. map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method);
  110. PrintProtoRpcDeclarationAsPragma(printer, method, vars);
  111. PrintSimpleSignature(printer, method, vars);
  112. printer->Print(";\n\n");
  113. PrintAdvancedSignature(printer, method, vars);
  114. printer->Print(";\n\n\n");
  115. }
  116. void PrintSimpleImplementation(Printer *printer, const MethodDescriptor *method,
  117. map< ::grpc::string, ::grpc::string> vars) {
  118. printer->Print("{\n");
  119. printer->Print(vars, " [[self RPCTo$method_name$With");
  120. if (method->client_streaming()) {
  121. printer->Print("RequestsWriter:requestWriter");
  122. } else {
  123. printer->Print("Request:request");
  124. }
  125. if (method->server_streaming()) {
  126. printer->Print(" eventHandler:eventHandler] start];\n");
  127. } else {
  128. printer->Print(" handler:handler] start];\n");
  129. }
  130. printer->Print("}\n");
  131. }
  132. void PrintAdvancedImplementation(Printer *printer,
  133. const MethodDescriptor *method,
  134. map< ::grpc::string, ::grpc::string> vars) {
  135. printer->Print("{\n");
  136. printer->Print(vars, " return [self RPCToMethod:@\"$method_name$\"\n");
  137. printer->Print(" requestsWriter:");
  138. if (method->client_streaming()) {
  139. printer->Print("requestWriter\n");
  140. } else {
  141. printer->Print("[GRXWriter writerWithValue:request]\n");
  142. }
  143. printer->Print(vars, " responseClass:[$response_class$ class]\n");
  144. printer->Print(" responsesWriteable:[GRXWriteable ");
  145. if (method->server_streaming()) {
  146. printer->Print("writeableWithEventHandler:eventHandler]];\n");
  147. } else {
  148. printer->Print("writeableWithSingleHandler:handler]];\n");
  149. }
  150. printer->Print("}\n");
  151. }
  152. void PrintMethodImplementations(Printer *printer,
  153. const MethodDescriptor *method) {
  154. map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method);
  155. PrintProtoRpcDeclarationAsPragma(printer, method, vars);
  156. // TODO(jcanizales): Print documentation from the method.
  157. PrintSimpleSignature(printer, method, vars);
  158. PrintSimpleImplementation(printer, method, vars);
  159. printer->Print("// Returns a not-yet-started RPC object.\n");
  160. PrintAdvancedSignature(printer, method, vars);
  161. PrintAdvancedImplementation(printer, method, vars);
  162. }
  163. } // namespace
  164. ::grpc::string GetHeader(const ServiceDescriptor *service) {
  165. ::grpc::string output;
  166. {
  167. // Scope the output stream so it closes and finalizes output to the string.
  168. grpc::protobuf::io::StringOutputStream output_stream(&output);
  169. Printer printer(&output_stream, '$');
  170. map< ::grpc::string, ::grpc::string> vars = {
  171. {"service_class", ServiceClassName(service)}};
  172. printer.Print(vars, "@protocol $service_class$ <NSObject>\n\n");
  173. for (int i = 0; i < service->method_count(); i++) {
  174. PrintMethodDeclarations(&printer, service->method(i));
  175. }
  176. printer.Print("@end\n\n");
  177. printer.Print(
  178. "/**\n"
  179. " * Basic service implementation, over gRPC, that only does\n"
  180. " * marshalling and parsing.\n"
  181. " */\n");
  182. printer.Print(vars,
  183. "@interface $service_class$ :"
  184. " GRPCProtoService<$service_class$>\n");
  185. printer.Print(
  186. "- (instancetype)initWithHost:(NSString *)host"
  187. " NS_DESIGNATED_INITIALIZER;\n");
  188. printer.Print("+ (instancetype)serviceWithHost:(NSString *)host;\n");
  189. printer.Print("@end\n");
  190. }
  191. return output;
  192. }
  193. ::grpc::string GetSource(const ServiceDescriptor *service) {
  194. ::grpc::string output;
  195. {
  196. // Scope the output stream so it closes and finalizes output to the string.
  197. grpc::protobuf::io::StringOutputStream output_stream(&output);
  198. Printer printer(&output_stream, '$');
  199. map< ::grpc::string, ::grpc::string> vars = {
  200. {"service_name", service->name()},
  201. {"service_class", ServiceClassName(service)},
  202. {"package", service->file()->package()}};
  203. printer.Print(vars, "@implementation $service_class$\n\n");
  204. printer.Print("// Designated initializer\n");
  205. printer.Print("- (instancetype)initWithHost:(NSString *)host {\n");
  206. printer.Print(
  207. vars,
  208. " return (self = [super initWithHost:host"
  209. " packageName:@\"$package$\" serviceName:@\"$service_name$\"]);\n");
  210. printer.Print("}\n\n");
  211. printer.Print(
  212. "// Override superclass initializer to disallow different"
  213. " package and service names.\n");
  214. printer.Print("- (instancetype)initWithHost:(NSString *)host\n");
  215. printer.Print(" packageName:(NSString *)packageName\n");
  216. printer.Print(" serviceName:(NSString *)serviceName {\n");
  217. printer.Print(" return [self initWithHost:host];\n");
  218. printer.Print("}\n\n");
  219. printer.Print("+ (instancetype)serviceWithHost:(NSString *)host {\n");
  220. printer.Print(" return [[self alloc] initWithHost:host];\n");
  221. printer.Print("}\n\n\n");
  222. for (int i = 0; i < service->method_count(); i++) {
  223. PrintMethodImplementations(&printer, service->method(i));
  224. }
  225. printer.Print("@end\n");
  226. }
  227. return output;
  228. }
  229. } // namespace grpc_objective_c_generator