xref: /aosp_15_r20/external/grpc-grpc/src/compiler/objective_c_plugin.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1*cc02d7e2SAndroid Build Coastguard Worker /*
2*cc02d7e2SAndroid Build Coastguard Worker  *
3*cc02d7e2SAndroid Build Coastguard Worker  * Copyright 2015 gRPC authors.
4*cc02d7e2SAndroid Build Coastguard Worker  *
5*cc02d7e2SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*cc02d7e2SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*cc02d7e2SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
8*cc02d7e2SAndroid Build Coastguard Worker  *
9*cc02d7e2SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
10*cc02d7e2SAndroid Build Coastguard Worker  *
11*cc02d7e2SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*cc02d7e2SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*cc02d7e2SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*cc02d7e2SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*cc02d7e2SAndroid Build Coastguard Worker  * limitations under the License.
16*cc02d7e2SAndroid Build Coastguard Worker  *
17*cc02d7e2SAndroid Build Coastguard Worker  */
18*cc02d7e2SAndroid Build Coastguard Worker 
19*cc02d7e2SAndroid Build Coastguard Worker // Generates Objective C gRPC service interface out of Protobuf IDL.
20*cc02d7e2SAndroid Build Coastguard Worker 
21*cc02d7e2SAndroid Build Coastguard Worker #include <memory>
22*cc02d7e2SAndroid Build Coastguard Worker 
23*cc02d7e2SAndroid Build Coastguard Worker #include <google/protobuf/compiler/objectivec/names.h>
24*cc02d7e2SAndroid Build Coastguard Worker 
25*cc02d7e2SAndroid Build Coastguard Worker #include "src/compiler/config.h"
26*cc02d7e2SAndroid Build Coastguard Worker #include "src/compiler/objective_c_generator.h"
27*cc02d7e2SAndroid Build Coastguard Worker #include "src/compiler/objective_c_generator_helpers.h"
28*cc02d7e2SAndroid Build Coastguard Worker 
29*cc02d7e2SAndroid Build Coastguard Worker using ::google::protobuf::compiler::objectivec::
30*cc02d7e2SAndroid Build Coastguard Worker     IsProtobufLibraryBundledProtoFile;
31*cc02d7e2SAndroid Build Coastguard Worker using ::google::protobuf::compiler::objectivec::ProtobufLibraryFrameworkName;
32*cc02d7e2SAndroid Build Coastguard Worker #ifdef SUPPORT_OBJC_PREFIX_VALIDATION
33*cc02d7e2SAndroid Build Coastguard Worker using ::google::protobuf::compiler::objectivec::ValidateObjCClassPrefixes;
34*cc02d7e2SAndroid Build Coastguard Worker #endif
35*cc02d7e2SAndroid Build Coastguard Worker using ::grpc_objective_c_generator::FrameworkImport;
36*cc02d7e2SAndroid Build Coastguard Worker using ::grpc_objective_c_generator::LocalImport;
37*cc02d7e2SAndroid Build Coastguard Worker using ::grpc_objective_c_generator::PreprocIfElse;
38*cc02d7e2SAndroid Build Coastguard Worker using ::grpc_objective_c_generator::PreprocIfNot;
39*cc02d7e2SAndroid Build Coastguard Worker using ::grpc_objective_c_generator::SystemImport;
40*cc02d7e2SAndroid Build Coastguard Worker 
41*cc02d7e2SAndroid Build Coastguard Worker namespace {
42*cc02d7e2SAndroid Build Coastguard Worker 
ImportProtoHeaders(const grpc::protobuf::FileDescriptor * dep,const char * indent,const::std::string & framework,const::std::string & pb_runtime_import_prefix)43*cc02d7e2SAndroid Build Coastguard Worker inline ::std::string ImportProtoHeaders(
44*cc02d7e2SAndroid Build Coastguard Worker     const grpc::protobuf::FileDescriptor* dep, const char* indent,
45*cc02d7e2SAndroid Build Coastguard Worker     const ::std::string& framework,
46*cc02d7e2SAndroid Build Coastguard Worker     const ::std::string& pb_runtime_import_prefix) {
47*cc02d7e2SAndroid Build Coastguard Worker   ::std::string header = grpc_objective_c_generator::MessageHeaderName(dep);
48*cc02d7e2SAndroid Build Coastguard Worker 
49*cc02d7e2SAndroid Build Coastguard Worker   if (!IsProtobufLibraryBundledProtoFile(dep)) {
50*cc02d7e2SAndroid Build Coastguard Worker     if (framework.empty()) {
51*cc02d7e2SAndroid Build Coastguard Worker       return indent + LocalImport(header);
52*cc02d7e2SAndroid Build Coastguard Worker     } else {
53*cc02d7e2SAndroid Build Coastguard Worker       return indent + FrameworkImport(header, framework);
54*cc02d7e2SAndroid Build Coastguard Worker     }
55*cc02d7e2SAndroid Build Coastguard Worker   }
56*cc02d7e2SAndroid Build Coastguard Worker 
57*cc02d7e2SAndroid Build Coastguard Worker   ::std::string base_name = header;
58*cc02d7e2SAndroid Build Coastguard Worker   grpc_generator::StripPrefix(&base_name, "google/protobuf/");
59*cc02d7e2SAndroid Build Coastguard Worker   ::std::string file_name = "GPB" + base_name;
60*cc02d7e2SAndroid Build Coastguard Worker   // create the import code snippet
61*cc02d7e2SAndroid Build Coastguard Worker   ::std::string framework_header =
62*cc02d7e2SAndroid Build Coastguard Worker       ::std::string(ProtobufLibraryFrameworkName) + "/" + file_name;
63*cc02d7e2SAndroid Build Coastguard Worker   ::std::string local_header = file_name;
64*cc02d7e2SAndroid Build Coastguard Worker   if (!pb_runtime_import_prefix.empty()) {
65*cc02d7e2SAndroid Build Coastguard Worker     local_header = pb_runtime_import_prefix + "/" + file_name;
66*cc02d7e2SAndroid Build Coastguard Worker   }
67*cc02d7e2SAndroid Build Coastguard Worker 
68*cc02d7e2SAndroid Build Coastguard Worker   static const ::std::string kFrameworkImportsCondition =
69*cc02d7e2SAndroid Build Coastguard Worker       "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS";
70*cc02d7e2SAndroid Build Coastguard Worker   return PreprocIfElse(kFrameworkImportsCondition,
71*cc02d7e2SAndroid Build Coastguard Worker                        indent + SystemImport(framework_header),
72*cc02d7e2SAndroid Build Coastguard Worker                        indent + LocalImport(local_header));
73*cc02d7e2SAndroid Build Coastguard Worker }
74*cc02d7e2SAndroid Build Coastguard Worker 
75*cc02d7e2SAndroid Build Coastguard Worker }  // namespace
76*cc02d7e2SAndroid Build Coastguard Worker 
77*cc02d7e2SAndroid Build Coastguard Worker class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
78*cc02d7e2SAndroid Build Coastguard Worker  public:
ObjectiveCGrpcGenerator()79*cc02d7e2SAndroid Build Coastguard Worker   ObjectiveCGrpcGenerator() {}
~ObjectiveCGrpcGenerator()80*cc02d7e2SAndroid Build Coastguard Worker   virtual ~ObjectiveCGrpcGenerator() {}
81*cc02d7e2SAndroid Build Coastguard Worker 
82*cc02d7e2SAndroid Build Coastguard Worker  public:
GetSupportedFeatures() const83*cc02d7e2SAndroid Build Coastguard Worker   uint64_t GetSupportedFeatures() const override {
84*cc02d7e2SAndroid Build Coastguard Worker     return FEATURE_PROTO3_OPTIONAL
85*cc02d7e2SAndroid Build Coastguard Worker #ifdef GRPC_PROTOBUF_EDITION_SUPPORT
86*cc02d7e2SAndroid Build Coastguard Worker            | FEATURE_SUPPORTS_EDITIONS
87*cc02d7e2SAndroid Build Coastguard Worker #endif
88*cc02d7e2SAndroid Build Coastguard Worker         ;
89*cc02d7e2SAndroid Build Coastguard Worker   }
90*cc02d7e2SAndroid Build Coastguard Worker 
91*cc02d7e2SAndroid Build Coastguard Worker #ifdef GRPC_PROTOBUF_EDITION_SUPPORT
GetMinimumEdition() const92*cc02d7e2SAndroid Build Coastguard Worker   grpc::protobuf::Edition GetMinimumEdition() const override {
93*cc02d7e2SAndroid Build Coastguard Worker     return grpc::protobuf::Edition::EDITION_PROTO2;
94*cc02d7e2SAndroid Build Coastguard Worker   }
GetMaximumEdition() const95*cc02d7e2SAndroid Build Coastguard Worker   grpc::protobuf::Edition GetMaximumEdition() const override {
96*cc02d7e2SAndroid Build Coastguard Worker     return grpc::protobuf::Edition::EDITION_2023;
97*cc02d7e2SAndroid Build Coastguard Worker   }
98*cc02d7e2SAndroid Build Coastguard Worker #endif
99*cc02d7e2SAndroid Build Coastguard Worker 
Generate(const grpc::protobuf::FileDescriptor * file,const::std::string & parameter,grpc::protobuf::compiler::GeneratorContext * context,::std::string * error) const100*cc02d7e2SAndroid Build Coastguard Worker   virtual bool Generate(const grpc::protobuf::FileDescriptor* file,
101*cc02d7e2SAndroid Build Coastguard Worker                         const ::std::string& parameter,
102*cc02d7e2SAndroid Build Coastguard Worker                         grpc::protobuf::compiler::GeneratorContext* context,
103*cc02d7e2SAndroid Build Coastguard Worker                         ::std::string* error) const override {
104*cc02d7e2SAndroid Build Coastguard Worker     if (file->service_count() == 0) {
105*cc02d7e2SAndroid Build Coastguard Worker       // No services.  Do nothing.
106*cc02d7e2SAndroid Build Coastguard Worker       return true;
107*cc02d7e2SAndroid Build Coastguard Worker     }
108*cc02d7e2SAndroid Build Coastguard Worker 
109*cc02d7e2SAndroid Build Coastguard Worker #ifdef SUPPORT_OBJC_PREFIX_VALIDATION
110*cc02d7e2SAndroid Build Coastguard Worker     // Default options will use env variables for controls.
111*cc02d7e2SAndroid Build Coastguard Worker     if (!ValidateObjCClassPrefixes({file}, {}, error)) {
112*cc02d7e2SAndroid Build Coastguard Worker       return false;
113*cc02d7e2SAndroid Build Coastguard Worker     }
114*cc02d7e2SAndroid Build Coastguard Worker #endif
115*cc02d7e2SAndroid Build Coastguard Worker 
116*cc02d7e2SAndroid Build Coastguard Worker     bool grpc_local_import = false;
117*cc02d7e2SAndroid Build Coastguard Worker     ::std::string framework;
118*cc02d7e2SAndroid Build Coastguard Worker     ::std::string pb_runtime_import_prefix;
119*cc02d7e2SAndroid Build Coastguard Worker     ::std::string grpc_local_import_prefix;
120*cc02d7e2SAndroid Build Coastguard Worker     std::vector<::std::string> params_list =
121*cc02d7e2SAndroid Build Coastguard Worker         grpc_generator::tokenize(parameter, ",");
122*cc02d7e2SAndroid Build Coastguard Worker     for (auto param_str = params_list.begin(); param_str != params_list.end();
123*cc02d7e2SAndroid Build Coastguard Worker          ++param_str) {
124*cc02d7e2SAndroid Build Coastguard Worker       std::vector<::std::string> param =
125*cc02d7e2SAndroid Build Coastguard Worker           grpc_generator::tokenize(*param_str, "=");
126*cc02d7e2SAndroid Build Coastguard Worker       if (param[0] == "generate_for_named_framework") {
127*cc02d7e2SAndroid Build Coastguard Worker         if (param.size() != 2) {
128*cc02d7e2SAndroid Build Coastguard Worker           *error =
129*cc02d7e2SAndroid Build Coastguard Worker               std::string("Format: generate_for_named_framework=<Framework>");
130*cc02d7e2SAndroid Build Coastguard Worker           return false;
131*cc02d7e2SAndroid Build Coastguard Worker         } else if (param[1].empty()) {
132*cc02d7e2SAndroid Build Coastguard Worker           *error =
133*cc02d7e2SAndroid Build Coastguard Worker               std::string("Name of framework cannot be empty for parameter: ") +
134*cc02d7e2SAndroid Build Coastguard Worker               param[0];
135*cc02d7e2SAndroid Build Coastguard Worker           return false;
136*cc02d7e2SAndroid Build Coastguard Worker         }
137*cc02d7e2SAndroid Build Coastguard Worker         framework = param[1];
138*cc02d7e2SAndroid Build Coastguard Worker       } else if (param[0] == "runtime_import_prefix") {
139*cc02d7e2SAndroid Build Coastguard Worker         if (param.size() != 2) {
140*cc02d7e2SAndroid Build Coastguard Worker           *error = grpc::string("Format: runtime_import_prefix=dir/");
141*cc02d7e2SAndroid Build Coastguard Worker           return false;
142*cc02d7e2SAndroid Build Coastguard Worker         }
143*cc02d7e2SAndroid Build Coastguard Worker         pb_runtime_import_prefix = param[1];
144*cc02d7e2SAndroid Build Coastguard Worker         grpc_generator::StripSuffix(&pb_runtime_import_prefix, "/");
145*cc02d7e2SAndroid Build Coastguard Worker       } else if (param[0] == "grpc_local_import_prefix") {
146*cc02d7e2SAndroid Build Coastguard Worker         grpc_local_import = true;
147*cc02d7e2SAndroid Build Coastguard Worker         if (param.size() != 2) {
148*cc02d7e2SAndroid Build Coastguard Worker           *error = grpc::string("Format: grpc_local_import_prefix=dir/");
149*cc02d7e2SAndroid Build Coastguard Worker           return false;
150*cc02d7e2SAndroid Build Coastguard Worker         }
151*cc02d7e2SAndroid Build Coastguard Worker         grpc_local_import_prefix = param[1];
152*cc02d7e2SAndroid Build Coastguard Worker       }
153*cc02d7e2SAndroid Build Coastguard Worker     }
154*cc02d7e2SAndroid Build Coastguard Worker 
155*cc02d7e2SAndroid Build Coastguard Worker     static const ::std::string kNonNullBegin = "NS_ASSUME_NONNULL_BEGIN\n";
156*cc02d7e2SAndroid Build Coastguard Worker     static const ::std::string kNonNullEnd = "NS_ASSUME_NONNULL_END\n";
157*cc02d7e2SAndroid Build Coastguard Worker     static const ::std::string kProtocolOnly = "GPB_GRPC_PROTOCOL_ONLY";
158*cc02d7e2SAndroid Build Coastguard Worker     static const ::std::string kForwardDeclare =
159*cc02d7e2SAndroid Build Coastguard Worker         "GPB_GRPC_FORWARD_DECLARE_MESSAGE_PROTO";
160*cc02d7e2SAndroid Build Coastguard Worker 
161*cc02d7e2SAndroid Build Coastguard Worker     ::std::string file_name =
162*cc02d7e2SAndroid Build Coastguard Worker         google::protobuf::compiler::objectivec::FilePath(file);
163*cc02d7e2SAndroid Build Coastguard Worker 
164*cc02d7e2SAndroid Build Coastguard Worker     grpc_objective_c_generator::Parameters generator_params;
165*cc02d7e2SAndroid Build Coastguard Worker     generator_params.no_v1_compatibility = false;
166*cc02d7e2SAndroid Build Coastguard Worker 
167*cc02d7e2SAndroid Build Coastguard Worker     if (!parameter.empty()) {
168*cc02d7e2SAndroid Build Coastguard Worker       std::vector<std::string> parameters_list =
169*cc02d7e2SAndroid Build Coastguard Worker           grpc_generator::tokenize(parameter, ",");
170*cc02d7e2SAndroid Build Coastguard Worker       for (auto parameter_string = parameters_list.begin();
171*cc02d7e2SAndroid Build Coastguard Worker            parameter_string != parameters_list.end(); parameter_string++) {
172*cc02d7e2SAndroid Build Coastguard Worker         std::vector<std::string> param =
173*cc02d7e2SAndroid Build Coastguard Worker             grpc_generator::tokenize(*parameter_string, "=");
174*cc02d7e2SAndroid Build Coastguard Worker         if (param[0] == "no_v1_compatibility") {
175*cc02d7e2SAndroid Build Coastguard Worker           generator_params.no_v1_compatibility = true;
176*cc02d7e2SAndroid Build Coastguard Worker         }
177*cc02d7e2SAndroid Build Coastguard Worker       }
178*cc02d7e2SAndroid Build Coastguard Worker     }
179*cc02d7e2SAndroid Build Coastguard Worker 
180*cc02d7e2SAndroid Build Coastguard Worker     // Write out a file header.
181*cc02d7e2SAndroid Build Coastguard Worker     ::std::string file_header =
182*cc02d7e2SAndroid Build Coastguard Worker         "// Code generated by gRPC proto compiler.  DO NOT EDIT!\n"
183*cc02d7e2SAndroid Build Coastguard Worker         "// source: " +
184*cc02d7e2SAndroid Build Coastguard Worker         file->name() + "\n\n";
185*cc02d7e2SAndroid Build Coastguard Worker 
186*cc02d7e2SAndroid Build Coastguard Worker     {
187*cc02d7e2SAndroid Build Coastguard Worker       // Generate .pbrpc.h
188*cc02d7e2SAndroid Build Coastguard Worker 
189*cc02d7e2SAndroid Build Coastguard Worker       ::std::string imports;
190*cc02d7e2SAndroid Build Coastguard Worker       if (framework.empty()) {
191*cc02d7e2SAndroid Build Coastguard Worker         imports = LocalImport(file_name + ".pbobjc.h");
192*cc02d7e2SAndroid Build Coastguard Worker       } else {
193*cc02d7e2SAndroid Build Coastguard Worker         imports = FrameworkImport(file_name + ".pbobjc.h", framework);
194*cc02d7e2SAndroid Build Coastguard Worker       }
195*cc02d7e2SAndroid Build Coastguard Worker 
196*cc02d7e2SAndroid Build Coastguard Worker       ::std::string system_imports;
197*cc02d7e2SAndroid Build Coastguard Worker       if (grpc_local_import) {
198*cc02d7e2SAndroid Build Coastguard Worker         system_imports =
199*cc02d7e2SAndroid Build Coastguard Worker             LocalImport(grpc_local_import_prefix + "ProtoRPC/ProtoService.h");
200*cc02d7e2SAndroid Build Coastguard Worker         if (generator_params.no_v1_compatibility) {
201*cc02d7e2SAndroid Build Coastguard Worker           system_imports +=
202*cc02d7e2SAndroid Build Coastguard Worker               LocalImport(grpc_local_import_prefix + "ProtoRPC/ProtoRPC.h");
203*cc02d7e2SAndroid Build Coastguard Worker         } else {
204*cc02d7e2SAndroid Build Coastguard Worker           system_imports += LocalImport(grpc_local_import_prefix +
205*cc02d7e2SAndroid Build Coastguard Worker                                         "ProtoRPC/ProtoRPCLegacy.h");
206*cc02d7e2SAndroid Build Coastguard Worker           system_imports += LocalImport(grpc_local_import_prefix +
207*cc02d7e2SAndroid Build Coastguard Worker                                         "RxLibrary/GRXWriteable.h");
208*cc02d7e2SAndroid Build Coastguard Worker           system_imports +=
209*cc02d7e2SAndroid Build Coastguard Worker               LocalImport(grpc_local_import_prefix + "RxLibrary/GRXWriter.h");
210*cc02d7e2SAndroid Build Coastguard Worker         }
211*cc02d7e2SAndroid Build Coastguard Worker       } else {
212*cc02d7e2SAndroid Build Coastguard Worker         system_imports = SystemImport("ProtoRPC/ProtoService.h");
213*cc02d7e2SAndroid Build Coastguard Worker         if (generator_params.no_v1_compatibility) {
214*cc02d7e2SAndroid Build Coastguard Worker           system_imports += SystemImport("ProtoRPC/ProtoRPC.h");
215*cc02d7e2SAndroid Build Coastguard Worker         } else {
216*cc02d7e2SAndroid Build Coastguard Worker           system_imports += SystemImport("ProtoRPC/ProtoRPCLegacy.h");
217*cc02d7e2SAndroid Build Coastguard Worker           system_imports += SystemImport("RxLibrary/GRXWriteable.h");
218*cc02d7e2SAndroid Build Coastguard Worker           system_imports += SystemImport("RxLibrary/GRXWriter.h");
219*cc02d7e2SAndroid Build Coastguard Worker         }
220*cc02d7e2SAndroid Build Coastguard Worker       }
221*cc02d7e2SAndroid Build Coastguard Worker 
222*cc02d7e2SAndroid Build Coastguard Worker       ::std::string forward_declarations =
223*cc02d7e2SAndroid Build Coastguard Worker           "@class GRPCUnaryProtoCall;\n"
224*cc02d7e2SAndroid Build Coastguard Worker           "@class GRPCStreamingProtoCall;\n"
225*cc02d7e2SAndroid Build Coastguard Worker           "@class GRPCCallOptions;\n"
226*cc02d7e2SAndroid Build Coastguard Worker           "@protocol GRPCProtoResponseHandler;\n";
227*cc02d7e2SAndroid Build Coastguard Worker       if (!generator_params.no_v1_compatibility) {
228*cc02d7e2SAndroid Build Coastguard Worker         forward_declarations += "@class GRPCProtoCall;\n";
229*cc02d7e2SAndroid Build Coastguard Worker       }
230*cc02d7e2SAndroid Build Coastguard Worker       forward_declarations += "\n";
231*cc02d7e2SAndroid Build Coastguard Worker 
232*cc02d7e2SAndroid Build Coastguard Worker       ::std::string class_declarations =
233*cc02d7e2SAndroid Build Coastguard Worker           grpc_objective_c_generator::GetAllMessageClasses(file);
234*cc02d7e2SAndroid Build Coastguard Worker 
235*cc02d7e2SAndroid Build Coastguard Worker       ::std::string class_imports;
236*cc02d7e2SAndroid Build Coastguard Worker       for (int i = 0; i < file->dependency_count(); i++) {
237*cc02d7e2SAndroid Build Coastguard Worker         class_imports += ImportProtoHeaders(
238*cc02d7e2SAndroid Build Coastguard Worker             file->dependency(i), "  ", framework, pb_runtime_import_prefix);
239*cc02d7e2SAndroid Build Coastguard Worker       }
240*cc02d7e2SAndroid Build Coastguard Worker 
241*cc02d7e2SAndroid Build Coastguard Worker       ::std::string ng_protocols;
242*cc02d7e2SAndroid Build Coastguard Worker       for (int i = 0; i < file->service_count(); i++) {
243*cc02d7e2SAndroid Build Coastguard Worker         const grpc::protobuf::ServiceDescriptor* service = file->service(i);
244*cc02d7e2SAndroid Build Coastguard Worker         ng_protocols += grpc_objective_c_generator::GetV2Protocol(service);
245*cc02d7e2SAndroid Build Coastguard Worker       }
246*cc02d7e2SAndroid Build Coastguard Worker 
247*cc02d7e2SAndroid Build Coastguard Worker       ::std::string protocols;
248*cc02d7e2SAndroid Build Coastguard Worker       for (int i = 0; i < file->service_count(); i++) {
249*cc02d7e2SAndroid Build Coastguard Worker         const grpc::protobuf::ServiceDescriptor* service = file->service(i);
250*cc02d7e2SAndroid Build Coastguard Worker         protocols +=
251*cc02d7e2SAndroid Build Coastguard Worker             grpc_objective_c_generator::GetProtocol(service, generator_params);
252*cc02d7e2SAndroid Build Coastguard Worker       }
253*cc02d7e2SAndroid Build Coastguard Worker 
254*cc02d7e2SAndroid Build Coastguard Worker       ::std::string interfaces;
255*cc02d7e2SAndroid Build Coastguard Worker       for (int i = 0; i < file->service_count(); i++) {
256*cc02d7e2SAndroid Build Coastguard Worker         const grpc::protobuf::ServiceDescriptor* service = file->service(i);
257*cc02d7e2SAndroid Build Coastguard Worker         interfaces +=
258*cc02d7e2SAndroid Build Coastguard Worker             grpc_objective_c_generator::GetInterface(service, generator_params);
259*cc02d7e2SAndroid Build Coastguard Worker       }
260*cc02d7e2SAndroid Build Coastguard Worker 
261*cc02d7e2SAndroid Build Coastguard Worker       Write(context, file_name + ".pbrpc.h",
262*cc02d7e2SAndroid Build Coastguard Worker             file_header + SystemImport("Foundation/Foundation.h") + "\n" +
263*cc02d7e2SAndroid Build Coastguard Worker                 PreprocIfNot(kForwardDeclare, imports) + "\n" +
264*cc02d7e2SAndroid Build Coastguard Worker                 PreprocIfNot(kProtocolOnly, system_imports) + "\n" +
265*cc02d7e2SAndroid Build Coastguard Worker                 class_declarations + "\n" +
266*cc02d7e2SAndroid Build Coastguard Worker                 PreprocIfNot(kForwardDeclare, class_imports) + "\n" +
267*cc02d7e2SAndroid Build Coastguard Worker                 forward_declarations + "\n" + kNonNullBegin + "\n" +
268*cc02d7e2SAndroid Build Coastguard Worker                 ng_protocols + protocols + "\n" +
269*cc02d7e2SAndroid Build Coastguard Worker                 PreprocIfNot(kProtocolOnly, interfaces) + "\n" + kNonNullEnd +
270*cc02d7e2SAndroid Build Coastguard Worker                 "\n");
271*cc02d7e2SAndroid Build Coastguard Worker     }
272*cc02d7e2SAndroid Build Coastguard Worker 
273*cc02d7e2SAndroid Build Coastguard Worker     {
274*cc02d7e2SAndroid Build Coastguard Worker       // Generate .pbrpc.m
275*cc02d7e2SAndroid Build Coastguard Worker 
276*cc02d7e2SAndroid Build Coastguard Worker       ::std::string imports;
277*cc02d7e2SAndroid Build Coastguard Worker       if (framework.empty()) {
278*cc02d7e2SAndroid Build Coastguard Worker         imports = LocalImport(file_name + ".pbrpc.h") +
279*cc02d7e2SAndroid Build Coastguard Worker                   LocalImport(file_name + ".pbobjc.h");
280*cc02d7e2SAndroid Build Coastguard Worker       } else {
281*cc02d7e2SAndroid Build Coastguard Worker         imports = FrameworkImport(file_name + ".pbrpc.h", framework) +
282*cc02d7e2SAndroid Build Coastguard Worker                   FrameworkImport(file_name + ".pbobjc.h", framework);
283*cc02d7e2SAndroid Build Coastguard Worker       }
284*cc02d7e2SAndroid Build Coastguard Worker 
285*cc02d7e2SAndroid Build Coastguard Worker       if (grpc_local_import) {
286*cc02d7e2SAndroid Build Coastguard Worker         if (generator_params.no_v1_compatibility) {
287*cc02d7e2SAndroid Build Coastguard Worker           imports +=
288*cc02d7e2SAndroid Build Coastguard Worker               LocalImport(grpc_local_import_prefix + "ProtoRPC/ProtoRPC.h");
289*cc02d7e2SAndroid Build Coastguard Worker         } else {
290*cc02d7e2SAndroid Build Coastguard Worker           imports += LocalImport(grpc_local_import_prefix +
291*cc02d7e2SAndroid Build Coastguard Worker                                  "ProtoRPC/ProtoRPCLegacy.h");
292*cc02d7e2SAndroid Build Coastguard Worker           imports += LocalImport(grpc_local_import_prefix +
293*cc02d7e2SAndroid Build Coastguard Worker                                  "RxLibrary/GRXWriter+Immediate.h");
294*cc02d7e2SAndroid Build Coastguard Worker         }
295*cc02d7e2SAndroid Build Coastguard Worker       } else {
296*cc02d7e2SAndroid Build Coastguard Worker         if (generator_params.no_v1_compatibility) {
297*cc02d7e2SAndroid Build Coastguard Worker           imports += SystemImport("ProtoRPC/ProtoRPC.h");
298*cc02d7e2SAndroid Build Coastguard Worker         } else {
299*cc02d7e2SAndroid Build Coastguard Worker           imports += SystemImport("ProtoRPC/ProtoRPCLegacy.h");
300*cc02d7e2SAndroid Build Coastguard Worker           imports += SystemImport("RxLibrary/GRXWriter+Immediate.h");
301*cc02d7e2SAndroid Build Coastguard Worker         }
302*cc02d7e2SAndroid Build Coastguard Worker       }
303*cc02d7e2SAndroid Build Coastguard Worker 
304*cc02d7e2SAndroid Build Coastguard Worker       ::std::string class_imports;
305*cc02d7e2SAndroid Build Coastguard Worker       for (int i = 0; i < file->dependency_count(); i++) {
306*cc02d7e2SAndroid Build Coastguard Worker         class_imports += ImportProtoHeaders(file->dependency(i), "", framework,
307*cc02d7e2SAndroid Build Coastguard Worker                                             pb_runtime_import_prefix);
308*cc02d7e2SAndroid Build Coastguard Worker       }
309*cc02d7e2SAndroid Build Coastguard Worker 
310*cc02d7e2SAndroid Build Coastguard Worker       ::std::string definitions;
311*cc02d7e2SAndroid Build Coastguard Worker       for (int i = 0; i < file->service_count(); i++) {
312*cc02d7e2SAndroid Build Coastguard Worker         const grpc::protobuf::ServiceDescriptor* service = file->service(i);
313*cc02d7e2SAndroid Build Coastguard Worker         definitions +=
314*cc02d7e2SAndroid Build Coastguard Worker             grpc_objective_c_generator::GetSource(service, generator_params);
315*cc02d7e2SAndroid Build Coastguard Worker       }
316*cc02d7e2SAndroid Build Coastguard Worker 
317*cc02d7e2SAndroid Build Coastguard Worker       Write(context, file_name + ".pbrpc.m",
318*cc02d7e2SAndroid Build Coastguard Worker             file_header +
319*cc02d7e2SAndroid Build Coastguard Worker                 PreprocIfNot(kProtocolOnly, imports + "\n" + class_imports +
320*cc02d7e2SAndroid Build Coastguard Worker                                                 "\n" + definitions));
321*cc02d7e2SAndroid Build Coastguard Worker     }
322*cc02d7e2SAndroid Build Coastguard Worker 
323*cc02d7e2SAndroid Build Coastguard Worker     return true;
324*cc02d7e2SAndroid Build Coastguard Worker   }
325*cc02d7e2SAndroid Build Coastguard Worker 
326*cc02d7e2SAndroid Build Coastguard Worker  private:
327*cc02d7e2SAndroid Build Coastguard Worker   // Write the given code into the given file.
Write(grpc::protobuf::compiler::GeneratorContext * context,const::std::string & filename,const::std::string & code) const328*cc02d7e2SAndroid Build Coastguard Worker   void Write(grpc::protobuf::compiler::GeneratorContext* context,
329*cc02d7e2SAndroid Build Coastguard Worker              const ::std::string& filename, const ::std::string& code) const {
330*cc02d7e2SAndroid Build Coastguard Worker     std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
331*cc02d7e2SAndroid Build Coastguard Worker         context->Open(filename));
332*cc02d7e2SAndroid Build Coastguard Worker     grpc::protobuf::io::CodedOutputStream coded_out(output.get());
333*cc02d7e2SAndroid Build Coastguard Worker     coded_out.WriteRaw(code.data(), code.size());
334*cc02d7e2SAndroid Build Coastguard Worker   }
335*cc02d7e2SAndroid Build Coastguard Worker };
336*cc02d7e2SAndroid Build Coastguard Worker 
main(int argc,char * argv[])337*cc02d7e2SAndroid Build Coastguard Worker int main(int argc, char* argv[]) {
338*cc02d7e2SAndroid Build Coastguard Worker   ObjectiveCGrpcGenerator generator;
339*cc02d7e2SAndroid Build Coastguard Worker   return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
340*cc02d7e2SAndroid Build Coastguard Worker }
341