Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: third_party/protobuf/src/google/protobuf/compiler/ruby/ruby_generator.cc

Issue 2495533002: third_party/protobuf: Update to HEAD (83d681ee2c) (Closed)
Patch Set: Make chrome settings proto generated file a component Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Protocol Buffers - Google's data interchange format 1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved. 2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/ 3 // https://developers.google.com/protocol-buffers/
4 // 4 //
5 // Redistribution and use in source and binary forms, with or without 5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are 6 // modification, are permitted provided that the following conditions are
7 // met: 7 // met:
8 // 8 //
9 // * Redistributions of source code must retain the above copyright 9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer. 10 // notice, this list of conditions and the following disclaimer.
(...skipping 30 matching lines...) Expand all
41 41
42 using google::protobuf::internal::scoped_ptr; 42 using google::protobuf::internal::scoped_ptr;
43 43
44 namespace google { 44 namespace google {
45 namespace protobuf { 45 namespace protobuf {
46 namespace compiler { 46 namespace compiler {
47 namespace ruby { 47 namespace ruby {
48 48
49 // Forward decls. 49 // Forward decls.
50 std::string IntToString(int32 value); 50 std::string IntToString(int32 value);
51 std::string StripDotProto(const std::string& proto_file); 51 std::string GetRequireName(const std::string& proto_file);
52 std::string LabelForField(google::protobuf::FieldDescriptor* field); 52 std::string LabelForField(google::protobuf::FieldDescriptor* field);
53 std::string TypeName(google::protobuf::FieldDescriptor* field); 53 std::string TypeName(google::protobuf::FieldDescriptor* field);
54 void GenerateMessage(const google::protobuf::Descriptor* message, 54 void GenerateMessage(const google::protobuf::Descriptor* message,
55 google::protobuf::io::Printer* printer); 55 google::protobuf::io::Printer* printer);
56 void GenerateEnum(const google::protobuf::EnumDescriptor* en, 56 void GenerateEnum(const google::protobuf::EnumDescriptor* en,
57 google::protobuf::io::Printer* printer); 57 google::protobuf::io::Printer* printer);
58 void GenerateMessageAssignment( 58 void GenerateMessageAssignment(
59 const std::string& prefix, 59 const std::string& prefix,
60 const google::protobuf::Descriptor* message, 60 const google::protobuf::Descriptor* message,
61 google::protobuf::io::Printer* printer); 61 google::protobuf::io::Printer* printer);
62 void GenerateEnumAssignment( 62 void GenerateEnumAssignment(
63 const std::string& prefix, 63 const std::string& prefix,
64 const google::protobuf::EnumDescriptor* en, 64 const google::protobuf::EnumDescriptor* en,
65 google::protobuf::io::Printer* printer); 65 google::protobuf::io::Printer* printer);
66 66
67 std::string IntToString(int32 value) { 67 std::string IntToString(int32 value) {
68 std::ostringstream os; 68 std::ostringstream os;
69 os << value; 69 os << value;
70 return os.str(); 70 return os.str();
71 } 71 }
72 72
73 std::string StripDotProto(const std::string& proto_file) { 73 std::string GetRequireName(const std::string& proto_file) {
74 int lastindex = proto_file.find_last_of("."); 74 int lastindex = proto_file.find_last_of(".");
75 return proto_file.substr(0, lastindex); 75 return proto_file.substr(0, lastindex) + "_pb";
76 } 76 }
77 77
78 std::string GetOutputFilename(const std::string& proto_file) { 78 std::string GetOutputFilename(const std::string& proto_file) {
79 return StripDotProto(proto_file) + ".rb"; 79 return GetRequireName(proto_file) + ".rb";
80 } 80 }
81 81
82 std::string LabelForField(const google::protobuf::FieldDescriptor* field) { 82 std::string LabelForField(const google::protobuf::FieldDescriptor* field) {
83 switch (field->label()) { 83 switch (field->label()) {
84 case FieldDescriptor::LABEL_OPTIONAL: return "optional"; 84 case FieldDescriptor::LABEL_OPTIONAL: return "optional";
85 case FieldDescriptor::LABEL_REQUIRED: return "required"; 85 case FieldDescriptor::LABEL_REQUIRED: return "required";
86 case FieldDescriptor::LABEL_REPEATED: return "repeated"; 86 case FieldDescriptor::LABEL_REPEATED: return "repeated";
87 default: assert(false); return ""; 87 default: assert(false); return "";
88 } 88 }
89 } 89 }
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 "value :$name$, $number$\n", 230 "value :$name$, $number$\n",
231 "name", value->name(), 231 "name", value->name(),
232 "number", IntToString(value->number())); 232 "number", IntToString(value->number()));
233 } 233 }
234 234
235 printer->Outdent(); 235 printer->Outdent();
236 printer->Print( 236 printer->Print(
237 "end\n"); 237 "end\n");
238 } 238 }
239 239
240 // Module names, class names, and enum value names need to be Ruby constants, 240 // Locale-agnostic utility functions.
241 // which must start with a capital letter. 241 bool IsLower(char ch) { return ch >= 'a' && ch <= 'z'; }
242
243 bool IsUpper(char ch) { return ch >= 'A' && ch <= 'Z'; }
244
245 bool IsAlpha(char ch) { return IsLower(ch) || IsUpper(ch); }
246
247 char ToUpper(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; }
248
249
250 // Package names in protobuf are snake_case by convention, but Ruby module
251 // names must be PascalCased.
252 //
253 // foo_bar_baz -> FooBarBaz
254 std::string PackageToModule(const std::string& name) {
255 bool next_upper = true;
256 std::string result;
257 result.reserve(name.size());
258
259 for (int i = 0; i < name.size(); i++) {
260 if (name[i] == '_') {
261 next_upper = true;
262 } else {
263 if (next_upper) {
264 result.push_back(ToUpper(name[i]));
265 } else {
266 result.push_back(name[i]);
267 }
268 next_upper = false;
269 }
270 }
271
272 return result;
273 }
274
275 // Class and enum names in protobuf should be PascalCased by convention, but
276 // since there is nothing enforcing this we need to ensure that they are valid
277 // Ruby constants. That mainly means making sure that the first character is
278 // an upper-case letter.
242 std::string RubifyConstant(const std::string& name) { 279 std::string RubifyConstant(const std::string& name) {
243 std::string ret = name; 280 std::string ret = name;
244 if (!ret.empty()) { 281 if (!ret.empty()) {
245 if (ret[0] >= 'a' && ret[0] <= 'z') { 282 if (IsLower(ret[0])) {
246 // If it starts with a lowercase letter, capitalize it. 283 // If it starts with a lowercase letter, capitalize it.
247 ret[0] = ret[0] - 'a' + 'A'; 284 ret[0] = ToUpper(ret[0]);
248 } else if (ret[0] < 'A' || ret[0] > 'Z') { 285 } else if (!IsAlpha(ret[0])) {
249 // Otherwise (e.g. if it begins with an underscore), we need to come up 286 // Otherwise (e.g. if it begins with an underscore), we need to come up
250 // with some prefix that starts with a capital letter. We could be smarter 287 // with some prefix that starts with a capital letter. We could be smarter
251 // here, e.g. try to strip leading underscores, but this may cause other 288 // here, e.g. try to strip leading underscores, but this may cause other
252 // problems if the user really intended the name. So let's just prepend a 289 // problems if the user really intended the name. So let's just prepend a
253 // well-known suffix. 290 // well-known suffix.
254 ret = "PB_" + ret; 291 ret = "PB_" + ret;
255 } 292 }
256 } 293 }
294
257 return ret; 295 return ret;
258 } 296 }
259 297
260 void GenerateMessageAssignment( 298 void GenerateMessageAssignment(
261 const std::string& prefix, 299 const std::string& prefix,
262 const google::protobuf::Descriptor* message, 300 const google::protobuf::Descriptor* message,
263 google::protobuf::io::Printer* printer) { 301 google::protobuf::io::Printer* printer) {
264 302
265 // Don't generate MapEntry messages -- we use the Ruby extension's native 303 // Don't generate MapEntry messages -- we use the Ruby extension's native
266 // support for map fields instead. 304 // support for map fields instead.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 while (!package_name.empty()) { 345 while (!package_name.empty()) {
308 size_t dot_index = package_name.find("."); 346 size_t dot_index = package_name.find(".");
309 string component; 347 string component;
310 if (dot_index == string::npos) { 348 if (dot_index == string::npos) {
311 component = package_name; 349 component = package_name;
312 package_name = ""; 350 package_name = "";
313 } else { 351 } else {
314 component = package_name.substr(0, dot_index); 352 component = package_name.substr(0, dot_index);
315 package_name = package_name.substr(dot_index + 1); 353 package_name = package_name.substr(dot_index + 1);
316 } 354 }
317 component = RubifyConstant(component); 355 component = PackageToModule(component);
318 printer->Print( 356 printer->Print(
319 "module $name$\n", 357 "module $name$\n",
320 "name", component); 358 "name", component);
321 printer->Indent(); 359 printer->Indent();
322 levels++; 360 levels++;
323 } 361 }
324 return levels; 362 return levels;
325 } 363 }
326 364
327 void EndPackageModules( 365 void EndPackageModules(
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 422
385 // Ok to omit this proto2 dependency -- so we won't print anything. 423 // Ok to omit this proto2 dependency -- so we won't print anything.
386 GOOGLE_LOG(WARNING) << "Omitting proto2 dependency '" << import->name() 424 GOOGLE_LOG(WARNING) << "Omitting proto2 dependency '" << import->name()
387 << "' from proto3 output file '" 425 << "' from proto3 output file '"
388 << GetOutputFilename(from->name()) 426 << GetOutputFilename(from->name())
389 << "' because we don't support proto2 and no proto2 " 427 << "' because we don't support proto2 and no proto2 "
390 "types from that file are being used."; 428 "types from that file are being used.";
391 return true; 429 return true;
392 } else { 430 } else {
393 printer->Print( 431 printer->Print(
394 "require '$name$'\n", "name", StripDotProto(import->name())); 432 "require '$name$'\n", "name", GetRequireName(import->name()));
395 return true; 433 return true;
396 } 434 }
397 } 435 }
398 436
399 bool GenerateFile(const FileDescriptor* file, io::Printer* printer, 437 bool GenerateFile(const FileDescriptor* file, io::Printer* printer,
400 string* error) { 438 string* error) {
401 printer->Print( 439 printer->Print(
402 "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" 440 "# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
403 "# source: $filename$\n" 441 "# source: $filename$\n"
404 "\n", 442 "\n",
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 generator_context->Open(GetOutputFilename(file->name()))); 492 generator_context->Open(GetOutputFilename(file->name())));
455 io::Printer printer(output.get(), '$'); 493 io::Printer printer(output.get(), '$');
456 494
457 return GenerateFile(file, &printer, error); 495 return GenerateFile(file, &printer, error);
458 } 496 }
459 497
460 } // namespace ruby 498 } // namespace ruby
461 } // namespace compiler 499 } // namespace compiler
462 } // namespace protobuf 500 } // namespace protobuf
463 } // namespace google 501 } // namespace google
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698