blob: 53ff81f94a4a88cc55d2a98051307a2006311717 [file] [log] [blame]
murgatroid99d3efd0a2015-04-07 11:40:29 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
murgatroid99d3efd0a2015-04-07 11:40:29 -07004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * 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
murgatroid99d3efd0a2015-04-07 11:40:29 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
murgatroid99d3efd0a2015-04-07 11:40:29 -070010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * 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.
murgatroid99d3efd0a2015-04-07 11:40:29 -070016 *
17 */
18
19// Generates Objective C gRPC service interface out of Protobuf IDL.
20
21#include <memory>
22
23#include "src/compiler/config.h"
24#include "src/compiler/objective_c_generator.h"
25#include "src/compiler/objective_c_generator_helpers.h"
26
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -070027#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
28
Masood Malekghassemiac592452016-07-01 11:58:04 -070029using ::google::protobuf::compiler::objectivec::
30 IsProtobufLibraryBundledProtoFile;
Craig Tillerbaa14a92017-11-03 09:09:36 -070031using ::google::protobuf::compiler::objectivec::ProtobufLibraryFrameworkName;
Makarand Dharmapurikar46cc9ee2016-07-08 11:42:07 -070032
murgatroid99d3efd0a2015-04-07 11:40:29 -070033class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
34 public:
35 ObjectiveCGrpcGenerator() {}
36 virtual ~ObjectiveCGrpcGenerator() {}
37
Craig Tillerbaa14a92017-11-03 09:09:36 -070038 virtual bool Generate(const grpc::protobuf::FileDescriptor* file,
39 const ::grpc::string& parameter,
40 grpc::protobuf::compiler::GeneratorContext* context,
41 ::grpc::string* error) const {
murgatroid99d3efd0a2015-04-07 11:40:29 -070042 if (file->service_count() == 0) {
43 // No services. Do nothing.
44 return true;
45 }
46
Muxi Yand0442812017-06-08 10:06:39 -070047 ::grpc::string file_name =
48 google::protobuf::compiler::objectivec::FilePath(file);
Jorge Canizalesb015dfb2015-08-13 18:41:29 -070049 ::grpc::string prefix = file->options().objc_class_prefix();
Jorge Canizales9a065d22015-04-27 00:05:01 -070050
Jorge Canizales1900dfc2015-05-15 09:44:04 -070051 {
52 // Generate .pbrpc.h
murgatroid99d3efd0a2015-04-07 11:40:29 -070053
Jorge Canizalesb015dfb2015-08-13 18:41:29 -070054 ::grpc::string imports = ::grpc::string("#import \"") + file_name +
Masood Malekghassemiac592452016-07-01 11:58:04 -070055 ".pbobjc.h\"\n\n"
56 "#import <ProtoRPC/ProtoService.h>\n"
Muxi Yan56369ea2017-04-06 11:52:43 -070057 "#import <ProtoRPC/ProtoRPC.h>\n"
Masood Malekghassemiac592452016-07-01 11:58:04 -070058 "#import <RxLibrary/GRXWriteable.h>\n"
59 "#import <RxLibrary/GRXWriter.h>\n";
Jorge Canizales9a065d22015-04-27 00:05:01 -070060
Jorge Canizalesb015dfb2015-08-13 18:41:29 -070061 ::grpc::string proto_imports;
Muxi Yan75271d72017-09-18 17:30:20 -070062 proto_imports += "#if GPB_GRPC_FORWARD_DECLARE_MESSAGE_PROTO\n" +
63 grpc_objective_c_generator::GetAllMessageClasses(file) +
64 "#else\n";
Jorge Canizales1900dfc2015-05-15 09:44:04 -070065 for (int i = 0; i < file->dependency_count(); i++) {
Masood Malekghassemiac592452016-07-01 11:58:04 -070066 ::grpc::string header =
67 grpc_objective_c_generator::MessageHeaderName(file->dependency(i));
Craig Tillerbaa14a92017-11-03 09:09:36 -070068 const grpc::protobuf::FileDescriptor* dependency = file->dependency(i);
Makarand Dharmapurikar46cc9ee2016-07-08 11:42:07 -070069 if (IsProtobufLibraryBundledProtoFile(dependency)) {
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -070070 ::grpc::string base_name = header;
71 grpc_generator::StripPrefix(&base_name, "google/protobuf/");
Makarand Dharmapurikar77f8da22016-07-08 15:03:20 -070072 // create the import code snippet
Makarand Dharmapurikar2b220f82016-07-08 10:47:57 -070073 proto_imports +=
Muxi Yan75271d72017-09-18 17:30:20 -070074 " #if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS\n"
75 " #import <" +
Masood Malekghassemiac592452016-07-01 11:58:04 -070076 ::grpc::string(ProtobufLibraryFrameworkName) + "/" + base_name +
77 ">\n"
Muxi Yan75271d72017-09-18 17:30:20 -070078 " #else\n"
79 " #import \"" +
Masood Malekghassemiac592452016-07-01 11:58:04 -070080 header +
81 "\"\n"
Muxi Yan75271d72017-09-18 17:30:20 -070082 " #endif\n";
Makarand Dharmapurikar86202522016-07-08 12:41:12 -070083 } else {
Muxi Yan75271d72017-09-18 17:30:20 -070084 proto_imports += ::grpc::string(" #import \"") + header + "\"\n";
Makarand Dharmapurikar86202522016-07-08 12:41:12 -070085 }
Jorge Canizales1a7918b2015-05-13 12:04:03 -070086 }
Muxi Yan75271d72017-09-18 17:30:20 -070087 proto_imports += "#endif\n";
Jorge Canizales9a065d22015-04-27 00:05:01 -070088
Jorge Canizalesb015dfb2015-08-13 18:41:29 -070089 ::grpc::string declarations;
Jorge Canizales1900dfc2015-05-15 09:44:04 -070090 for (int i = 0; i < file->service_count(); i++) {
Craig Tillerbaa14a92017-11-03 09:09:36 -070091 const grpc::protobuf::ServiceDescriptor* service = file->service(i);
Jorge Canizales52592fc2015-05-26 11:53:31 -070092 declarations += grpc_objective_c_generator::GetHeader(service);
Jorge Canizales1a7918b2015-05-13 12:04:03 -070093 }
Jorge Canizales1900dfc2015-05-15 09:44:04 -070094
Masood Malekghassemiac592452016-07-01 11:58:04 -070095 static const ::grpc::string kNonNullBegin =
96 "\nNS_ASSUME_NONNULL_BEGIN\n\n";
Benjamin Herzog1843ccb2016-04-27 17:39:26 +020097 static const ::grpc::string kNonNullEnd = "\nNS_ASSUME_NONNULL_END\n";
Benjamin Herzog208795c2016-04-18 18:10:14 +020098
Craig Tillerbaa14a92017-11-03 09:09:36 -070099 Write(context, file_name + ".pbrpc.h",
100 imports + '\n' + proto_imports + '\n' + kNonNullBegin +
101 declarations + kNonNullEnd);
Jorge Canizales1900dfc2015-05-15 09:44:04 -0700102 }
103
104 {
105 // Generate .pbrpc.m
106
Jorge Canizalesb015dfb2015-08-13 18:41:29 -0700107 ::grpc::string imports = ::grpc::string("#import \"") + file_name +
Masood Malekghassemiac592452016-07-01 11:58:04 -0700108 ".pbrpc.h\"\n\n"
109 "#import <ProtoRPC/ProtoRPC.h>\n"
110 "#import <RxLibrary/GRXWriter+Immediate.h>\n";
Muxi Yan1e32fea2017-09-19 09:46:12 -0700111 for (int i = 0; i < file->dependency_count(); i++) {
112 ::grpc::string header =
113 grpc_objective_c_generator::MessageHeaderName(file->dependency(i));
Craig Tillerbaa14a92017-11-03 09:09:36 -0700114 const grpc::protobuf::FileDescriptor* dependency = file->dependency(i);
Muxi Yan1e32fea2017-09-19 09:46:12 -0700115 if (IsProtobufLibraryBundledProtoFile(dependency)) {
116 ::grpc::string base_name = header;
117 grpc_generator::StripPrefix(&base_name, "google/protobuf/");
118 // create the import code snippet
119 imports +=
120 "#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS\n"
121 " #import <" +
122 ::grpc::string(ProtobufLibraryFrameworkName) + "/" + base_name +
123 ">\n"
124 "#else\n"
125 " #import \"" +
126 header +
127 "\"\n"
128 "#endif\n";
129 } else {
130 imports += ::grpc::string("#import \"") + header + "\"\n";
131 }
132 }
Jorge Canizales1900dfc2015-05-15 09:44:04 -0700133
Jorge Canizalesb015dfb2015-08-13 18:41:29 -0700134 ::grpc::string definitions;
Jorge Canizales1900dfc2015-05-15 09:44:04 -0700135 for (int i = 0; i < file->service_count(); i++) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700136 const grpc::protobuf::ServiceDescriptor* service = file->service(i);
Jorge Canizales52592fc2015-05-26 11:53:31 -0700137 definitions += grpc_objective_c_generator::GetSource(service);
Jorge Canizales1900dfc2015-05-15 09:44:04 -0700138 }
139
140 Write(context, file_name + ".pbrpc.m", imports + '\n' + definitions);
murgatroid99d3efd0a2015-04-07 11:40:29 -0700141 }
142
143 return true;
144 }
145
146 private:
Jorge Canizales1a7918b2015-05-13 12:04:03 -0700147 // Write the given code into the given file.
Craig Tillerbaa14a92017-11-03 09:09:36 -0700148 void Write(grpc::protobuf::compiler::GeneratorContext* context,
149 const ::grpc::string& filename, const ::grpc::string& code) const {
Jorge Canizales1a7918b2015-05-13 12:04:03 -0700150 std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
151 context->Open(filename));
152 grpc::protobuf::io::CodedOutputStream coded_out(output.get());
153 coded_out.WriteRaw(code.data(), code.size());
154 }
murgatroid99d3efd0a2015-04-07 11:40:29 -0700155};
156
Craig Tillerbaa14a92017-11-03 09:09:36 -0700157int main(int argc, char* argv[]) {
murgatroid99d3efd0a2015-04-07 11:40:29 -0700158 ObjectiveCGrpcGenerator generator;
159 return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
160}