aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/compiler
diff options
context:
space:
mode:
authorGravatar Muxi Yan <muxi@users.noreply.github.com>2018-02-27 17:02:39 -0800
committerGravatar GitHub <noreply@github.com>2018-02-27 17:02:39 -0800
commitcab345efe666f03739e2ae7ef11696c486d47716 (patch)
tree3425f906366d51a14a05e45fa83189e47313ce49 /src/compiler
parent0a03beea7a0c1bced34c778d70e8937ddce5a6ea (diff)
parent3d35c5462077bc4f7091ad1150e93b2d108f7e42 (diff)
Merge pull request #14490 from nallohki/master
Updates Objective-C Generation to allow for omission of the generated @interface and @implementation
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/objective_c_generator.cc104
-rw-r--r--src/compiler/objective_c_generator.h10
-rw-r--r--src/compiler/objective_c_generator_helpers.h40
-rw-r--r--src/compiler/objective_c_plugin.cc145
4 files changed, 182 insertions, 117 deletions
diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc
index ab7d869758..ffdeb8f6b0 100644
--- a/src/compiler/objective_c_generator.cc
+++ b/src/compiler/objective_c_generator.cc
@@ -212,37 +212,49 @@ 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)}};
- printer.Print(vars, "@protocol $service_class$ <NSObject>\n\n");
+ // Scope the output stream so it closes and finalizes output to the string.
+ grpc::protobuf::io::StringOutputStream output_stream(&output);
+ Printer printer(&output_stream, '$');
- for (int i = 0; i < service->method_count(); i++) {
- PrintMethodDeclarations(&printer, service->method(i));
- }
- printer.Print("@end\n\n");
+ map< ::grpc::string, ::grpc::string> vars = {
+ {"service_class", ServiceClassName(service)}};
- 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 +270,32 @@ void PrintMethodImplementations(Printer* printer,
{"service_class", ServiceClassName(service)},
{"package", service->file()->package()}};
- printer.Print(vars, "@implementation $service_class$\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("// 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");
+ " 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_generator_helpers.h b/src/compiler/objective_c_generator_helpers.h
index 4004e6aef8..a284da97f4 100644
--- a/src/compiler/objective_c_generator_helpers.h
+++ b/src/compiler/objective_c_generator_helpers.h
@@ -40,5 +40,45 @@ inline string ServiceClassName(const ServiceDescriptor* service) {
string prefix = file->options().objc_class_prefix();
return prefix + service->name();
}
+
+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 PreprocConditional(::grpc::string symbol, bool invert) {
+ return invert ? "!defined(" + symbol + ") || !" + symbol
+ : "defined(" + symbol + ") && " + symbol;
+}
+
+inline ::grpc::string PreprocIf(const ::grpc::string& symbol,
+ const ::grpc::string& if_true) {
+ return ::grpc::string("#if " + PreprocConditional(symbol, false) + "\n" +
+ if_true + "#endif\n");
+}
+
+inline ::grpc::string PreprocIfNot(const ::grpc::string& symbol,
+ const ::grpc::string& if_true) {
+ return ::grpc::string("#if " + PreprocConditional(symbol, true) + "\n" +
+ if_true + "#endif\n");
+}
+
+inline ::grpc::string PreprocIfElse(const ::grpc::string& symbol,
+ const ::grpc::string& if_true,
+ const ::grpc::string& if_false) {
+ return ::grpc::string("#if " + PreprocConditional(symbol, false) + "\n" +
+ if_true + "#else\n" + if_false + "#endif\n");
+}
+
+inline ::grpc::string PreprocIfNotElse(const ::grpc::string& symbol,
+ const ::grpc::string& if_true,
+ const ::grpc::string& if_false) {
+ return ::grpc::string("#if " + PreprocConditional(symbol, true) + "\n" +
+ if_true + "#else\n" + if_false + "#endif\n");
+}
+
} // namespace grpc_objective_c_generator
#endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H
diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc
index d5d488e84d..76703d79cd 100644
--- a/src/compiler/objective_c_plugin.cc
+++ b/src/compiler/objective_c_plugin.cc
@@ -29,12 +29,42 @@
using ::google::protobuf::compiler::objectivec::
IsProtobufLibraryBundledProtoFile;
using ::google::protobuf::compiler::objectivec::ProtobufLibraryFrameworkName;
+using ::grpc_objective_c_generator::LocalImport;
+using ::grpc_objective_c_generator::PreprocIfElse;
+using ::grpc_objective_c_generator::PreprocIfNot;
+using ::grpc_objective_c_generator::SystemImport;
+
+namespace {
+
+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,
@@ -44,97 +74,68 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
return true;
}
+ static const ::grpc::string kNonNullBegin = "NS_ASSUME_NONNULL_BEGIN\n";
+ static const ::grpc::string kNonNullEnd = "NS_ASSUME_NONNULL_END\n";
+ static const ::grpc::string kProtocolOnly = "GPB_GRPC_PROTOCOL_ONLY";
+ static const ::grpc::string kForwardDeclare =
+ "GPB_GRPC_FORWARD_DECLARE_MESSAGE_PROTO";
+
::grpc::string file_name =
google::protobuf::compiler::objectivec::FilePath(file);
- ::grpc::string prefix = file->options().objc_class_prefix();
{
// 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);
+ PreprocIfNot(kForwardDeclare, imports) + "\n" +
+ PreprocIfNot(kProtocolOnly, system_imports) + "\n" +
+ PreprocIfElse(kForwardDeclare, class_declarations,
+ class_imports) +
+ "\n" + forward_declarations + "\n" + kNonNullBegin + "\n" +
+ protocols + "\n" + PreprocIfNot(kProtocolOnly, 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 +144,9 @@ 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",
+ PreprocIfNot(kProtocolOnly,
+ imports + "\n" + class_imports + "\n" + definitions));
}
return true;