xref: /aosp_15_r20/external/grpc-grpc/src/compiler/generator_helpers.h (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 #ifndef GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H
20*cc02d7e2SAndroid Build Coastguard Worker #define GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H
21*cc02d7e2SAndroid Build Coastguard Worker 
22*cc02d7e2SAndroid Build Coastguard Worker #include <iostream>
23*cc02d7e2SAndroid Build Coastguard Worker #include <map>
24*cc02d7e2SAndroid Build Coastguard Worker #include <sstream>
25*cc02d7e2SAndroid Build Coastguard Worker #include <string>
26*cc02d7e2SAndroid Build Coastguard Worker #include <vector>
27*cc02d7e2SAndroid Build Coastguard Worker 
28*cc02d7e2SAndroid Build Coastguard Worker #include "src/compiler/config.h"
29*cc02d7e2SAndroid Build Coastguard Worker #include "src/compiler/proto_parser_helper.h"
30*cc02d7e2SAndroid Build Coastguard Worker 
31*cc02d7e2SAndroid Build Coastguard Worker namespace grpc_generator {
32*cc02d7e2SAndroid Build Coastguard Worker 
StripSuffix(std::string * filename,const std::string & suffix)33*cc02d7e2SAndroid Build Coastguard Worker inline bool StripSuffix(std::string* filename, const std::string& suffix) {
34*cc02d7e2SAndroid Build Coastguard Worker   if (filename->length() >= suffix.length()) {
35*cc02d7e2SAndroid Build Coastguard Worker     size_t suffix_pos = filename->length() - suffix.length();
36*cc02d7e2SAndroid Build Coastguard Worker     if (filename->compare(suffix_pos, std::string::npos, suffix) == 0) {
37*cc02d7e2SAndroid Build Coastguard Worker       filename->resize(filename->size() - suffix.size());
38*cc02d7e2SAndroid Build Coastguard Worker       return true;
39*cc02d7e2SAndroid Build Coastguard Worker     }
40*cc02d7e2SAndroid Build Coastguard Worker   }
41*cc02d7e2SAndroid Build Coastguard Worker 
42*cc02d7e2SAndroid Build Coastguard Worker   return false;
43*cc02d7e2SAndroid Build Coastguard Worker }
44*cc02d7e2SAndroid Build Coastguard Worker 
StripPrefix(std::string * name,const std::string & prefix)45*cc02d7e2SAndroid Build Coastguard Worker inline bool StripPrefix(std::string* name, const std::string& prefix) {
46*cc02d7e2SAndroid Build Coastguard Worker   if (name->length() >= prefix.length()) {
47*cc02d7e2SAndroid Build Coastguard Worker     if (name->substr(0, prefix.size()) == prefix) {
48*cc02d7e2SAndroid Build Coastguard Worker       *name = name->substr(prefix.size());
49*cc02d7e2SAndroid Build Coastguard Worker       return true;
50*cc02d7e2SAndroid Build Coastguard Worker     }
51*cc02d7e2SAndroid Build Coastguard Worker   }
52*cc02d7e2SAndroid Build Coastguard Worker   return false;
53*cc02d7e2SAndroid Build Coastguard Worker }
54*cc02d7e2SAndroid Build Coastguard Worker 
StripProto(std::string filename)55*cc02d7e2SAndroid Build Coastguard Worker inline std::string StripProto(std::string filename) {
56*cc02d7e2SAndroid Build Coastguard Worker   if (!StripSuffix(&filename, ".protodevel")) {
57*cc02d7e2SAndroid Build Coastguard Worker     StripSuffix(&filename, ".proto");
58*cc02d7e2SAndroid Build Coastguard Worker   }
59*cc02d7e2SAndroid Build Coastguard Worker   return filename;
60*cc02d7e2SAndroid Build Coastguard Worker }
61*cc02d7e2SAndroid Build Coastguard Worker 
StringReplace(std::string str,const std::string & from,const std::string & to,bool replace_all)62*cc02d7e2SAndroid Build Coastguard Worker inline std::string StringReplace(std::string str, const std::string& from,
63*cc02d7e2SAndroid Build Coastguard Worker                                  const std::string& to, bool replace_all) {
64*cc02d7e2SAndroid Build Coastguard Worker   size_t pos = 0;
65*cc02d7e2SAndroid Build Coastguard Worker 
66*cc02d7e2SAndroid Build Coastguard Worker   do {
67*cc02d7e2SAndroid Build Coastguard Worker     pos = str.find(from, pos);
68*cc02d7e2SAndroid Build Coastguard Worker     if (pos == std::string::npos) {
69*cc02d7e2SAndroid Build Coastguard Worker       break;
70*cc02d7e2SAndroid Build Coastguard Worker     }
71*cc02d7e2SAndroid Build Coastguard Worker     str.replace(pos, from.length(), to);
72*cc02d7e2SAndroid Build Coastguard Worker     pos += to.length();
73*cc02d7e2SAndroid Build Coastguard Worker   } while (replace_all);
74*cc02d7e2SAndroid Build Coastguard Worker 
75*cc02d7e2SAndroid Build Coastguard Worker   return str;
76*cc02d7e2SAndroid Build Coastguard Worker }
77*cc02d7e2SAndroid Build Coastguard Worker 
StringReplace(std::string str,const std::string & from,const std::string & to)78*cc02d7e2SAndroid Build Coastguard Worker inline std::string StringReplace(std::string str, const std::string& from,
79*cc02d7e2SAndroid Build Coastguard Worker                                  const std::string& to) {
80*cc02d7e2SAndroid Build Coastguard Worker   return StringReplace(str, from, to, true);
81*cc02d7e2SAndroid Build Coastguard Worker }
82*cc02d7e2SAndroid Build Coastguard Worker 
tokenize(const std::string & input,const std::string & delimiters)83*cc02d7e2SAndroid Build Coastguard Worker inline std::vector<std::string> tokenize(const std::string& input,
84*cc02d7e2SAndroid Build Coastguard Worker                                          const std::string& delimiters) {
85*cc02d7e2SAndroid Build Coastguard Worker   std::vector<std::string> tokens;
86*cc02d7e2SAndroid Build Coastguard Worker   size_t pos, last_pos = 0;
87*cc02d7e2SAndroid Build Coastguard Worker 
88*cc02d7e2SAndroid Build Coastguard Worker   for (;;) {
89*cc02d7e2SAndroid Build Coastguard Worker     bool done = false;
90*cc02d7e2SAndroid Build Coastguard Worker     pos = input.find_first_of(delimiters, last_pos);
91*cc02d7e2SAndroid Build Coastguard Worker     if (pos == std::string::npos) {
92*cc02d7e2SAndroid Build Coastguard Worker       done = true;
93*cc02d7e2SAndroid Build Coastguard Worker       pos = input.length();
94*cc02d7e2SAndroid Build Coastguard Worker     }
95*cc02d7e2SAndroid Build Coastguard Worker 
96*cc02d7e2SAndroid Build Coastguard Worker     tokens.push_back(input.substr(last_pos, pos - last_pos));
97*cc02d7e2SAndroid Build Coastguard Worker     if (done) return tokens;
98*cc02d7e2SAndroid Build Coastguard Worker 
99*cc02d7e2SAndroid Build Coastguard Worker     last_pos = pos + 1;
100*cc02d7e2SAndroid Build Coastguard Worker   }
101*cc02d7e2SAndroid Build Coastguard Worker }
102*cc02d7e2SAndroid Build Coastguard Worker 
CapitalizeFirstLetter(std::string s)103*cc02d7e2SAndroid Build Coastguard Worker inline std::string CapitalizeFirstLetter(std::string s) {
104*cc02d7e2SAndroid Build Coastguard Worker   if (s.empty()) {
105*cc02d7e2SAndroid Build Coastguard Worker     return s;
106*cc02d7e2SAndroid Build Coastguard Worker   }
107*cc02d7e2SAndroid Build Coastguard Worker   s[0] = ::toupper(s[0]);
108*cc02d7e2SAndroid Build Coastguard Worker   return s;
109*cc02d7e2SAndroid Build Coastguard Worker }
110*cc02d7e2SAndroid Build Coastguard Worker 
LowercaseFirstLetter(std::string s)111*cc02d7e2SAndroid Build Coastguard Worker inline std::string LowercaseFirstLetter(std::string s) {
112*cc02d7e2SAndroid Build Coastguard Worker   if (s.empty()) {
113*cc02d7e2SAndroid Build Coastguard Worker     return s;
114*cc02d7e2SAndroid Build Coastguard Worker   }
115*cc02d7e2SAndroid Build Coastguard Worker   s[0] = ::tolower(s[0]);
116*cc02d7e2SAndroid Build Coastguard Worker   return s;
117*cc02d7e2SAndroid Build Coastguard Worker }
118*cc02d7e2SAndroid Build Coastguard Worker 
LowerUnderscoreToUpperCamel(std::string str)119*cc02d7e2SAndroid Build Coastguard Worker inline std::string LowerUnderscoreToUpperCamel(std::string str) {
120*cc02d7e2SAndroid Build Coastguard Worker   std::vector<std::string> tokens = tokenize(str, "_");
121*cc02d7e2SAndroid Build Coastguard Worker   std::string result = "";
122*cc02d7e2SAndroid Build Coastguard Worker   for (unsigned int i = 0; i < tokens.size(); i++) {
123*cc02d7e2SAndroid Build Coastguard Worker     result += CapitalizeFirstLetter(tokens[i]);
124*cc02d7e2SAndroid Build Coastguard Worker   }
125*cc02d7e2SAndroid Build Coastguard Worker   return result;
126*cc02d7e2SAndroid Build Coastguard Worker }
127*cc02d7e2SAndroid Build Coastguard Worker 
FileNameInUpperCamel(const grpc::protobuf::FileDescriptor * file,bool include_package_path)128*cc02d7e2SAndroid Build Coastguard Worker inline std::string FileNameInUpperCamel(
129*cc02d7e2SAndroid Build Coastguard Worker     const grpc::protobuf::FileDescriptor* file, bool include_package_path) {
130*cc02d7e2SAndroid Build Coastguard Worker   std::vector<std::string> tokens = tokenize(StripProto(file->name()), "/");
131*cc02d7e2SAndroid Build Coastguard Worker   std::string result = "";
132*cc02d7e2SAndroid Build Coastguard Worker   if (include_package_path) {
133*cc02d7e2SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < tokens.size() - 1; i++) {
134*cc02d7e2SAndroid Build Coastguard Worker       result += tokens[i] + "/";
135*cc02d7e2SAndroid Build Coastguard Worker     }
136*cc02d7e2SAndroid Build Coastguard Worker   }
137*cc02d7e2SAndroid Build Coastguard Worker   result += LowerUnderscoreToUpperCamel(tokens.back());
138*cc02d7e2SAndroid Build Coastguard Worker   return result;
139*cc02d7e2SAndroid Build Coastguard Worker }
140*cc02d7e2SAndroid Build Coastguard Worker 
FileNameInUpperCamel(const grpc::protobuf::FileDescriptor * file)141*cc02d7e2SAndroid Build Coastguard Worker inline std::string FileNameInUpperCamel(
142*cc02d7e2SAndroid Build Coastguard Worker     const grpc::protobuf::FileDescriptor* file) {
143*cc02d7e2SAndroid Build Coastguard Worker   return FileNameInUpperCamel(file, true);
144*cc02d7e2SAndroid Build Coastguard Worker }
145*cc02d7e2SAndroid Build Coastguard Worker 
146*cc02d7e2SAndroid Build Coastguard Worker enum MethodType {
147*cc02d7e2SAndroid Build Coastguard Worker   METHODTYPE_NO_STREAMING,
148*cc02d7e2SAndroid Build Coastguard Worker   METHODTYPE_CLIENT_STREAMING,
149*cc02d7e2SAndroid Build Coastguard Worker   METHODTYPE_SERVER_STREAMING,
150*cc02d7e2SAndroid Build Coastguard Worker   METHODTYPE_BIDI_STREAMING
151*cc02d7e2SAndroid Build Coastguard Worker };
152*cc02d7e2SAndroid Build Coastguard Worker 
GetMethodType(const grpc::protobuf::MethodDescriptor * method)153*cc02d7e2SAndroid Build Coastguard Worker inline MethodType GetMethodType(
154*cc02d7e2SAndroid Build Coastguard Worker     const grpc::protobuf::MethodDescriptor* method) {
155*cc02d7e2SAndroid Build Coastguard Worker   if (method->client_streaming()) {
156*cc02d7e2SAndroid Build Coastguard Worker     if (method->server_streaming()) {
157*cc02d7e2SAndroid Build Coastguard Worker       return METHODTYPE_BIDI_STREAMING;
158*cc02d7e2SAndroid Build Coastguard Worker     } else {
159*cc02d7e2SAndroid Build Coastguard Worker       return METHODTYPE_CLIENT_STREAMING;
160*cc02d7e2SAndroid Build Coastguard Worker     }
161*cc02d7e2SAndroid Build Coastguard Worker   } else {
162*cc02d7e2SAndroid Build Coastguard Worker     if (method->server_streaming()) {
163*cc02d7e2SAndroid Build Coastguard Worker       return METHODTYPE_SERVER_STREAMING;
164*cc02d7e2SAndroid Build Coastguard Worker     } else {
165*cc02d7e2SAndroid Build Coastguard Worker       return METHODTYPE_NO_STREAMING;
166*cc02d7e2SAndroid Build Coastguard Worker     }
167*cc02d7e2SAndroid Build Coastguard Worker   }
168*cc02d7e2SAndroid Build Coastguard Worker }
169*cc02d7e2SAndroid Build Coastguard Worker 
Split(const std::string & s,char,std::vector<std::string> * append_to)170*cc02d7e2SAndroid Build Coastguard Worker inline void Split(const std::string& s, char /*delim*/,
171*cc02d7e2SAndroid Build Coastguard Worker                   std::vector<std::string>* append_to) {
172*cc02d7e2SAndroid Build Coastguard Worker   std::istringstream iss(s);
173*cc02d7e2SAndroid Build Coastguard Worker   std::string piece;
174*cc02d7e2SAndroid Build Coastguard Worker   while (std::getline(iss, piece)) {
175*cc02d7e2SAndroid Build Coastguard Worker     append_to->push_back(piece);
176*cc02d7e2SAndroid Build Coastguard Worker   }
177*cc02d7e2SAndroid Build Coastguard Worker }
178*cc02d7e2SAndroid Build Coastguard Worker 
179*cc02d7e2SAndroid Build Coastguard Worker enum CommentType {
180*cc02d7e2SAndroid Build Coastguard Worker   COMMENTTYPE_LEADING,
181*cc02d7e2SAndroid Build Coastguard Worker   COMMENTTYPE_TRAILING,
182*cc02d7e2SAndroid Build Coastguard Worker   COMMENTTYPE_LEADING_DETACHED
183*cc02d7e2SAndroid Build Coastguard Worker };
184*cc02d7e2SAndroid Build Coastguard Worker 
185*cc02d7e2SAndroid Build Coastguard Worker // Get all the raw comments and append each line without newline to out.
186*cc02d7e2SAndroid Build Coastguard Worker template <typename DescriptorType>
GetComment(const DescriptorType * desc,CommentType type,std::vector<std::string> * out)187*cc02d7e2SAndroid Build Coastguard Worker inline void GetComment(const DescriptorType* desc, CommentType type,
188*cc02d7e2SAndroid Build Coastguard Worker                        std::vector<std::string>* out) {
189*cc02d7e2SAndroid Build Coastguard Worker   grpc::protobuf::SourceLocation location;
190*cc02d7e2SAndroid Build Coastguard Worker   if (!desc->GetSourceLocation(&location)) {
191*cc02d7e2SAndroid Build Coastguard Worker     return;
192*cc02d7e2SAndroid Build Coastguard Worker   }
193*cc02d7e2SAndroid Build Coastguard Worker   if (type == COMMENTTYPE_LEADING || type == COMMENTTYPE_TRAILING) {
194*cc02d7e2SAndroid Build Coastguard Worker     const std::string& comments = type == COMMENTTYPE_LEADING
195*cc02d7e2SAndroid Build Coastguard Worker                                       ? location.leading_comments
196*cc02d7e2SAndroid Build Coastguard Worker                                       : location.trailing_comments;
197*cc02d7e2SAndroid Build Coastguard Worker     Split(comments, '\n', out);
198*cc02d7e2SAndroid Build Coastguard Worker   } else if (type == COMMENTTYPE_LEADING_DETACHED) {
199*cc02d7e2SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < location.leading_detached_comments.size();
200*cc02d7e2SAndroid Build Coastguard Worker          i++) {
201*cc02d7e2SAndroid Build Coastguard Worker       Split(location.leading_detached_comments[i], '\n', out);
202*cc02d7e2SAndroid Build Coastguard Worker       out->push_back("");
203*cc02d7e2SAndroid Build Coastguard Worker     }
204*cc02d7e2SAndroid Build Coastguard Worker   } else {
205*cc02d7e2SAndroid Build Coastguard Worker     std::cerr << "Unknown comment type " << type << std::endl;
206*cc02d7e2SAndroid Build Coastguard Worker     abort();
207*cc02d7e2SAndroid Build Coastguard Worker   }
208*cc02d7e2SAndroid Build Coastguard Worker }
209*cc02d7e2SAndroid Build Coastguard Worker 
210*cc02d7e2SAndroid Build Coastguard Worker // Each raw comment line without newline is appended to out.
211*cc02d7e2SAndroid Build Coastguard Worker // For file level leading and detached leading comments, we return comments
212*cc02d7e2SAndroid Build Coastguard Worker // above syntax line. Return nothing for trailing comments.
213*cc02d7e2SAndroid Build Coastguard Worker template <>
GetComment(const grpc::protobuf::FileDescriptor * desc,CommentType type,std::vector<std::string> * out)214*cc02d7e2SAndroid Build Coastguard Worker inline void GetComment(const grpc::protobuf::FileDescriptor* desc,
215*cc02d7e2SAndroid Build Coastguard Worker                        CommentType type, std::vector<std::string>* out) {
216*cc02d7e2SAndroid Build Coastguard Worker   if (type == COMMENTTYPE_TRAILING) {
217*cc02d7e2SAndroid Build Coastguard Worker     return;
218*cc02d7e2SAndroid Build Coastguard Worker   }
219*cc02d7e2SAndroid Build Coastguard Worker   grpc::protobuf::SourceLocation location;
220*cc02d7e2SAndroid Build Coastguard Worker   std::vector<int> path;
221*cc02d7e2SAndroid Build Coastguard Worker   path.push_back(grpc::protobuf::FileDescriptorProto::kSyntaxFieldNumber);
222*cc02d7e2SAndroid Build Coastguard Worker   if (!desc->GetSourceLocation(path, &location)) {
223*cc02d7e2SAndroid Build Coastguard Worker     return;
224*cc02d7e2SAndroid Build Coastguard Worker   }
225*cc02d7e2SAndroid Build Coastguard Worker   if (type == COMMENTTYPE_LEADING) {
226*cc02d7e2SAndroid Build Coastguard Worker     Split(location.leading_comments, '\n', out);
227*cc02d7e2SAndroid Build Coastguard Worker   } else if (type == COMMENTTYPE_LEADING_DETACHED) {
228*cc02d7e2SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < location.leading_detached_comments.size();
229*cc02d7e2SAndroid Build Coastguard Worker          i++) {
230*cc02d7e2SAndroid Build Coastguard Worker       Split(location.leading_detached_comments[i], '\n', out);
231*cc02d7e2SAndroid Build Coastguard Worker       out->push_back("");
232*cc02d7e2SAndroid Build Coastguard Worker     }
233*cc02d7e2SAndroid Build Coastguard Worker   } else {
234*cc02d7e2SAndroid Build Coastguard Worker     std::cerr << "Unknown comment type " << type << std::endl;
235*cc02d7e2SAndroid Build Coastguard Worker     abort();
236*cc02d7e2SAndroid Build Coastguard Worker   }
237*cc02d7e2SAndroid Build Coastguard Worker }
238*cc02d7e2SAndroid Build Coastguard Worker 
239*cc02d7e2SAndroid Build Coastguard Worker // Add prefix and newline to each comment line and concatenate them together.
240*cc02d7e2SAndroid Build Coastguard Worker // Make sure there is a space after the prefix unless the line is empty.
GenerateCommentsWithPrefix(const std::vector<std::string> & in,const std::string & prefix)241*cc02d7e2SAndroid Build Coastguard Worker inline std::string GenerateCommentsWithPrefix(
242*cc02d7e2SAndroid Build Coastguard Worker     const std::vector<std::string>& in, const std::string& prefix) {
243*cc02d7e2SAndroid Build Coastguard Worker   std::ostringstream oss;
244*cc02d7e2SAndroid Build Coastguard Worker   for (auto it = in.begin(); it != in.end(); it++) {
245*cc02d7e2SAndroid Build Coastguard Worker     const std::string& elem = *it;
246*cc02d7e2SAndroid Build Coastguard Worker     if (elem.empty()) {
247*cc02d7e2SAndroid Build Coastguard Worker       oss << prefix << "\n";
248*cc02d7e2SAndroid Build Coastguard Worker     } else if (elem[0] == ' ') {
249*cc02d7e2SAndroid Build Coastguard Worker       oss << prefix << EscapeVariableDelimiters(elem) << "\n";
250*cc02d7e2SAndroid Build Coastguard Worker     } else {
251*cc02d7e2SAndroid Build Coastguard Worker       oss << prefix << " " << EscapeVariableDelimiters(elem) << "\n";
252*cc02d7e2SAndroid Build Coastguard Worker     }
253*cc02d7e2SAndroid Build Coastguard Worker   }
254*cc02d7e2SAndroid Build Coastguard Worker   return oss.str();
255*cc02d7e2SAndroid Build Coastguard Worker }
256*cc02d7e2SAndroid Build Coastguard Worker 
257*cc02d7e2SAndroid Build Coastguard Worker template <typename DescriptorType>
GetPrefixedComments(const DescriptorType * desc,bool leading,const std::string & prefix)258*cc02d7e2SAndroid Build Coastguard Worker inline std::string GetPrefixedComments(const DescriptorType* desc, bool leading,
259*cc02d7e2SAndroid Build Coastguard Worker                                        const std::string& prefix) {
260*cc02d7e2SAndroid Build Coastguard Worker   std::vector<std::string> out;
261*cc02d7e2SAndroid Build Coastguard Worker   if (leading) {
262*cc02d7e2SAndroid Build Coastguard Worker     grpc_generator::GetComment(
263*cc02d7e2SAndroid Build Coastguard Worker         desc, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &out);
264*cc02d7e2SAndroid Build Coastguard Worker     std::vector<std::string> leading;
265*cc02d7e2SAndroid Build Coastguard Worker     grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING,
266*cc02d7e2SAndroid Build Coastguard Worker                                &leading);
267*cc02d7e2SAndroid Build Coastguard Worker     out.insert(out.end(), leading.begin(), leading.end());
268*cc02d7e2SAndroid Build Coastguard Worker   } else {
269*cc02d7e2SAndroid Build Coastguard Worker     grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_TRAILING,
270*cc02d7e2SAndroid Build Coastguard Worker                                &out);
271*cc02d7e2SAndroid Build Coastguard Worker   }
272*cc02d7e2SAndroid Build Coastguard Worker   return GenerateCommentsWithPrefix(out, prefix);
273*cc02d7e2SAndroid Build Coastguard Worker }
274*cc02d7e2SAndroid Build Coastguard Worker 
275*cc02d7e2SAndroid Build Coastguard Worker }  // namespace grpc_generator
276*cc02d7e2SAndroid Build Coastguard Worker 
277*cc02d7e2SAndroid Build Coastguard Worker #endif  // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H
278