objective_c_generator.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. *
  3. * Copyright 2015, Google Inc.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following disclaimer
  14. * in the documentation and/or other materials provided with the
  15. * distribution.
  16. * * Neither the name of Google Inc. nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. */
  33. #include <map>
  34. #include <sstream>
  35. #include "src/compiler/config.h"
  36. #include "src/compiler/objective_c_generator.h"
  37. #include "src/compiler/objective_c_generator_helpers.h"
  38. #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
  39. using ::google::protobuf::compiler::objectivec::ClassName;
  40. using ::grpc::protobuf::io::Printer;
  41. using ::grpc::protobuf::MethodDescriptor;
  42. using ::grpc::protobuf::ServiceDescriptor;
  43. using ::grpc::string;
  44. using ::std::map;
  45. namespace grpc_objective_c_generator {
  46. namespace {
  47. void PrintProtoRpcDeclarationAsPragma(Printer *printer,
  48. const MethodDescriptor *method,
  49. map<string, string> vars) {
  50. vars["client_stream"] = method->client_streaming() ? "stream " : "";
  51. vars["server_stream"] = method->server_streaming() ? "stream " : "";
  52. printer->Print(vars,
  53. "#pragma mark $method_name$($client_stream$$request_type$)"
  54. " returns ($server_stream$$response_type$)\n\n");
  55. }
  56. void PrintMethodSignature(Printer *printer,
  57. const MethodDescriptor *method,
  58. const map<string, string>& vars) {
  59. // TODO(jcanizales): Print method comments.
  60. printer->Print(vars, "- ($return_type$)$method_name$With");
  61. if (method->client_streaming()) {
  62. printer->Print("RequestsWriter:(id<GRXWriter>)request");
  63. } else {
  64. printer->Print(vars, "Request:($request_class$ *)request");
  65. }
  66. // TODO(jcanizales): Put this on a new line and align colons.
  67. // TODO(jcanizales): eventHandler for server streaming?
  68. printer->Print(" handler:(void(^)(");
  69. if (method->server_streaming()) {
  70. printer->Print("BOOL done, ");
  71. }
  72. printer->Print(vars, "$response_class$ *response, NSError *error))handler");
  73. }
  74. void PrintSimpleSignature(Printer *printer,
  75. const MethodDescriptor *method,
  76. map<string, string> vars) {
  77. vars["method_name"] =
  78. grpc_generator::LowercaseFirstLetter(vars["method_name"]);
  79. vars["return_type"] = "void";
  80. PrintMethodSignature(printer, method, vars);
  81. }
  82. void PrintAdvancedSignature(Printer *printer,
  83. const MethodDescriptor *method,
  84. map<string, string> vars) {
  85. vars["method_name"] = "RPCTo" + vars["method_name"];
  86. vars["return_type"] = "ProtoRPC *";
  87. PrintMethodSignature(printer, method, vars);
  88. }
  89. inline map<string, string> GetMethodVars(const MethodDescriptor *method) {
  90. return {{ "method_name", method->name() },
  91. { "request_type", method->input_type()->name() },
  92. { "response_type", method->output_type()->name() },
  93. { "request_class", ClassName(method->input_type()) },
  94. { "response_class", ClassName(method->output_type()) }};
  95. }
  96. void PrintMethodDeclarations(Printer *printer,
  97. const MethodDescriptor *method) {
  98. map<string, string> vars = GetMethodVars(method);
  99. PrintProtoRpcDeclarationAsPragma(printer, method, vars);
  100. PrintSimpleSignature(printer, method, vars);
  101. printer->Print(";\n\n");
  102. PrintAdvancedSignature(printer, method, vars);
  103. printer->Print(";\n\n\n");
  104. }
  105. void PrintSimpleImplementation(Printer *printer,
  106. const MethodDescriptor *method,
  107. map<string, string> vars) {
  108. printer->Print("{\n");
  109. printer->Print(vars, " [[self RPCTo$method_name$With");
  110. if (method->client_streaming()) {
  111. printer->Print("RequestsWriter:request");
  112. } else {
  113. printer->Print("Request:request");
  114. }
  115. printer->Print(" handler:handler] start];\n");
  116. printer->Print("}\n");
  117. }
  118. void PrintAdvancedImplementation(Printer *printer,
  119. const MethodDescriptor *method,
  120. map<string, string> vars) {
  121. printer->Print("{\n");
  122. printer->Print(vars, " return [self RPCToMethod:@\"$method_name$\"\n");
  123. printer->Print(" requestsWriter:");
  124. if (method->client_streaming()) {
  125. printer->Print("request\n");
  126. } else {
  127. printer->Print("[GRXWriter writerWithValue:request]\n");
  128. }
  129. printer->Print(vars, " responseClass:[$response_class$ class]\n");
  130. printer->Print(" responsesWriteable:[GRXWriteable ");
  131. if (method->server_streaming()) {
  132. printer->Print("writeableWithStreamHandler:handler]];\n");
  133. } else {
  134. printer->Print("writeableWithSingleValueHandler:handler]];\n");
  135. }
  136. printer->Print("}\n");
  137. }
  138. void PrintMethodImplementations(Printer *printer,
  139. const MethodDescriptor *method) {
  140. map<string, string> vars = GetMethodVars(method);
  141. PrintProtoRpcDeclarationAsPragma(printer, method, vars);
  142. // TODO(jcanizales): Print documentation from the method.
  143. PrintSimpleSignature(printer, method, vars);
  144. PrintSimpleImplementation(printer, method, vars);
  145. printer->Print("// Returns a not-yet-started RPC object.\n");
  146. PrintAdvancedSignature(printer, method, vars);
  147. PrintAdvancedImplementation(printer, method, vars);
  148. }
  149. } // namespace
  150. string GetHeader(const ServiceDescriptor *service) {
  151. string output;
  152. {
  153. // Scope the output stream so it closes and finalizes output to the string.
  154. grpc::protobuf::io::StringOutputStream output_stream(&output);
  155. Printer printer(&output_stream, '$');
  156. printer.Print("@protocol GRXWriteable;\n");
  157. printer.Print("@protocol GRXWriter;\n\n");
  158. map<string, string> vars = {{"service_class", ServiceClassName(service)}};
  159. printer.Print(vars, "@protocol $service_class$ <NSObject>\n\n");
  160. for (int i = 0; i < service->method_count(); i++) {
  161. PrintMethodDeclarations(&printer, service->method(i));
  162. }
  163. printer.Print("@end\n\n");
  164. printer.Print("// Basic service implementation, over gRPC, that only does"
  165. " marshalling and parsing.\n");
  166. printer.Print(vars, "@interface $service_class$ :"
  167. " ProtoService<$service_class$>\n");
  168. printer.Print("- (instancetype)initWithHost:(NSString *)host"
  169. " NS_DESIGNATED_INITIALIZER;\n");
  170. printer.Print("@end\n");
  171. }
  172. return output;
  173. }
  174. string GetSource(const ServiceDescriptor *service) {
  175. string output;
  176. {
  177. // Scope the output stream so it closes and finalizes output to the string.
  178. grpc::protobuf::io::StringOutputStream output_stream(&output);
  179. Printer printer(&output_stream, '$');
  180. map<string, string> vars = {{"service_name", service->name()},
  181. {"service_class", ServiceClassName(service)},
  182. {"package", service->file()->package()}};
  183. printer.Print(vars,
  184. "static NSString *const kPackageName = @\"$package$\";\n");
  185. printer.Print(vars,
  186. "static NSString *const kServiceName = @\"$service_name$\";\n\n");
  187. printer.Print(vars, "@implementation $service_class$\n\n");
  188. printer.Print("// Designated initializer\n");
  189. printer.Print("- (instancetype)initWithHost:(NSString *)host {\n");
  190. printer.Print(" return (self = [super initWithHost:host"
  191. " packageName:kPackageName serviceName:kServiceName]);\n");
  192. printer.Print("}\n\n");
  193. printer.Print("// Override superclass initializer to disallow different"
  194. " package and service names.\n");
  195. printer.Print("- (instancetype)initWithHost:(NSString *)host\n");
  196. printer.Print(" packageName:(NSString *)packageName\n");
  197. printer.Print(" serviceName:(NSString *)serviceName {\n");
  198. printer.Print(" return [self initWithHost:host];\n");
  199. printer.Print("}\n\n\n");
  200. for (int i = 0; i < service->method_count(); i++) {
  201. PrintMethodImplementations(&printer, service->method(i));
  202. }
  203. printer.Print("@end\n");
  204. }
  205. return output;
  206. }
  207. } // namespace grpc_objective_c_generator