node_generator.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2016 gRPC authors.
4  *
5  * 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
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * 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.
16  *
17  */
18 
20 
21 #include <map>
22 
23 #include "src/compiler/config.h"
26 
33 using std::map;
34 
36 namespace {
37 
38 // Returns the alias we assign to the module of the given .proto filename
39 // when importing. Copied entirely from
40 // github:google/protobuf/src/google/protobuf/compiler/js/js_generator.cc#L154
41 std::string ModuleAlias(const std::string filename) {
42  // This scheme could technically cause problems if a file includes any 2 of:
43  // foo/bar_baz.proto
44  // foo_bar_baz.proto
45  // foo_bar/baz.proto
46  //
47  // We'll worry about this problem if/when we actually see it. This name isn't
48  // exposed to users so we can change it later if we need to.
50  basename = grpc_generator::StringReplace(basename, "-", "$");
51  basename = grpc_generator::StringReplace(basename, "/", "_");
52  basename = grpc_generator::StringReplace(basename, ".", "_");
53  return basename + "_pb";
54 }
55 
56 // Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
57 // message file foo/bar/baz.js
58 std::string GetJSMessageFilename(const std::string& filename) {
60  return grpc_generator::StripProto(name) + "_pb.js";
61 }
62 
63 // Given a filename like foo/bar/baz.proto, returns the root directory
64 // path ../../
65 std::string GetRootPath(const std::string& from_filename,
66  const std::string& to_filename) {
67  if (to_filename.find("google/protobuf") == 0) {
68  // Well-known types (.proto files in the google/protobuf directory) are
69  // assumed to come from the 'google-protobuf' npm package. We may want to
70  // generalize this exception later by letting others put generated code in
71  // their own npm packages.
72  return "google-protobuf/";
73  }
74  size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/');
75  if (slashes == 0) {
76  return "./";
77  }
78  std::string result = "";
79  for (size_t i = 0; i < slashes; i++) {
80  result += "../";
81  }
82  return result;
83 }
84 
85 // Return the relative path to load to_file from the directory containing
86 // from_file, assuming that both paths are relative to the same directory
87 std::string GetRelativePath(const std::string& from_file,
88  const std::string& to_file) {
89  return GetRootPath(from_file, to_file) + to_file;
90 }
91 
92 /* Finds all message types used in all services in the file, and returns them
93  * as a map of fully qualified message type name to message descriptor */
94 map<std::string, const Descriptor*> GetAllMessages(const FileDescriptor* file) {
95  map<std::string, const Descriptor*> message_types;
96  for (int service_num = 0; service_num < file->service_count();
97  service_num++) {
98  const ServiceDescriptor* service = file->service(service_num);
99  for (int method_num = 0; method_num < service->method_count();
100  method_num++) {
101  const MethodDescriptor* method = service->method(method_num);
102  const Descriptor* input_type = method->input_type();
103  const Descriptor* output_type = method->output_type();
104  message_types[input_type->full_name()] = input_type;
105  message_types[output_type->full_name()] = output_type;
106  }
107  }
108  return message_types;
109 }
110 
111 std::string MessageIdentifierName(const std::string& name) {
112  return grpc_generator::StringReplace(name, ".", "_");
113 }
114 
115 std::string NodeObjectPath(const Descriptor* descriptor) {
116  std::string module_alias = ModuleAlias(descriptor->file()->name());
117  std::string name = descriptor->full_name();
118  grpc_generator::StripPrefix(&name, descriptor->file()->package() + ".");
119  return module_alias + "." + name;
120 }
121 
122 // Prints out the message serializer and deserializer functions
123 void PrintMessageTransformer(const Descriptor* descriptor, Printer* out,
124  const Parameters& params) {
125  map<std::string, std::string> template_vars;
126  std::string full_name = descriptor->full_name();
127  template_vars["identifier_name"] = MessageIdentifierName(full_name);
128  template_vars["name"] = full_name;
129  template_vars["node_name"] = NodeObjectPath(descriptor);
130  // Print the serializer
131  out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n");
132  out->Indent();
133  out->Print(template_vars, "if (!(arg instanceof $node_name$)) {\n");
134  out->Indent();
135  out->Print(template_vars,
136  "throw new Error('Expected argument of type $name$');\n");
137  out->Outdent();
138  out->Print("}\n");
139  if (params.minimum_node_version > 5) {
140  // Node version is > 5, we should use Buffer.from
141  out->Print("return Buffer.from(arg.serializeBinary());\n");
142  } else {
143  out->Print("return new Buffer(arg.serializeBinary());\n");
144  }
145  out->Outdent();
146  out->Print("}\n\n");
147 
148  // Print the deserializer
149  out->Print(template_vars,
150  "function deserialize_$identifier_name$(buffer_arg) {\n");
151  out->Indent();
152  out->Print(
153  template_vars,
154  "return $node_name$.deserializeBinary(new Uint8Array(buffer_arg));\n");
155  out->Outdent();
156  out->Print("}\n\n");
157 }
158 
159 void PrintMethod(const MethodDescriptor* method, Printer* out) {
160  const Descriptor* input_type = method->input_type();
161  const Descriptor* output_type = method->output_type();
162  map<std::string, std::string> vars;
163  vars["service_name"] = method->service()->full_name();
164  vars["name"] = method->name();
165  vars["input_type"] = NodeObjectPath(input_type);
166  vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
167  vars["output_type"] = NodeObjectPath(output_type);
168  vars["output_type_id"] = MessageIdentifierName(output_type->full_name());
169  vars["client_stream"] = method->client_streaming() ? "true" : "false";
170  vars["server_stream"] = method->server_streaming() ? "true" : "false";
171  out->Print("{\n");
172  out->Indent();
173  out->Print(vars, "path: '/$service_name$/$name$',\n");
174  out->Print(vars, "requestStream: $client_stream$,\n");
175  out->Print(vars, "responseStream: $server_stream$,\n");
176  out->Print(vars, "requestType: $input_type$,\n");
177  out->Print(vars, "responseType: $output_type$,\n");
178  out->Print(vars, "requestSerialize: serialize_$input_type_id$,\n");
179  out->Print(vars, "requestDeserialize: deserialize_$input_type_id$,\n");
180  out->Print(vars, "responseSerialize: serialize_$output_type_id$,\n");
181  out->Print(vars, "responseDeserialize: deserialize_$output_type_id$,\n");
182  out->Outdent();
183  out->Print("}");
184 }
185 
186 // Prints out the service descriptor object
187 void PrintService(const ServiceDescriptor* service, Printer* out) {
188  map<std::string, std::string> template_vars;
189  out->Print(GetNodeComments(service, true).c_str());
190  template_vars["name"] = service->name();
191  out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n");
192  out->Indent();
193  for (int i = 0; i < service->method_count(); i++) {
196  out->Print(GetNodeComments(service->method(i), true).c_str());
197  out->Print("$method_name$: ", "method_name", method_name);
198  PrintMethod(service->method(i), out);
199  out->Print(",\n");
200  out->Print(GetNodeComments(service->method(i), false).c_str());
201  }
202  out->Outdent();
203  out->Print("};\n\n");
204  out->Print(template_vars,
205  "exports.$name$Client = "
206  "grpc.makeGenericClientConstructor($name$Service);\n");
207  out->Print(GetNodeComments(service, false).c_str());
208 }
209 
210 void PrintImports(const FileDescriptor* file, Printer* out) {
211  out->Print("var grpc = require('grpc');\n");
212  if (file->message_type_count() > 0) {
213  std::string file_path =
214  GetRelativePath(file->name(), GetJSMessageFilename(file->name()));
215  out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
216  ModuleAlias(file->name()), "file_path", file_path);
217  }
218 
219  for (int i = 0; i < file->dependency_count(); i++) {
220  std::string file_path = GetRelativePath(
221  file->name(), GetJSMessageFilename(file->dependency(i)->name()));
222  out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
223  ModuleAlias(file->dependency(i)->name()), "file_path",
224  file_path);
225  }
226  out->Print("\n");
227 }
228 
229 void PrintTransformers(const FileDescriptor* file, Printer* out,
230  const Parameters& params) {
231  map<std::string, const Descriptor*> messages = GetAllMessages(file);
233  it != messages.end(); it++) {
234  PrintMessageTransformer(it->second, out, params);
235  }
236  out->Print("\n");
237 }
238 
239 void PrintServices(const FileDescriptor* file, Printer* out) {
240  for (int i = 0; i < file->service_count(); i++) {
241  PrintService(file->service(i), out);
242  }
243 }
244 } // namespace
245 
248  {
249  StringOutputStream output_stream(&output);
250  Printer out(&output_stream, '$');
251 
252  if (file->service_count() == 0) {
253  return output;
254  }
255  out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n");
256 
257  std::string leading_comments = GetNodeComments(file, true);
258  if (!leading_comments.empty()) {
259  out.Print("// Original file comments:\n");
260  out.PrintRaw(leading_comments.c_str());
261  }
262 
263  out.Print("'use strict';\n");
264 
265  PrintImports(file, &out);
266 
267  PrintTransformers(file, &out, params);
268 
269  PrintServices(file, &out);
270 
271  out.Print(GetNodeComments(file, false).c_str());
272  }
273  return output;
274 }
275 
276 } // namespace grpc_node_generator
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
filename
const char * filename
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
regen-readme.it
it
Definition: regen-readme.py:15
grpc_node_generator::GenerateFile
std::string GenerateFile(const FileDescriptor *file, const Parameters &params)
Definition: node_generator.cc:246
grpc_generator::StringReplace
std::string StringReplace(std::string str, const std::string &from, const std::string &to, bool replace_all)
Definition: generator_helpers.h:61
grpc::protobuf::FileDescriptor
GRPC_CUSTOM_FILEDESCRIPTOR FileDescriptor
Definition: include/grpcpp/impl/codegen/config_protobuf.h:85
config.h
FileDescriptor
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:128
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
file
Definition: bloaty/third_party/zlib/examples/gzappend.c:170
grpc::protobuf::io::Printer
GRPC_CUSTOM_PRINTER Printer
Definition: src/compiler/config.h:54
setup.name
name
Definition: setup.py:542
iterator
const typedef MCPhysReg * iterator
Definition: MCRegisterInfo.h:27
map
zval * map
Definition: php/ext/google/protobuf/encode_decode.c:480
grpc_node_generator::Parameters
Definition: node_generator.h:27
Descriptor
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:121
grpc::protobuf::io::StringOutputStream
GRPC_CUSTOM_STRINGOUTPUTSTREAM StringOutputStream
Definition: src/compiler/config.h:56
gen_stats_data.c_str
def c_str(s, encoding='ascii')
Definition: gen_stats_data.py:38
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
grpc::protobuf::MethodDescriptor
GRPC_CUSTOM_METHODDESCRIPTOR MethodDescriptor
Definition: include/grpcpp/impl/codegen/config_protobuf.h:87
node_generator_helpers.h
node_generator.h
grpc_node_generator
Definition: node_generator.cc:35
grpc_generator::LowercaseFirstLetter
std::string LowercaseFirstLetter(std::string s)
Definition: generator_helpers.h:110
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
generator_helpers.h
grpc_generator::StripProto
std::string StripProto(std::string filename)
Definition: generator_helpers.h:54
grpc_node_generator::Parameters::minimum_node_version
int minimum_node_version
Definition: node_generator.h:29
grpc_node_generator::GetNodeComments
std::string GetNodeComments(const DescriptorType *desc, bool leading)
Definition: node_generator_helpers.h:36
service
__attribute__((deprecated("Please use GRPCProtoMethod."))) @interface ProtoMethod NSString * service
Definition: ProtoMethod.h:25
file::name
char * name
Definition: bloaty/third_party/zlib/examples/gzappend.c:176
grpc::protobuf::Descriptor
GRPC_CUSTOM_DESCRIPTOR Descriptor
Definition: include/grpcpp/impl/codegen/config_protobuf.h:81
method
NSString * method
Definition: ProtoMethod.h:28
descriptor
static const char descriptor[1336]
Definition: certs.upbdefs.c:16
method_name
absl::string_view method_name
Definition: call_creds_util.cc:40
grpc::protobuf::ServiceDescriptor
GRPC_CUSTOM_SERVICEDESCRIPTOR ServiceDescriptor
Definition: include/grpcpp/impl/codegen/config_protobuf.h:88
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
grpc_generator::StripPrefix
bool StripPrefix(std::string *name, const std::string &prefix)
Definition: generator_helpers.h:44


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:32