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

Side by Side Diff: components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc

Issue 2293073002: Tracing V2: Proto fields reflection. (Closed)
Patch Set: nit Created 4 years, 3 months 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
« no previous file with comments | « components/tracing/test/proto_zero_generation_unittest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "proto_zero_generator.h" 5 #include "proto_zero_generator.h"
6 6
7 #include <map> 7 #include <map>
8 #include <memory> 8 #include <memory>
9 #include <set> 9 #include <set>
10 #include <string> 10 #include <string>
(...skipping 25 matching lines...) Expand all
36 36
37 inline std::string ProtoStubName(const FileDescriptor* proto) { 37 inline std::string ProtoStubName(const FileDescriptor* proto) {
38 return StripSuffixString(proto->name(), ".proto") + ".pbzero"; 38 return StripSuffixString(proto->name(), ".proto") + ".pbzero";
39 } 39 }
40 40
41 class GeneratorJob { 41 class GeneratorJob {
42 public: 42 public:
43 GeneratorJob(const FileDescriptor *file, 43 GeneratorJob(const FileDescriptor *file,
44 Printer* stub_h_printer, 44 Printer* stub_h_printer,
45 Printer* stub_cc_printer) 45 Printer* stub_cc_printer)
46 : source_(file), 46 : source_(file), stub_h_(stub_h_printer), stub_cc_(stub_cc_printer) {
47 stub_h_(stub_h_printer), 47 }
48 stub_cc_(stub_cc_printer) {}
49 48
50 bool GenerateStubs() { 49 bool GenerateStubs() {
51 Preprocess(); 50 Preprocess();
52 GeneratePrologue(); 51 GeneratePrologue();
53 for (const EnumDescriptor* enumeration: enums_) 52 for (const EnumDescriptor* enumeration: enums_)
54 GenerateEnumDescriptor(enumeration); 53 GenerateEnumDescriptor(enumeration);
55 for (const Descriptor* message : messages_) 54 for (const Descriptor* message : messages_)
56 GenerateMessageDescriptor(message); 55 GenerateMessageDescriptor(message);
57 GenerateEpilogue(); 56 GenerateEpilogue();
58 return error_.empty(); 57 return error_.empty();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 // prohibited but not recommended in order to avoid name collisions. 93 // prohibited but not recommended in order to avoid name collisions.
95 template <class T> 94 template <class T>
96 inline std::string GetCppClassName(const T* descriptor, bool full = false) { 95 inline std::string GetCppClassName(const T* descriptor, bool full = false) {
97 std::string name = GetDescriptorName(descriptor); 96 std::string name = GetDescriptorName(descriptor);
98 StripString(&name, ".", '_'); 97 StripString(&name, ".", '_');
99 if (full) 98 if (full)
100 name = full_namespace_prefix_ + name; 99 name = full_namespace_prefix_ + name;
101 return name; 100 return name;
102 } 101 }
103 102
103 inline std::string GetFieldNumberConstant(const FieldDescriptor* field) {
104 std::string name = field->camelcase_name();
105 if (!name.empty()) {
106 name.at(0) = toupper(name.at(0));
107 name = "k" + name + "FieldNumber";
108 } else {
109 // Protoc allows fields like 'bool _ = 1'.
110 Abort("Empty field name in camel case notation.");
111 }
112 return name;
113 }
114
104 // Small enums can be written faster without involving VarInt encoder. 115 // Small enums can be written faster without involving VarInt encoder.
105 inline bool IsTinyEnumField(const FieldDescriptor* field) { 116 inline bool IsTinyEnumField(const FieldDescriptor* field) {
106 if (field->type() != FieldDescriptor::TYPE_ENUM) 117 if (field->type() != FieldDescriptor::TYPE_ENUM)
107 return false; 118 return false;
108 const EnumDescriptor* enumeration = field->enum_type(); 119 const EnumDescriptor* enumeration = field->enum_type();
109 120
110 for (int i = 0; i < enumeration->value_count(); ++i) { 121 for (int i = 0; i < enumeration->value_count(); ++i) {
111 int32_t value = enumeration->value(i)->number(); 122 int32_t value = enumeration->value(i)->number();
112 if (value < 0 || value > 0x7F) 123 if (value < 0 || value > 0x7F)
113 return false; 124 return false;
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 stub_h_->Print("\n"); 267 stub_h_->Print("\n");
257 268
258 // Print includes for private imports to .cc file. 269 // Print includes for private imports to .cc file.
259 for (const FileDescriptor* dependency : private_imports_) { 270 for (const FileDescriptor* dependency : private_imports_) {
260 stub_cc_->Print( 271 stub_cc_->Print(
261 "#include \"$name$.h\"\n", 272 "#include \"$name$.h\"\n",
262 "name", ProtoStubName(dependency)); 273 "name", ProtoStubName(dependency));
263 } 274 }
264 stub_cc_->Print("\n"); 275 stub_cc_->Print("\n");
265 276
277 if (messages_.size() > 0) {
278 stub_cc_->Print(
279 "namespace {\n"
280 " static const ::tracing::v2::proto::ProtoFieldDescriptor "
281 "kInvalidField = {\"\", "
282 "::tracing::v2::proto::ProtoFieldDescriptor::Type::TYPE_INVALID, "
283 "0, false};\n"
284 "}\n\n");
285 }
286
266 // Print namespaces. 287 // Print namespaces.
267 for (const std::string& ns : namespaces_) { 288 for (const std::string& ns : namespaces_) {
268 stub_h_->Print("namespace $ns$ {\n", "ns", ns); 289 stub_h_->Print("namespace $ns$ {\n", "ns", ns);
269 stub_cc_->Print("namespace $ns$ {\n", "ns", ns); 290 stub_cc_->Print("namespace $ns$ {\n", "ns", ns);
270 } 291 }
271 stub_h_->Print("\n"); 292 stub_h_->Print("\n");
272 stub_cc_->Print("\n"); 293 stub_cc_->Print("\n");
273 294
274 // Print forward declarations. 295 // Print forward declarations.
275 for (const Descriptor* message : referenced_messages_) { 296 for (const Descriptor* message : referenced_messages_) {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 "$inner_class$* $outer_class$::$action$_$name$() {\n" 449 "$inner_class$* $outer_class$::$action$_$name$() {\n"
429 " return BeginNestedMessage<$inner_class$>($id$);\n" 450 " return BeginNestedMessage<$inner_class$>($id$);\n"
430 "}\n\n", 451 "}\n\n",
431 "id", std::to_string(field->number()), 452 "id", std::to_string(field->number()),
432 "name", field->name(), 453 "name", field->name(),
433 "action", action, 454 "action", action,
434 "inner_class", inner_class, 455 "inner_class", inner_class,
435 "outer_class", outer_class); 456 "outer_class", outer_class);
436 } 457 }
437 458
459 void GenerateReflectionForMessageFields(const Descriptor* message) {
460 const bool has_fields = (message->field_count() > 0);
461
462 // Field number constants.
463 if (has_fields) {
464 stub_h_->Print("enum : int32_t {\n");
465 stub_h_->Indent();
466
467 for (int i = 0; i < message->field_count(); ++i) {
468 const FieldDescriptor* field = message->field(i);
469 stub_h_->Print(
470 "$name$ = $id$,\n",
471 "name", GetFieldNumberConstant(field),
472 "id", std::to_string(field->number()));
473 }
474 stub_h_->Outdent();
475 stub_h_->Print("};\n");
476 }
477
478 // Fields reflection table.
479 stub_h_->Print(
480 "static const ::tracing::v2::proto::ProtoFieldDescriptor* "
481 "GetFieldDescriptor(uint32_t field_id);\n");
482
483 std::string class_name = GetCppClassName(message);
484 if (has_fields) {
485 stub_cc_->Print(
486 "static const ::tracing::v2::proto::ProtoFieldDescriptor "
487 "kFields_$class$[] = {\n",
488 "class", class_name);
489 stub_cc_->Indent();
490 for (int i = 0; i < message->field_count(); ++i) {
491 const FieldDescriptor* field = message->field(i);
492 std::string type_const =
493 std::string("TYPE_") + FieldDescriptor::TypeName(field->type());
494 UpperString(&type_const);
495 stub_cc_->Print(
496 "{\"$name$\", "
497 "::tracing::v2::proto::ProtoFieldDescriptor::Type::$type$, "
498 "$number$, $is_repeated$},\n",
499 "name", field->name(),
500 "type", type_const,
501 "number", std::to_string(field->number()),
502 "is_repeated", std::to_string(field->is_repeated()));
503 }
504 stub_cc_->Outdent();
505 stub_cc_->Print("};\n\n");
506 }
507
508 // Fields reflection getter.
509 stub_cc_->Print(
510 "const ::tracing::v2::proto::ProtoFieldDescriptor* "
511 "$class$::GetFieldDescriptor(uint32_t field_id) {\n",
512 "class", class_name);
513 stub_cc_->Indent();
514 if (has_fields) {
515 stub_cc_->Print("switch (field_id) {\n");
516 stub_cc_->Indent();
517 for (int i = 0; i < message->field_count(); ++i) {
518 stub_cc_->Print(
519 "case $field$:\n"
520 " return &kFields_$class$[$id$];\n",
521 "class", class_name,
522 "field", GetFieldNumberConstant(message->field(i)),
523 "id", std::to_string(i));
524 }
525 stub_cc_->Print(
526 "default:\n"
527 " return &kInvalidField;\n");
528 stub_cc_->Outdent();
529 stub_cc_->Print("}\n");
530 } else {
531 stub_cc_->Print("return &kInvalidField;\n");
532 }
533 stub_cc_->Outdent();
534 stub_cc_->Print("}\n\n");
535 }
536
438 void GenerateMessageDescriptor(const Descriptor* message) { 537 void GenerateMessageDescriptor(const Descriptor* message) {
439 stub_h_->Print( 538 stub_h_->Print(
440 "class $name$ : public ::tracing::v2::ProtoZeroMessage {\n" 539 "class $name$ : public ::tracing::v2::ProtoZeroMessage {\n"
441 " public:\n", 540 " public:\n",
442 "name", GetCppClassName(message)); 541 "name", GetCppClassName(message));
443 stub_h_->Indent(); 542 stub_h_->Indent();
444 543
544 GenerateReflectionForMessageFields(message);
545
445 // Using statements for nested messages. 546 // Using statements for nested messages.
446 for (int i = 0; i < message->nested_type_count(); ++i) { 547 for (int i = 0; i < message->nested_type_count(); ++i) {
447 const Descriptor* nested_message = message->nested_type(i); 548 const Descriptor* nested_message = message->nested_type(i);
448 stub_h_->Print( 549 stub_h_->Print(
449 "using $local_name$ = $global_name$;\n", 550 "using $local_name$ = $global_name$;\n",
450 "local_name", nested_message->name(), 551 "local_name", nested_message->name(),
451 "global_name", GetCppClassName(nested_message, true)); 552 "global_name", GetCppClassName(nested_message, true));
452 } 553 }
453 554
454 // Using statements for nested enums. 555 // Using statements for nested enums.
(...skipping 13 matching lines...) Expand all
468 for (int j = 0; j < nested_enum->value_count(); ++j) { 569 for (int j = 0; j < nested_enum->value_count(); ++j) {
469 const EnumValueDescriptor* value = nested_enum->value(j); 570 const EnumValueDescriptor* value = nested_enum->value(j);
470 stub_h_->Print( 571 stub_h_->Print(
471 "static const $class$ $name$ = $full_name$;\n", 572 "static const $class$ $name$ = $full_name$;\n",
472 "class", nested_enum->name(), 573 "class", nested_enum->name(),
473 "name", value->name(), 574 "name", value->name(),
474 "full_name", value_name_prefix + value->name()); 575 "full_name", value_name_prefix + value->name());
475 } 576 }
476 } 577 }
477 578
478 // Field numbers.
479 if (message->field_count() > 0) {
480 stub_h_->Print("enum : int32_t {\n");
481 stub_h_->Indent();
482
483 for (int i = 0; i < message->field_count(); ++i) {
484 const FieldDescriptor* field = message->field(i);
485 std::string name = field->camelcase_name();
486 if (!name.empty()) {
487 name.at(0) = toupper(name.at(0));
488 } else {
489 // Protoc allows fields like 'bool _ = 1'.
490 Abort("Empty field name in camel case notation.");
491 }
492
493 stub_h_->Print(
494 "k$name$FieldNumber = $id$,\n",
495 "name", name,
496 "id", std::to_string(field->number()));
497 }
498 stub_h_->Outdent();
499 stub_h_->Print("};\n");
500 }
501
502 // Field descriptors. 579 // Field descriptors.
503 for (int i = 0; i < message->field_count(); ++i) { 580 for (int i = 0; i < message->field_count(); ++i) {
504 const FieldDescriptor* field = message->field(i); 581 const FieldDescriptor* field = message->field(i);
505 if (field->is_packed()) { 582 if (field->is_packed()) {
506 Abort("Packed repeated fields are not supported."); 583 Abort("Packed repeated fields are not supported.");
507 return; 584 return;
508 } 585 }
509 if (field->type() != FieldDescriptor::TYPE_MESSAGE) { 586 if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
510 GenerateSimpleFieldDescriptor(field); 587 GenerateSimpleFieldDescriptor(field);
511 } else { 588 } else {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 651
575 if (!job.GenerateStubs()) { 652 if (!job.GenerateStubs()) {
576 *error = job.GetFirstError(); 653 *error = job.GetFirstError();
577 return false; 654 return false;
578 } 655 }
579 return true; 656 return true;
580 } 657 }
581 658
582 } // namespace proto 659 } // namespace proto
583 } // namespace tracing 660 } // namespace tracing
OLDNEW
« no previous file with comments | « components/tracing/test/proto_zero_generation_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698