diff --git a/src/compiler/generator_helpers.h b/src/compiler/generator_helpers.h index 7ce4ec526c9..a232fcc9548 100644 --- a/src/compiler/generator_helpers.h +++ b/src/compiler/generator_helpers.h @@ -103,6 +103,14 @@ inline grpc::string CapitalizeFirstLetter(grpc::string s) { return s; } +inline grpc::string LowercaseFirstLetter(grpc::string s) { + if (s.empty()) { + return s; + } + s[0] = ::tolower(s[0]); + return s; +} + inline grpc::string LowerUnderscoreToUpperCamel(grpc::string str) { std::vector tokens = tokenize(str, "_"); grpc::string result = ""; diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc index c68c9c37c21..d1482a40d07 100644 --- a/src/compiler/objective_c_generator.cc +++ b/src/compiler/objective_c_generator.cc @@ -43,51 +43,87 @@ namespace grpc_objective_c_generator { namespace { -void PrintSimpleBlockSignature(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, - std::map *vars) { - (*vars)["method_name"] = method->name(); - (*vars)["request_type"] = PrefixedName(method->input_type()->name()); - (*vars)["response_type"] = PrefixedName(method->output_type()->name()); +using ::grpc::protobuf::io::Printer; +using ::grpc::protobuf::MethodDescriptor; +using ::std::map; +using ::grpc::string; + +void PrintProtoRpcDeclarationAsPragma(Printer *printer, + const MethodDescriptor *method, + map vars) { + vars["client_stream"] = method->client_streaming() ? "stream " : ""; + vars["server_stream"] = method->server_streaming() ? "stream " : ""; + + printer->Print(vars, + "#pragma mark $method_name$($client_stream$$request_type$)" + " returns ($server_stream$$response_type$)\n\n"); +} - if (method->server_streaming()) { - printer->Print("// When the response stream finishes, the handler is " - "called with nil for both arguments.\n\n"); +void PrintMethodSignature(Printer *printer, + const MethodDescriptor *method, + const map& vars) { + // TODO(jcanizales): Print method comments. + + printer->Print(vars, "- ($return_type$)$method_name$With"); + if (method->client_streaming()) { + printer->Print("RequestsWriter:(id)request"); } else { - printer->Print("// The handler is only called once.\n\n"); + printer->Print(vars, "Request:($prefix$$request_type$ *)request"); } - printer->Print(*vars, "- (id)$method_name$WithRequest:" - "($request_type$)request completionHandler:(void(^)" - "($response_type$ *, NSError *))handler"); + + // TODO(jcanizales): Put this on a new line and align colons. + printer->Print(" handler:(void(^)("); + if (method->server_streaming()) { + printer->Print("BOOL done, "); + } + printer->Print(vars, + "$prefix$$response_type$ *response, NSError *error))handler"); } -void PrintSimpleDelegateSignature(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, - std::map *vars) { - (*vars)["method_name"] = method->name(); - (*vars)["request_type"] = PrefixedName(method->input_type()->name()); +void PrintSimpleSignature(Printer *printer, + const MethodDescriptor *method, + map vars) { + vars["method_name"] = + grpc_generator::LowercaseFirstLetter(vars["method_name"]); + vars["return_type"] = "void"; + PrintMethodSignature(printer, method, vars); +} - printer->Print(*vars, "- (id)$method_name$WithRequest:" - "($request_type$)request delegate:(id)delegate"); +void PrintAdvancedSignature(Printer *printer, + const MethodDescriptor *method, + map vars) { + vars["method_name"] = "RPCTo" + vars["method_name"]; + vars["return_type"] = "ProtoRPC *"; + PrintMethodSignature(printer, method, vars); } -void PrintAdvancedSignature(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, - std::map *vars) { - (*vars)["method_name"] = method->name(); - printer->Print(*vars, "- (GRXSource *)$method_name$WithRequest:" - "(id)request"); +void PrintMethodDeclarations(Printer *printer, + const MethodDescriptor *method, + map vars) { + vars["method_name"] = method->name(); + vars["request_type"] = method->input_type()->name(); + vars["response_type"] = method->output_type()->name(); + + PrintProtoRpcDeclarationAsPragma(printer, method, vars); + + PrintSimpleSignature(printer, method, vars); + printer->Print(";\n\n"); + PrintAdvancedSignature(printer, method, vars); + printer->Print(";\n\n\n"); } -void PrintSourceMethodSimpleBlock(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, - std::map *vars) { - PrintSimpleBlockSignature(printer, method, vars); +void PrintSourceMethodSimpleBlock(Printer *printer, + const MethodDescriptor *method, + map vars) { + vars["method_name"] = method->name(); + vars["request_type"] = method->input_type()->name(); + vars["response_type"] = method->output_type()->name(); + + PrintSimpleSignature(printer, method, vars); - (*vars)["method_name"] = method->name(); printer->Print(" {\n"); printer->Indent(); - printer->Print(*vars, "return [[self $method_name$WithRequest:request] " + printer->Print(vars, "return [[self $method_name$WithRequest:request] " "connectHandler:^(id value, NSError *error) {\n"); printer->Indent(); printer->Print("handler(value, error);\n"); @@ -97,36 +133,25 @@ void PrintSourceMethodSimpleBlock(grpc::protobuf::io::Printer *printer, printer->Print("}\n"); } -void PrintSourceMethodSimpleDelegate(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, - std::map *vars) { - PrintSimpleDelegateSignature(printer, method, vars); +void PrintSourceMethodAdvanced(Printer *printer, + const MethodDescriptor *method, + map vars) { + vars["method_name"] = method->name(); + vars["request_type"] = method->input_type()->name(); + vars["response_type"] = method->output_type()->name(); - (*vars)["method_name"] = method->name(); - printer->Print(" {\n"); - printer->Indent(); - printer->Print(*vars, "return [[self $method_name$WithRequest:request]" - "connectToSink:delegate];\n"); - printer->Outdent(); - printer->Print("}\n"); -} - -void PrintSourceMethodAdvanced(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, - std::map *vars) { PrintAdvancedSignature(printer, method, vars); - (*vars)["method_name"] = method->name(); printer->Print(" {\n"); printer->Indent(); - printer->Print(*vars, "return [self $method_name$WithRequest:request " + printer->Print(vars, "return [self $method_name$WithRequest:request " "client:[self newClient]];\n"); printer->Outdent(); printer->Print("}\n"); } -void PrintSourceMethodHandler(grpc::protobuf::io::Printer *printer, - const grpc::protobuf::MethodDescriptor *method, +void PrintSourceMethodHandler(Printer *printer, + const MethodDescriptor *method, std::map *vars) { (*vars)["method_name"] = method->name(); (*vars)["response_type"] = PrefixedName(method->output_type()->name()); @@ -148,53 +173,42 @@ void PrintSourceMethodHandler(grpc::protobuf::io::Printer *printer, } grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service, - const grpc::string message_header) { + const string prefix) { grpc::string output; grpc::protobuf::io::StringOutputStream output_stream(&output); - grpc::protobuf::io::Printer printer(&output_stream, '$'); - std::map vars; - printer.Print("#import \"PBgRPCClient.h\"\n"); - printer.Print("#import \"PBStub.h\"\n"); - vars["message_header"] = message_header; - printer.Print(vars, "#import \"$message_header$\"\n\n"); - printer.Print("@protocol GRXSource\n"); - printer.Print("@class GRXSource\n\n"); - vars["service_name"] = service->name(); - printer.Print("@protocol $service_name$Stub \n\n"); - printer.Print("#pragma mark Simple block handlers\n\n"); - for (int i = 0; i < service->method_count(); i++) { - PrintSimpleBlockSignature(&printer, service->method(i), &vars); - printer.Print(";\n"); - } - printer.Print("\n"); - printer.Print("#pragma mark Simple delegate handlers.\n\n"); - printer.Print("# TODO(jcanizales): Use high-level snippets to remove this duplication."); - for (int i = 0; i < service->method_count(); i++) { - PrintSimpleDelegateSignature(&printer, service->method(i), &vars); - printer.Print(";\n"); - } - printer.Print("\n"); - printer.Print("#pragma mark Advanced handlers.\n\n"); + Printer printer(&output_stream, '$'); + + printer.Print("@protocol GRXWriteable;\n"); + printer.Print("@protocol GRXWriter;\n\n"); + + map vars = {{"service_name", service->name()}, + {"prefix", prefix}}; + printer.Print(vars, "@protocol $prefix$$service_name$ \n\n"); + for (int i = 0; i < service->method_count(); i++) { - PrintAdvancedSignature(&printer, service->method(i), &vars); - printer.Print(";\n"); + PrintMethodDeclarations(&printer, service->method(i), vars); } - printer.Print("\n"); printer.Print("@end\n\n"); - printer.Print("// Basic stub that only does marshalling and parsing\n"); - printer.Print(vars, "@interface $service_name$Stub :" - " PBStub<$service_name$Stub>\n"); - printer.Print("- (instancetype)initWithHost:(NSString *)host;\n"); + + printer.Print("// Basic service implementation, over gRPC, that only does" + " marshalling and parsing.\n"); + // use prefix + printer.Print(vars, "@interface RMT$service_name$ :" + " ProtoService\n"); + printer.Print("- (instancetype)initWithHost:(NSString *)host" + " NS_DESIGNATED_INITIALIZER;\n"); printer.Print("@end\n"); return output; } -grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service) { +grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service, + const string prefix) { grpc::string output; grpc::protobuf::io::StringOutputStream output_stream(&output); - grpc::protobuf::io::Printer printer(&output_stream, '$'); - std::map vars; - vars["service_name"] = service->name(); + Printer printer(&output_stream, '$'); + + map vars = {{"service_name", service->name()}, + {"prefix", prefix}}; printer.Print(vars, "#import \"$service_name$Stub.pb.h\"\n"); printer.Print("#import \"PBGeneratedMessage+GRXSource.h\"\n\n"); vars["full_name"] = service->full_name(); @@ -211,17 +225,12 @@ grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service) { printer.Print("}\n\n"); printer.Print("#pragma mark Simple block handlers.\n"); for (int i = 0; i < service->method_count(); i++) { - PrintSourceMethodSimpleBlock(&printer, service->method(i), &vars); - } - printer.Print("\n"); - printer.Print("#pragma mark Simple delegate handlers.\n"); - for (int i = 0; i < service->method_count(); i++) { - PrintSourceMethodSimpleDelegate(&printer, service->method(i), &vars); + PrintSourceMethodSimpleBlock(&printer, service->method(i), vars); } printer.Print("\n"); printer.Print("#pragma mark Advanced handlers.\n"); for (int i = 0; i < service->method_count(); i++) { - PrintSourceMethodAdvanced(&printer, service->method(i), &vars); + PrintSourceMethodAdvanced(&printer, service->method(i), vars); } printer.Print("\n"); printer.Print("#pragma mark Handlers for subclasses " diff --git a/src/compiler/objective_c_generator.h b/src/compiler/objective_c_generator.h index 93c730b34e4..e01724a7f7d 100644 --- a/src/compiler/objective_c_generator.h +++ b/src/compiler/objective_c_generator.h @@ -39,9 +39,10 @@ namespace grpc_objective_c_generator { grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service, - const grpc::string message_header); + const grpc::string prefix); -grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service); +grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service, + const grpc::string prefix); } // namespace grpc_objective_c_generator diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc index eebce0cd20d..ef32dcc0562 100644 --- a/src/compiler/objective_c_plugin.cc +++ b/src/compiler/objective_c_plugin.cc @@ -54,27 +54,29 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { return true; } + grpc::string file_name = grpc_generator::FileNameInUpperCamel(file); + grpc::string prefix = "RMT"; // TODO + for (int i = 0; i < file->service_count(); i++) { const grpc::protobuf::ServiceDescriptor *service = file->service(i); - grpc::string file_name = grpc_objective_c_generator::StubFileName( - service->name()); // Generate .pb.h - grpc::string header_code = grpc_objective_c_generator::GetHeader( - service, grpc_objective_c_generator::MessageHeaderName(file)); - std::unique_ptr header_output( - context->Open(file_name + ".pb.h")); - grpc::protobuf::io::CodedOutputStream header_coded_out( - header_output.get()); - header_coded_out.WriteRaw(header_code.data(), header_code.size()); + + Insert(context, file_name + ".pb.h", "imports", + "#import \n"); + + Insert(context, file_name + ".pb.h", "global_scope", + grpc_objective_c_generator::GetHeader(service, prefix)); // Generate .pb.m - grpc::string source_code = grpc_objective_c_generator::GetSource(service); - std::unique_ptr source_output( - context->Open(file_name + ".pb.m")); - grpc::protobuf::io::CodedOutputStream source_coded_out( - source_output.get()); - source_coded_out.WriteRaw(source_code.data(), source_code.size()); + + Insert(context, file_name + ".pb.m", "imports", + "#import \n" + "#import \n" + "#import \n"); + + Insert(context, file_name + ".pb.m", "global_scope", + grpc_objective_c_generator::GetSource(service, prefix)); } return true;