diff options
author | Tyson Roberts <github@cabbits.net> | 2018-02-22 11:34:53 +0900 |
---|---|---|
committer | Tyson Roberts <github@cabbits.net> | 2018-02-22 11:34:53 +0900 |
commit | 8ff667855fe16dfa0d2fc9345bca572151ffa9fc (patch) | |
tree | 6caf432a1a194f1c249e70e875dab64460a9a4dc | |
parent | d555bd85435ea79f74a58c519dd71a5bb65c7f7a (diff) |
Updates Objective-C Generation to allow for ommission of the generated @interface and @implementation
-rw-r--r-- | src/compiler/objective_c_generator.cc | 107 | ||||
-rw-r--r-- | src/compiler/objective_c_generator.h | 10 | ||||
-rw-r--r-- | src/compiler/objective_c_plugin.cc | 168 |
3 files changed, 165 insertions, 120 deletions
diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc index ab7d869758..7c1c8d4f26 100644 --- a/src/compiler/objective_c_generator.cc +++ b/src/compiler/objective_c_generator.cc @@ -212,37 +212,48 @@ void PrintMethodImplementations(Printer* printer, return output; } -::grpc::string GetHeader(const ServiceDescriptor* service) { +::grpc::string GetProtocol(const ServiceDescriptor* service) { ::grpc::string output; - { - // Scope the output stream so it closes and finalizes output to the string. - grpc::protobuf::io::StringOutputStream output_stream(&output); - Printer printer(&output_stream, '$'); - map< ::grpc::string, ::grpc::string> vars = { - {"service_class", ServiceClassName(service)}}; + // Scope the output stream so it closes and finalizes output to the string. + grpc::protobuf::io::StringOutputStream output_stream(&output); + Printer printer(&output_stream, '$'); - printer.Print(vars, "@protocol $service_class$ <NSObject>\n\n"); + map< ::grpc::string, ::grpc::string> vars = { + {"service_class", ServiceClassName(service)}}; - for (int i = 0; i < service->method_count(); i++) { - PrintMethodDeclarations(&printer, service->method(i)); - } - printer.Print("@end\n\n"); - - printer.Print( - "/**\n" - " * Basic service implementation, over gRPC, that only does\n" - " * marshalling and parsing.\n" - " */\n"); - printer.Print(vars, - "@interface $service_class$ :" - " GRPCProtoService<$service_class$>\n"); - printer.Print( - "- (instancetype)initWithHost:(NSString *)host" - " NS_DESIGNATED_INITIALIZER;\n"); - printer.Print("+ (instancetype)serviceWithHost:(NSString *)host;\n"); - printer.Print("@end\n"); + printer.Print(vars, "@protocol $service_class$ <NSObject>\n\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintMethodDeclarations(&printer, service->method(i)); } + printer.Print("@end\n\n"); + + return output; +} + +::grpc::string GetInterface(const ServiceDescriptor* service) { + ::grpc::string output; + + // Scope the output stream so it closes and finalizes output to the string. + grpc::protobuf::io::StringOutputStream output_stream(&output); + Printer printer(&output_stream, '$'); + + map< ::grpc::string, ::grpc::string> vars = { + {"service_class", ServiceClassName(service)}}; + + printer.Print(vars, + "/**\n" + " * Basic service implementation, over gRPC, that only does\n" + " * marshalling and parsing.\n" + " */\n"); + printer.Print(vars, + "@interface $service_class$ :" + " GRPCProtoService<$service_class$>\n"); + printer.Print("- (instancetype)initWithHost:(NSString *)host" + " NS_DESIGNATED_INITIALIZER;\n"); + printer.Print("+ (instancetype)serviceWithHost:(NSString *)host;\n"); + printer.Print("@end\n"); + return output; } @@ -258,26 +269,30 @@ void PrintMethodImplementations(Printer* printer, {"service_class", ServiceClassName(service)}, {"package", service->file()->package()}}; - printer.Print(vars, "@implementation $service_class$\n\n"); - - printer.Print("// Designated initializer\n"); - printer.Print("- (instancetype)initWithHost:(NSString *)host {\n"); - printer.Print( - vars, - " return (self = [super initWithHost:host" - " packageName:@\"$package$\" serviceName:@\"$service_name$\"]);\n"); - printer.Print("}\n\n"); - printer.Print( - "// Override superclass initializer to disallow different" - " package and service names.\n"); - printer.Print("- (instancetype)initWithHost:(NSString *)host\n"); - printer.Print(" packageName:(NSString *)packageName\n"); - printer.Print(" serviceName:(NSString *)serviceName {\n"); - printer.Print(" return [self initWithHost:host];\n"); - printer.Print("}\n\n"); - printer.Print("+ (instancetype)serviceWithHost:(NSString *)host {\n"); - printer.Print(" return [[self alloc] initWithHost:host];\n"); - printer.Print("}\n\n\n"); + printer.Print(vars, + "@implementation $service_class$\n\n" + "// Designated initializer\n" + "- (instancetype)initWithHost:(NSString *)host {\n" + " self = [super initWithHost:host\n" + " packageName:@\"$package$\"\n" + " serviceName:@\"$service_name$\"];\n" + " return self;\n" + "}\n\n"); + + printer.Print("// Override superclass initializer to disallow different" + " package and service names.\n" + "- (instancetype)initWithHost:(NSString *)host\n" + " packageName:(NSString *)packageName\n" + " serviceName:(NSString *)serviceName {\n" + " return [self initWithHost:host];\n" + "}\n\n"); + + printer.Print("#pragma mark - Class Methods\n\n" + "+ (instancetype)serviceWithHost:(NSString *)host {\n" + " return [[self alloc] initWithHost:host];\n" + "}\n\n"); + + printer.Print("#pragma mark - Method Implementations\n\n"); for (int i = 0; i < service->method_count(); i++) { PrintMethodImplementations(&printer, service->method(i)); diff --git a/src/compiler/objective_c_generator.h b/src/compiler/objective_c_generator.h index d3aed76c4f..eb1c7ff005 100644 --- a/src/compiler/objective_c_generator.h +++ b/src/compiler/objective_c_generator.h @@ -31,9 +31,13 @@ using ::grpc::string; // Returns forward declaration of classes in the generated header file. string GetAllMessageClasses(const FileDescriptor* file); -// Returns the content to be included in the "global_scope" insertion point of -// the generated header file. -string GetHeader(const ServiceDescriptor* service); +// Returns the content to be included defining the @protocol segment at the +// insertion point of the generated implementation file. +string GetProtocol(const ServiceDescriptor* service); + +// Returns the content to be included defining the @interface segment at the +// insertion point of the generated implementation file. +string GetInterface(const ServiceDescriptor* service); // Returns the content to be included in the "global_scope" insertion point of // the generated implementation file. diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc index d5d488e84d..398bbc25a7 100644 --- a/src/compiler/objective_c_plugin.cc +++ b/src/compiler/objective_c_plugin.cc @@ -30,11 +30,58 @@ using ::google::protobuf::compiler::objectivec:: IsProtobufLibraryBundledProtoFile; using ::google::protobuf::compiler::objectivec::ProtobufLibraryFrameworkName; +namespace { + +inline ::grpc::string LocalImport(const ::grpc::string &import) { + return ::grpc::string("#import \"" + import + "\"\n"); +} + +inline ::grpc::string SystemImport(const ::grpc::string &import) { + return ::grpc::string("#import <" + import + ">\n"); +} + +inline ::grpc::string PreprocIf(const ::grpc::string& condition, + const ::grpc::string& if_true) { + return ::grpc::string("#if " + condition + "\n" + if_true + "#endif\n"); +} + +inline ::grpc::string PreprocIfElse(const ::grpc::string& condition, + const ::grpc::string& if_true, + const ::grpc::string& if_false) { + return ::grpc::string("#if " + condition + "\n" + + if_true + "#else\n" + if_false + "#endif\n"); +} + +inline ::grpc::string ImportProtoHeaders( + const grpc::protobuf::FileDescriptor* dep, + const char *indent) { + ::grpc::string header = grpc_objective_c_generator::MessageHeaderName(dep); + + if (!IsProtobufLibraryBundledProtoFile(dep)) { + return indent + LocalImport(header); + } + + ::grpc::string base_name = header; + grpc_generator::StripPrefix(&base_name, "google/protobuf/"); + // create the import code snippet + ::grpc::string framework_header = + ::grpc::string(ProtobufLibraryFrameworkName) + "/" + base_name; + + static const ::grpc::string kFrameworkImportsCondition = + "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS"; + return PreprocIfElse(kFrameworkImportsCondition, + indent + SystemImport(framework_header), + indent + LocalImport(header)); +} + +} // namespace + class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { public: ObjectiveCGrpcGenerator() {} virtual ~ObjectiveCGrpcGenerator() {} + public: virtual bool Generate(const grpc::protobuf::FileDescriptor* file, const ::grpc::string& parameter, grpc::protobuf::compiler::GeneratorContext* context, @@ -46,95 +93,70 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { ::grpc::string file_name = google::protobuf::compiler::objectivec::FilePath(file); - ::grpc::string prefix = file->options().objc_class_prefix(); + static const ::grpc::string kNonNullBegin = "NS_ASSUME_NONNULL_BEGIN\n"; + static const ::grpc::string kNonNullEnd = "NS_ASSUME_NONNULL_END\n"; + static const ::grpc::string kForwardDeclareCondition = + "GPB_GRPC_FORWARD_DECLARE_MESSAGE_PROTO"; + static const ::grpc::string kOmitInterfaceCondition = + "GPB_GRPC_OMIT_INTERFACE"; { // Generate .pbrpc.h - ::grpc::string imports = - ::grpc::string("#if !GPB_GRPC_FORWARD_DECLARE_MESSAGE_PROTO\n") + - "#import \"" + file_name + - ".pbobjc.h\"\n" - "#endif\n\n" - "#import <ProtoRPC/ProtoService.h>\n" - "#import <ProtoRPC/ProtoRPC.h>\n" - "#import <RxLibrary/GRXWriteable.h>\n" - "#import <RxLibrary/GRXWriter.h>\n"; - - ::grpc::string proto_imports; - proto_imports += "#if GPB_GRPC_FORWARD_DECLARE_MESSAGE_PROTO\n" + - grpc_objective_c_generator::GetAllMessageClasses(file) + - "#else\n"; + ::grpc::string imports = LocalImport(file_name + ".pbobjc.h"); + + ::grpc::string system_imports = + SystemImport("ProtoRPC/ProtoService.h") + + SystemImport("ProtoRPC/ProtoRPC.h") + + SystemImport("RxLibrary/GRXWriteable.h") + + SystemImport("RxLibrary/GRXWriter.h"); + + ::grpc::string forward_declarations = "@class GRPCProtoCall;\n\n"; + + ::grpc::string class_declarations = + grpc_objective_c_generator::GetAllMessageClasses(file); + + ::grpc::string class_imports; for (int i = 0; i < file->dependency_count(); i++) { - ::grpc::string header = - grpc_objective_c_generator::MessageHeaderName(file->dependency(i)); - const grpc::protobuf::FileDescriptor* dependency = file->dependency(i); - if (IsProtobufLibraryBundledProtoFile(dependency)) { - ::grpc::string base_name = header; - grpc_generator::StripPrefix(&base_name, "google/protobuf/"); - // create the import code snippet - proto_imports += - " #if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS\n" - " #import <" + - ::grpc::string(ProtobufLibraryFrameworkName) + "/" + base_name + - ">\n" - " #else\n" - " #import \"" + - header + - "\"\n" - " #endif\n"; - } else { - proto_imports += ::grpc::string(" #import \"") + header + "\"\n"; - } + class_imports += ImportProtoHeaders(file->dependency(i), " "); } - proto_imports += "#endif\n"; - ::grpc::string declarations; + ::grpc::string protocols; for (int i = 0; i < file->service_count(); i++) { const grpc::protobuf::ServiceDescriptor* service = file->service(i); - declarations += grpc_objective_c_generator::GetHeader(service); + protocols += grpc_objective_c_generator::GetProtocol(service); } - static const ::grpc::string kNonNullBegin = - "\nNS_ASSUME_NONNULL_BEGIN\n\n"; - static const ::grpc::string kNonNullEnd = "\nNS_ASSUME_NONNULL_END\n"; + ::grpc::string interfaces; + for (int i = 0; i < file->service_count(); i++) { + const grpc::protobuf::ServiceDescriptor* service = file->service(i); + interfaces += grpc_objective_c_generator::GetInterface(service); + } Write(context, file_name + ".pbrpc.h", - imports + '\n' + proto_imports + '\n' + kNonNullBegin + - declarations + kNonNullEnd); + PreprocIf("!" + kForwardDeclareCondition, imports) + "\n" + + PreprocIf("!" + kOmitInterfaceCondition, system_imports) + "\n" + + PreprocIfElse(kForwardDeclareCondition, + class_declarations, class_imports) + "\n" + + forward_declarations + "\n" + + kNonNullBegin + "\n" + + protocols + "\n" + + PreprocIf("!" + kOmitInterfaceCondition, interfaces) + "\n" + + kNonNullEnd + "\n"); } { // Generate .pbrpc.m - ::grpc::string imports = ::grpc::string("#import \"") + file_name + - ".pbrpc.h\"\n" - "#import \"" + - file_name + - ".pbobjc.h\"\n\n" - "#import <ProtoRPC/ProtoRPC.h>\n" - "#import <RxLibrary/GRXWriter+Immediate.h>\n"; + ::grpc::string imports = + LocalImport(file_name + ".pbrpc.h") + + LocalImport(file_name + ".pbobjc.h") + + SystemImport("ProtoRPC/ProtoRPC.h") + + SystemImport("RxLibrary/GRXWriter+Immediate.h"); + + ::grpc::string class_imports; for (int i = 0; i < file->dependency_count(); i++) { - ::grpc::string header = - grpc_objective_c_generator::MessageHeaderName(file->dependency(i)); - const grpc::protobuf::FileDescriptor* dependency = file->dependency(i); - if (IsProtobufLibraryBundledProtoFile(dependency)) { - ::grpc::string base_name = header; - grpc_generator::StripPrefix(&base_name, "google/protobuf/"); - // create the import code snippet - imports += - "#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS\n" - " #import <" + - ::grpc::string(ProtobufLibraryFrameworkName) + "/" + base_name + - ">\n" - "#else\n" - " #import \"" + - header + - "\"\n" - "#endif\n"; - } else { - imports += ::grpc::string("#import \"") + header + "\"\n"; - } + class_imports += ImportProtoHeaders(file->dependency(i), ""); } ::grpc::string definitions; @@ -143,7 +165,11 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { definitions += grpc_objective_c_generator::GetSource(service); } - Write(context, file_name + ".pbrpc.m", imports + '\n' + definitions); + Write(context, file_name + ".pbrpc.m", + PreprocIf("!" + kOmitInterfaceCondition, + imports + "\n" + + class_imports + "\n" + + definitions)); } return true; |