Chromium Code Reviews| Index: components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc |
| diff --git a/components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc b/components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc |
| index 713d3cca42fea6c28cb102b900dff6842c26bad2..720133e83e3df270ee6554be834f18929dcb3d0e 100644 |
| --- a/components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc |
| +++ b/components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc |
| @@ -43,9 +43,8 @@ class GeneratorJob { |
| GeneratorJob(const FileDescriptor *file, |
| Printer* stub_h_printer, |
| Printer* stub_cc_printer) |
| - : source_(file), |
| - stub_h_(stub_h_printer), |
| - stub_cc_(stub_cc_printer) {} |
| + : source_(file), stub_h_(stub_h_printer), stub_cc_(stub_cc_printer) { |
| + } |
| bool GenerateStubs() { |
| Preprocess(); |
| @@ -101,6 +100,18 @@ class GeneratorJob { |
| return name; |
| } |
| + inline std::string GetFieldNumberConstant(const FieldDescriptor* field) { |
| + std::string name = field->camelcase_name(); |
| + if (!name.empty()) { |
| + name.at(0) = toupper(name.at(0)); |
| + name = std::string("k") + name + "FieldNumber"; |
|
Primiano Tucci (use gerrit)
2016/09/02 16:49:51
you can avoid std::string and just "k" here.
|
| + } else { |
| + // Protoc allows fields like 'bool _ = 1'. |
| + Abort("Empty field name in camel case notation."); |
| + } |
| + return name; |
| + } |
| + |
| // Small enums can be written faster without involving VarInt encoder. |
| inline bool IsTinyEnumField(const FieldDescriptor* field) { |
| if (field->type() != FieldDescriptor::TYPE_ENUM) |
| @@ -263,6 +274,16 @@ class GeneratorJob { |
| } |
| stub_cc_->Print("\n"); |
| + if (messages_.size() > 0) { |
| + stub_cc_->Print( |
| + "namespace {\n" |
| + " static const ::tracing::v2::proto::ProtoFieldDescriptor " |
| + "kInvalidField = {\"\", " |
| + "::tracing::v2::proto::ProtoFieldDescriptor::Type::TYPE_INVALID, " |
| + "0, false};\n" |
| + "}\n\n"); |
| + } |
| + |
| // Print namespaces. |
| for (const std::string& ns : namespaces_) { |
| stub_h_->Print("namespace $ns$ {\n", "ns", ns); |
| @@ -435,6 +456,85 @@ class GeneratorJob { |
| "outer_class", outer_class); |
| } |
| + // TODO(kraynov): Implement reflection for enums. |
|
Primiano Tucci (use gerrit)
2016/09/02 16:49:51
Not sure we need this. I'd remove this todo. If we
|
| + void GenerateReflectionForMessageFields(const Descriptor* message) { |
| + const bool has_fields = (message->field_count() > 0); |
| + |
| + // Field number constants. |
| + if (has_fields) { |
| + stub_h_->Print("enum : int32_t {\n"); |
| + stub_h_->Indent(); |
| + |
| + for (int i = 0; i < message->field_count(); ++i) { |
| + const FieldDescriptor* field = message->field(i); |
| + stub_h_->Print( |
| + "$name$ = $id$,\n", |
| + "name", GetFieldNumberConstant(field), |
| + "id", std::to_string(field->number())); |
| + } |
| + stub_h_->Outdent(); |
| + stub_h_->Print("};\n"); |
| + } |
| + |
| + // Fields reflection table. |
| + stub_h_->Print( |
| + "static const ::tracing::v2::proto::ProtoFieldDescriptor* " |
| + "GetFieldDescriptor(uint32_t field_id);\n"); |
| + |
| + std::string class_name = GetCppClassName(message); |
| + if (has_fields) { |
| + stub_cc_->Print( |
| + "static const ::tracing::v2::proto::ProtoFieldDescriptor " |
| + "kFields_$class$[] = {\n", |
| + "class", class_name); |
| + stub_cc_->Indent(); |
| + for (int i = 0; i < message->field_count(); ++i) { |
| + const FieldDescriptor* field = message->field(i); |
| + std::string type_const = "TYPE_"; |
| + type_const += FieldDescriptor::TypeName(field->type()); |
|
Primiano Tucci (use gerrit)
2016/09/02 16:49:51
maybe you can do this in one line and to:
type_con
|
| + UpperString(&type_const); |
| + stub_cc_->Print( |
| + "{\"$name$\", " |
| + "::tracing::v2::proto::ProtoFieldDescriptor::Type::$type$, " |
| + "$number$, $is_repeated$},\n", |
| + "name", field->name(), |
| + "type", type_const, |
| + "number", std::to_string(field->number()), |
| + "is_repeated", std::to_string(field->is_repeated())); |
| + } |
| + stub_cc_->Outdent(); |
| + stub_cc_->Print("};\n\n"); |
| + } |
| + |
| + // Fields reflection getter. |
| + stub_cc_->Print( |
| + "const ::tracing::v2::proto::ProtoFieldDescriptor* " |
| + "$class$::GetFieldDescriptor(uint32_t field_id) {\n", |
| + "class", class_name); |
| + stub_cc_->Indent(); |
| + if (message->field_count() > 0) { |
| + stub_cc_->Print("switch (field_id) {\n"); |
| + stub_cc_->Indent(); |
| + for (int i = 0; i < message->field_count(); ++i) { |
| + stub_cc_->Print( |
| + "case $field$:\n" |
| + " return &kFields_$class$[$id$];\n", |
| + "class", class_name, |
| + "field", GetFieldNumberConstant(message->field(i)), |
| + "id", std::to_string(i)); |
| + } |
| + stub_cc_->Print( |
| + "default:\n" |
| + " return &kInvalidField;\n"); |
| + stub_cc_->Outdent(); |
| + stub_cc_->Print("}\n"); |
| + } else { |
| + stub_cc_->Print("return &kInvalidField;\n"); |
| + } |
| + stub_cc_->Outdent(); |
| + stub_cc_->Print("}\n\n"); |
| + } |
| + |
| void GenerateMessageDescriptor(const Descriptor* message) { |
| stub_h_->Print( |
| "class $name$ : public ::tracing::v2::ProtoZeroMessage {\n" |
| @@ -442,6 +542,8 @@ class GeneratorJob { |
| "name", GetCppClassName(message)); |
| stub_h_->Indent(); |
| + GenerateReflectionForMessageFields(message); |
| + |
| // Using statements for nested messages. |
| for (int i = 0; i < message->nested_type_count(); ++i) { |
| const Descriptor* nested_message = message->nested_type(i); |
| @@ -475,30 +577,6 @@ class GeneratorJob { |
| } |
| } |
| - // Field numbers. |
| - if (message->field_count() > 0) { |
| - stub_h_->Print("enum : int32_t {\n"); |
| - stub_h_->Indent(); |
| - |
| - for (int i = 0; i < message->field_count(); ++i) { |
| - const FieldDescriptor* field = message->field(i); |
| - std::string name = field->camelcase_name(); |
| - if (!name.empty()) { |
| - name.at(0) = toupper(name.at(0)); |
| - } else { |
| - // Protoc allows fields like 'bool _ = 1'. |
| - Abort("Empty field name in camel case notation."); |
| - } |
| - |
| - stub_h_->Print( |
| - "k$name$FieldNumber = $id$,\n", |
| - "name", name, |
| - "id", std::to_string(field->number())); |
| - } |
| - stub_h_->Outdent(); |
| - stub_h_->Print("};\n"); |
| - } |
| - |
| // Field descriptors. |
| for (int i = 0; i < message->field_count(); ++i) { |
| const FieldDescriptor* field = message->field(i); |