aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/protoc/plugins/cpp_styleguide/cpp_styleguide.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/tools/protoc/plugins/cpp_styleguide/cpp_styleguide.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/tools/protoc/plugins/cpp_styleguide/cpp_styleguide.cpp')
-rw-r--r--contrib/tools/protoc/plugins/cpp_styleguide/cpp_styleguide.cpp1021
1 files changed, 1021 insertions, 0 deletions
diff --git a/contrib/tools/protoc/plugins/cpp_styleguide/cpp_styleguide.cpp b/contrib/tools/protoc/plugins/cpp_styleguide/cpp_styleguide.cpp
new file mode 100644
index 00000000000..cd96aa05657
--- /dev/null
+++ b/contrib/tools/protoc/plugins/cpp_styleguide/cpp_styleguide.cpp
@@ -0,0 +1,1021 @@
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include "cpp_styleguide.h"
+#include <util/stream/output.h>
+
+namespace NProtobuf {
+namespace NCompiler {
+namespace NPlugins {
+
+ using namespace google::protobuf;
+ using namespace google::protobuf::compiler;
+ using namespace google::protobuf::compiler::cpp;
+
+ typedef std::map<TProtoStringType, TProtoStringType> TVariables;
+
+ bool GenerateYaStyle(const FileDescriptor* fileDescriptor) {
+ const auto& extension = fileDescriptor->FindExtensionByName("GenerateYaStyle");
+ return extension;
+ }
+
+ bool GenerateYaStyle(const FieldDescriptor* descriptor) {
+ const auto& fileDescriptor = descriptor->file();
+ return GenerateYaStyle(fileDescriptor);
+ }
+
+
+ void SetCommonFieldVariables(const FieldDescriptor* descriptor, TVariables* variables) {
+ const auto& name = descriptor->name();
+ if (GenerateYaStyle(descriptor))
+ (*variables)["rname"] = UnderscoresToCamelCase(name, true);
+ else
+ (*variables)["rname"] = name;
+ (*variables)["name"] = FieldName(descriptor);
+ }
+
+ TProtoStringType HeaderFileName(const FileDescriptor* file) {
+ TProtoStringType basename = compiler::StripProto(file->name());
+ return basename.append(".pb.h");
+ }
+
+ TProtoStringType SourceFileName(const FileDescriptor* file) {
+ TProtoStringType basename = compiler::StripProto(file->name());
+ return basename.append(".pb.cc");
+ }
+
+ bool IsLiteRuntimeMessage(const Descriptor* desc) {
+ return desc->file() != NULL && desc->file()->options().optimize_for() == google::protobuf::FileOptions::LITE_RUNTIME;
+ }
+
+ bool IsAutogeneratedNestedType(const Descriptor* desc) {
+ return desc->options().map_entry();
+ }
+
+ class TFieldExtGenerator {
+ public:
+ TFieldExtGenerator(const FieldDescriptor* field)
+ : Field_(field)
+ {
+ SetCommonFieldVariables(Field_, &Variables_);
+ }
+
+ virtual ~TFieldExtGenerator() {
+ }
+
+ virtual void GenerateAccessorDeclarations(io::Printer* printer) = 0;
+ virtual void GenerateJSONPrinting(io::Printer* printer) = 0;
+
+ protected:
+ void GenerateRepeatedJSONPrinting(io::Printer* printer, const char* itemPrinter) {
+ printer->Print("out << '[';\n");
+ printer->Print("{\n");
+ printer->Indent();
+ printer->Print("const char* separator = \"\";\n");
+ printer->Print(Variables_, "for (size_t _index = 0; _index < $rname$Size(); ++_index) {\n");
+ printer->Indent();
+ printer->Print("out << separator;\n");
+ printer->Print(Variables_, itemPrinter);
+ printer->Print(";\n");
+ printer->Print("separator = \",\";\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("out << ']';\n");
+ }
+
+ protected:
+ const FieldDescriptor* Field_;
+ TVariables Variables_;
+ };
+
+
+ class TMessageFieldExtGenerator: public TFieldExtGenerator {
+ public:
+ TMessageFieldExtGenerator(const FieldDescriptor* field)
+ : TFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateAccessorDeclarations(io::Printer* printer) {
+ Variables_["type"] = QualifiedClassName(Field_->message_type());
+
+ printer->Print(Variables_,
+ "inline const $type$& Get$rname$() const { return $name$(); }\n"
+ "inline $type$* Mutable$rname$() { return mutable_$name$(); }\n");
+ if (Variables_.end() != Variables_.find("RName"))
+ printer->Print(Variables_,
+ "inline const $type$& Get$RName$() const { return $name$(); }\n"
+ "inline $type$* Mutable$RName$() { return mutable_$name$(); }\n");
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ printer->Print(Variables_, "Get$rname$().PrintJSON(out);\n");
+ }
+ };
+
+ class TMapFieldExtGenerator: public TFieldExtGenerator {
+ public:
+ TMapFieldExtGenerator(const FieldDescriptor* field)
+ : TFieldExtGenerator(field)
+ , Key_(field->message_type()->FindFieldByName("key"))
+ , Val_(field->message_type()->FindFieldByName("value"))
+ {
+ Variables_["key_cpp"] = PrimitiveTypeName(Key_->cpp_type());
+
+ switch (Val_->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ Variables_["val_cpp"] = QualifiedClassName(Val_->message_type());
+ break;
+ case FieldDescriptor::CPPTYPE_ENUM:
+ Variables_["val_cpp"] = ClassName(Val_->enum_type(), true);
+ break;
+ default:
+ Variables_["val_cpp"] = PrimitiveTypeName(Val_->cpp_type());
+ }
+ }
+
+ void GenerateAccessorDeclarations(io::Printer* printer) {
+ printer->Print(Variables_,
+ "inline const ::google::protobuf::Map<$key_cpp$, $val_cpp$>& Get$rname$() const { return $name$(); }\n"
+ "inline ::google::protobuf::Map<$key_cpp$, $val_cpp$>* Mutable$rname$() { return mutable_$name$(); }\n");
+ if (Variables_.end() != Variables_.find("RName"))
+ printer->Print(Variables_,
+ "inline const ::google::protobuf::Map<$key_cpp$, $val_cpp$>& Get$RName$() const { return $name$(); }\n"
+ "inline ::google::protobuf::Map<$key_cpp$, $val_cpp$>* Mutable$RName$() { return mutable_$name$(); }\n");
+ }
+
+ void GenerateKeyValuePrinting(io::Printer* printer, const char* scopeName, bool isKey) {
+ const FieldDescriptor* desc = isKey ? Key_ : Val_;
+
+ switch(desc->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_STRING:
+ printer->Print(TString::Join("::google::protobuf::io::PrintJSONString(out, ", scopeName , ");\n").data());
+ break;
+ case FieldDescriptor::CPPTYPE_ENUM:
+ printer->Print(TString::Join("out << int(", scopeName, ");\n").data());
+ break;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ printer->Print(TString::Join(scopeName, ".PrintJSON(out);\n").data());
+ break;
+ default:
+ if (isKey) {
+ printer->Print(TString::Join("out << '\"' << ", scopeName, " << '\"';\n").data());
+ } else {
+ printer->Print(TString::Join("out << ", scopeName, ";\n").data());
+ }
+ }
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) {
+ printer->Print(Variables_,
+ "out << '{';\n"
+ "const ::google::protobuf::Map<$key_cpp$, $val_cpp$>& map = Get$rname$();\n"
+ "for (auto it = map.begin(); it != map.end(); ++it) {\n"
+ );
+ printer->Indent();
+ printer->Print("if (it != map.begin()) { out << ','; }\n");
+
+ GenerateKeyValuePrinting(printer, "it->first", true);
+ printer->Print("out << ':';\n");
+ GenerateKeyValuePrinting(printer, "it->second", false);
+
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("out << '}';\n");
+ }
+
+ private:
+ const FieldDescriptor* Key_;
+ const FieldDescriptor* Val_;
+ };
+
+ class TRepeatedMessageFieldExtGenerator: public TFieldExtGenerator {
+ public:
+ TRepeatedMessageFieldExtGenerator(const FieldDescriptor* field)
+ : TFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateAccessorDeclarations(io::Printer* printer) {
+ Variables_["type"] = QualifiedClassName(Field_->message_type());
+
+ printer->Print(Variables_,
+ "inline const $type$& Get$rname$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(int(_index)); }\n"
+ "inline $type$* Mutable$rname$(size_t _index) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return mutable_$name$(int(_index)); }\n"
+ "inline $type$* Add$rname$() { return add_$name$(); }\n"
+ "inline const $type$& get_idx_$name$(int _index) const { return $name$(_index); }\n"
+ "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " get_arr_$name$() const { return $name$(); }\n"
+ "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " Get$rname$() const { return $name$(); }\n"
+ "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ " Mutable$rname$() { return mutable_$name$(); }\n");
+
+ if (Variables_.end() != Variables_.find("RName"))
+ printer->Print(Variables_,
+ "inline const $type$& Get$RName$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(int(_index)); }\n"
+ "inline $type$* Mutable$RName$(size_t _index) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return mutable_$name$(int(_index)); }\n"
+ "inline $type$* Add$RName$() { return add_$name$(); }\n"
+ "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " Get$RName$() const { return $name$(); }\n"
+ "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ " Mutable$RName$() { return mutable_$name$(); }\n"
+ );
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ GenerateRepeatedJSONPrinting(printer, "Get$rname$(_index).PrintJSON(out)");
+ }
+ };
+
+ class TStringFieldExtGenerator: public TFieldExtGenerator {
+ public:
+ TStringFieldExtGenerator(const FieldDescriptor* field)
+ : TFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateAccessorDeclarations(io::Printer* printer) {
+ Variables_["pointer_type"] = Field_->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
+
+ if (Field_->options().ctype() != FieldOptions::STRING) {
+ printer->Outdent();
+ printer->Print(
+ " private:\n"
+ " // Hidden due to unknown ctype option.\n");
+ printer->Indent();
+ }
+
+ printer->Print(Variables_,
+ "inline const TProtoStringType& Get$rname$() const { return $name$(); }\n"
+ "inline void Set$rname$(const TProtoStringType& value) { set_$name$(value); }\n"
+ "inline void Set$rname$(TProtoStringType&& value) { set_$name$(std::move(value)); }\n"
+ "inline void Set$rname$(const char* value) { set_$name$(value); }\n"
+ "inline void Set$rname$(const $pointer_type$* value, size_t size) { set_$name$(value, size); }\n"
+ "inline TProtoStringType* Mutable$rname$() { return mutable_$name$(); }\n");
+
+ if (Variables_.end() != Variables_.find("RName"))
+ printer->Print(Variables_,
+ "inline const TProtoStringType& Get$RName$() const { return $name$(); }\n"
+ "inline void Set$RName$(const TProtoStringType& value) { set_$name$(value); }\n"
+ "inline void Set$RName$(TProtoStringType&& value) { set_$name$(std::move(value)); }\n"
+ "inline void Set$RName$(const char* value) { set_$name$(value); }\n"
+ "inline void Set$RName$(const $pointer_type$* value, size_t size) { set_$name$(value, size); }\n"
+ "inline TProtoStringType* Mutable$RName$() { return mutable_$name$(); }\n"
+ );
+
+ if (Field_->options().ctype() != FieldOptions::STRING) {
+ printer->Outdent();
+ printer->Print(" public:\n");
+ printer->Indent();
+ }
+
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ printer->Print(Variables_, "::google::protobuf::io::PrintJSONString(out, Get$rname$());\n");
+ }
+ };
+
+ class TRepeatedStringFieldExtGenerator: public TFieldExtGenerator {
+ public:
+ TRepeatedStringFieldExtGenerator(const FieldDescriptor* field)
+ : TFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateAccessorDeclarations(io::Printer* printer) {
+ Variables_["pointer_type"] = Field_->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
+
+ if (Field_->options().ctype() != FieldOptions::STRING) {
+ printer->Outdent();
+ printer->Print(
+ " private:\n"
+ " // Hidden due to unknown ctype option.\n");
+ printer->Indent();
+ }
+
+ printer->Print(Variables_,
+ "inline const TProtoStringType& Get$rname$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(_index); }\n"
+ "inline TProtoStringType* Mutable$rname$(size_t _index) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return mutable_$name$(_index); }\n"
+ "inline void Set$rname$(size_t _index, const TProtoStringType& value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
+ "inline void Set$rname$(size_t _index, TProtoStringType&& value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, std::move(value)); }\n"
+ "inline void Set$rname$(size_t _index, const char* value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
+ "inline void Set$rname$(size_t _index, const $pointer_type$* value, size_t size) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value, size); }\n"
+ "inline TProtoStringType* Add$rname$() { return add_$name$(); }\n"
+ "inline void Add$rname$(const TProtoStringType& value) { add_$name$(value); }\n"
+ "inline void Add$rname$(TProtoStringType&& value) { add_$name$(std::move(value)); }\n"
+ "inline void Add$rname$(const char* value) { add_$name$(value); }\n"
+ "inline void Add$rname$(const $pointer_type$* value, size_t size) { add_$name$(value, size); }\n"
+ "inline const TProtoStringType& get_idx_$name$(int _index) const { return $name$(_index); }\n"
+ "inline const ::google::protobuf::RepeatedPtrField<TProtoStringType>& get_arr_$name$() const"
+ "{ return $name$(); }\n"
+ "inline const ::google::protobuf::RepeatedPtrField<TProtoStringType>& Get$rname$() const"
+ "{ return $name$(); }\n"
+ "inline ::google::protobuf::RepeatedPtrField<TProtoStringType>* Mutable$rname$()"
+ "{ return mutable_$name$(); }\n");
+
+ if (Variables_.end() != Variables_.find("RName"))
+ printer->Print(Variables_,
+ "inline const TProtoStringType& Get$RName$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(_index); }\n"
+ "inline TProtoStringType* Mutable$RName$(size_t _index) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return mutable_$name$(_index); }\n"
+ "inline void Set$RName$(size_t _index, const TProtoStringType& value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
+ "inline void Set$RName$(size_t _index, TProtoStringType&& value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, std::move(value)); }\n"
+ "inline void Set$RName$(size_t _index, const char* value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
+ "inline void Set$RName$(size_t _index, const $pointer_type$* value, size_t size) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value, size); }\n"
+ "inline TProtoStringType* Add$RName$() { return add_$name$(); }\n"
+ "inline void Add$RName$(const TProtoStringType& value) { add_$name$(value); }\n"
+ "inline void Add$RName$(TProtoStringType&& value) { add_$name$(std::move(value)); }\n"
+ "inline void Add$RName$(const char* value) { add_$name$(value); }\n"
+ "inline void Add$RName$(const $pointer_type$* value, size_t size) { add_$name$(value, size); }\n"
+ "inline const ::google::protobuf::RepeatedPtrField<TProtoStringType>& Get$RName$() const"
+ "{ return $name$(); }\n"
+ "inline ::google::protobuf::RepeatedPtrField<TProtoStringType>* Mutable$RName$()"
+ "{ return mutable_$name$(); }\n"
+ );
+
+ if (Field_->options().ctype() != FieldOptions::STRING) {
+ printer->Outdent();
+ printer->Print(" public:\n");
+ printer->Indent();
+ }
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ GenerateRepeatedJSONPrinting(
+ printer,
+ "::google::protobuf::io::PrintJSONString(out, Get$rname$(_index))"
+ );
+ }
+ };
+
+ class TEnumFieldExtGenerator: public TFieldExtGenerator {
+ public:
+ TEnumFieldExtGenerator(const FieldDescriptor* field)
+ : TFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateAccessorDeclarations(io::Printer* printer) {
+ Variables_["type"] = ClassName(Field_->enum_type(), true);
+
+ printer->Print(Variables_,
+ "inline $type$ Get$rname$() const { return $name$(); }\n"
+ "inline void Set$rname$($type$ value) { set_$name$(value); }\n");
+
+ if (Variables_.end() != Variables_.find("RName"))
+ printer->Print(Variables_,
+ "inline $type$ Get$RName$() const { return $name$(); } \n"
+ "inline void Set$RName$($type$ value) { set_$name$(value); }\n"
+ );
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ printer->Print(Variables_, "out << (int)Get$rname$();\n");
+ }
+ };
+
+ class TRepeatedEnumFieldExtGenerator: public TFieldExtGenerator {
+ public:
+ TRepeatedEnumFieldExtGenerator(const FieldDescriptor* field)
+ : TFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateAccessorDeclarations(io::Printer* printer) {
+ Variables_["type"] = ClassName(Field_->enum_type(), true);
+
+ printer->Print(Variables_,
+ "inline $type$ Get$rname$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(_index); }\n"
+ "inline void Set$rname$(size_t _index, $type$ value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
+ "inline void Add$rname$($type$ value) { add_$name$(value); }\n"
+ "inline $type$ get_idx_$name$(int _index) const {return $name$(_index); }\n"
+ "inline const ::google::protobuf::RepeatedField<int>& get_arr_$name$() const { return $name$(); }\n"
+ "inline const ::google::protobuf::RepeatedField<int>& Get$rname$() const { return $name$(); }\n"
+ "inline ::google::protobuf::RepeatedField<int>* Mutable$rname$() { return mutable_$name$(); }\n");
+ if (Variables_.end() != Variables_.find("RName"))
+ printer->Print(Variables_,
+ "inline $type$ Get$RName$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(_index); }\n"
+ "inline void Set$RName$(size_t _index, $type$ value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
+ "inline void Add$RName$($type$ value) { add_$name$(value); }\n"
+ "inline const ::google::protobuf::RepeatedField<int>& Get$RName$() const { return $name$(); }\n"
+ "inline ::google::protobuf::RepeatedField<int>* Mutable$RName$() { return mutable_$name$(); }\n"
+ );
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ GenerateRepeatedJSONPrinting(printer, "out << (int)Get$rname$(_index)");
+ }
+ };
+
+ class TPrimitiveFieldExtGenerator: public TFieldExtGenerator {
+ public:
+ TPrimitiveFieldExtGenerator(const FieldDescriptor* field)
+ : TFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateAccessorDeclarations(io::Printer* printer) {
+ Variables_["type"] = PrimitiveTypeName(Field_->cpp_type());
+
+ printer->Print(Variables_,
+ "inline $type$ Get$rname$() const { return $name$();}\n"
+ "inline void Set$rname$($type$ value) { set_$name$(value); }\n");
+ if (Variables_.end() != Variables_.find("RName"))
+ printer->Print(Variables_,
+ "inline $type$ Get$RName$() const { return $name$();}\n"
+ "inline void Set$RName$($type$ value) { set_$name$(value); }\n"
+ );
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ printer->Print(Variables_, "out << Get$rname$();\n");
+ }
+ };
+
+ class TRepeatedPrimitiveFieldExtGenerator: public TFieldExtGenerator {
+ public:
+ TRepeatedPrimitiveFieldExtGenerator(const FieldDescriptor* field)
+ : TFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateAccessorDeclarations(io::Printer* printer) {
+ Variables_["type"] = PrimitiveTypeName(Field_->cpp_type());
+
+ printer->Print(Variables_,
+ "inline $type$ Get$rname$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(_index); }\n"
+ "inline void Set$rname$(size_t _index, $type$ value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
+ "inline void Add$rname$($type$ value) { add_$name$(value); }\n"
+ "inline $type$ get_idx_$name$(int _index) const { return $name$(_index); }\n"
+ "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+ " get_arr_$name$() const { return $name$(); }\n"
+ "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+ " Get$rname$() const { return $name$(); }\n"
+ "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+ " Mutable$rname$() { return mutable_$name$(); }\n");
+ if (Variables_.end() != Variables_.find("RName"))
+ printer->Print(Variables_,
+ "inline $type$ Get$RName$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(_index); }\n"
+ "inline void Set$RName$(size_t _index, $type$ value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
+ "inline void Add$RName$($type$ value) { add_$name$(value); }\n"
+ "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+ " Get$RName$() const { return $name$(); }\n"
+ "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+ " Mutable$RName$() { return mutable_$name$(); }\n"
+ );
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ GenerateRepeatedJSONPrinting(printer, "out << Get$rname$(_index)");
+ }
+ };
+
+ class TBoolFieldExtGenerator: public TPrimitiveFieldExtGenerator {
+ public:
+ TBoolFieldExtGenerator(const FieldDescriptor* field)
+ : TPrimitiveFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ printer->Print(Variables_, "out << (Get$rname$() ? \"true\" : \"false\");\n");
+ }
+ };
+
+ class TRepeatedBoolFieldExtGenerator: public TRepeatedPrimitiveFieldExtGenerator {
+ public:
+ TRepeatedBoolFieldExtGenerator(const FieldDescriptor* field)
+ : TRepeatedPrimitiveFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ GenerateRepeatedJSONPrinting(printer, "out << (Get$rname$(_index) ? \"true\" : \"false\")");
+ }
+ };
+
+ class TFloatFieldExtGenerator: public TPrimitiveFieldExtGenerator {
+ public:
+ TFloatFieldExtGenerator(const FieldDescriptor* field)
+ : TPrimitiveFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ printer->Print(Variables_, "out << double(Get$rname$());\n");
+ }
+ };
+
+ class TRepeatedFloatFieldExtGenerator: public TRepeatedPrimitiveFieldExtGenerator {
+ public:
+ TRepeatedFloatFieldExtGenerator(const FieldDescriptor* field)
+ : TRepeatedPrimitiveFieldExtGenerator(field)
+ {
+ }
+
+ void GenerateJSONPrinting(io::Printer* printer) override {
+ GenerateRepeatedJSONPrinting(printer, "out << double(Get$rname$(_index))");
+ }
+ };
+
+ // borrowed mostly from protobuf/compiler/cpp/cpp_extension.cc
+ class TExtensionGenerator {
+ public:
+ TExtensionGenerator(const FieldDescriptor* descriptor)
+ : Descriptor_(descriptor)
+ {
+ if (Descriptor_->is_repeated()) {
+ type_traits_ = "Repeated";
+ }
+
+ TProtoStringType clsName;
+ switch (Descriptor_->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_ENUM:
+ type_traits_.append("EnumTypeTraits< ");
+ clsName = ClassName(Descriptor_->enum_type(), true);
+ type_traits_.append(clsName);
+ type_traits_.append(", ");
+ type_traits_.append(clsName);
+ type_traits_.append("_IsValid>");
+ break;
+ case FieldDescriptor::CPPTYPE_STRING:
+ type_traits_.append("StringTypeTraits");
+ break;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ type_traits_.append("MessageTypeTraits< ");
+ type_traits_.append(ClassName(Descriptor_->message_type(), true));
+ type_traits_.append(" >");
+ break;
+ default:
+ type_traits_.append("PrimitiveTypeTraits< ");
+ type_traits_.append(PrimitiveTypeName(Descriptor_->cpp_type()));
+ type_traits_.append(" >");
+ break;
+ }
+ }
+
+ void GenerateDeclaration(io::Printer* printer) const
+ {
+ TVariables vars;
+ vars["extendee" ] = ClassName(Descriptor_->containing_type(), true);
+ vars["type_traits" ] = type_traits_;
+ vars["name" ] = Descriptor_->name();
+ vars["field_type" ] = SimpleItoa(static_cast<int>(Descriptor_->type()));
+ vars["packed" ] = Descriptor_->options().packed() ? "true" : "false";
+
+ printer->Print(vars,
+ "typedef ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
+ " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
+ " Td$name$;\n"
+ );
+ }
+
+ private:
+ const FieldDescriptor* Descriptor_;
+ TProtoStringType type_traits_;
+ };
+
+ class TOneofGenerator {
+ public:
+ TOneofGenerator(const OneofDescriptor* Descriptor_)
+ : Descriptor_(Descriptor_)
+ {
+ Variables_["camel_oneof_name"] = UnderscoresToCamelCase(Descriptor_->name(), true);
+ Variables_["rname"] = Descriptor_->name();
+ }
+
+ void GenerateDeclarations(io::Printer* printer) const {
+ printer->Print(Variables_, "$camel_oneof_name$Case Get$rname$Case() const { return $rname$_case(); }\n");
+ printer->Print(Variables_, "void Clear$rname$() { clear_$rname$(); }\n");
+
+ if (Descriptor_->name() != UnderscoresToCamelCase(Descriptor_->name(), true)) {
+ printer->Print(Variables_, "$camel_oneof_name$Case Get$camel_oneof_name$Case() const { return $rname$_case(); }\n");
+ printer->Print(Variables_, "void Clear$camel_oneof_name$() { clear_$rname$(); }\n");
+ }
+ }
+
+ private:
+ const OneofDescriptor* Descriptor_;
+ TVariables Variables_;
+ };
+
+ TFieldExtGenerator* MakeGenerator(const FieldDescriptor* field) {
+ if (field->is_repeated()) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ if (field->is_map()) {
+ return new TMapFieldExtGenerator(field);
+ }
+ return new TRepeatedMessageFieldExtGenerator(field);
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return new TRepeatedBoolFieldExtGenerator(field);
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return new TRepeatedFloatFieldExtGenerator(field);
+ case FieldDescriptor::CPPTYPE_STRING:
+ switch (field->options().ctype()) {
+ default: // RepeatedStringFieldExtGenerator handles unknown ctypes.
+ case FieldOptions::STRING:
+ return new TRepeatedStringFieldExtGenerator(field);
+ }
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return new TRepeatedEnumFieldExtGenerator(field);
+ default:
+ return new TRepeatedPrimitiveFieldExtGenerator(field);
+ }
+ } else {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return new TMessageFieldExtGenerator(field);
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return new TBoolFieldExtGenerator(field);
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return new TFloatFieldExtGenerator(field);
+ case FieldDescriptor::CPPTYPE_STRING:
+ switch (field->options().ctype()) {
+ default: // StringFieldGenerator handles unknown ctypes.
+ case FieldOptions::STRING:
+ return new TStringFieldExtGenerator(field);
+ }
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return new TEnumFieldExtGenerator(field);
+ default:
+ return new TPrimitiveFieldExtGenerator(field);
+ }
+ }
+ }
+
+ class TMessageExtGenerator {
+ public:
+ TMessageExtGenerator(const Descriptor* descriptor, OutputDirectory* outputDirectory)
+ : Descriptor_(descriptor)
+ , Classname_(ClassName(descriptor, false))
+ , OutputDirectory_(outputDirectory)
+ {
+ for (int i = 0, idx = 0; i < descriptor->nested_type_count(); i++) {
+ if (!IsAutogeneratedNestedType(descriptor->nested_type(i))) {
+ NestedGenerators_.emplace_back(descriptor->nested_type(i), OutputDirectory_);
+ }
+ }
+
+ FieldGenerators_.reserve(descriptor->field_count());
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ FieldGenerators_.emplace_back(MakeGenerator(descriptor->field(i)));
+ }
+
+ ExtensionGenerators_.reserve(descriptor->extension_count());
+ for (int i = 0; i < descriptor->extension_count(); i++) {
+ ExtensionGenerators_.emplace_back(descriptor->extension(i));
+ }
+
+ OneofGenerators_.reserve(descriptor->real_oneof_decl_count());
+ for (int i = 0; i < descriptor->real_oneof_decl_count(); i++) {
+ OneofGenerators_.emplace_back(descriptor->oneof_decl(i));
+ }
+ }
+
+ void GenerateClassDefinitionExtension() {
+ GenerateSaveLoadImplementation();
+ GenerateJSONImplementation();
+
+ for (auto& nestedGenerator: NestedGenerators_) {
+ nestedGenerator.GenerateClassDefinitionExtension();
+ }
+ }
+
+ void GenerateDebugOutputExtension() {
+ GenerateDebugOutput();
+
+ for (auto& nestedGenerator: NestedGenerators_) {
+ nestedGenerator.GenerateDebugOutputExtension();
+ }
+ }
+
+ void GenerateTypedefOutputExtension(bool nested) {
+ GenerateTypedefOutput(nested);
+
+ for (auto& nestedGenerator: NestedGenerators_) {
+ nestedGenerator.GenerateTypedefOutputExtension(true);
+ }
+ }
+
+
+ void GenerateClassExtension() {
+ GenerateDebugStringImplementation();
+ for (auto& nestedGenerator: NestedGenerators_) {
+ nestedGenerator.GenerateClassExtension();
+ }
+ }
+
+ void GenerateDeclarations() {
+ GenerateFieldAccessorDeclarations();
+
+ for (auto& nestedGenerator: NestedGenerators_) {
+ nestedGenerator.GenerateDeclarations();
+ }
+ }
+
+ void GenerateDefinitions() {
+ GenerateClassExtension();
+ GenerateDebugOutputExtension();
+ GenerateClassDefinitionExtension();
+ }
+
+ private:
+ void GenerateFieldAccessorDeclarations() {
+ TProtoStringType fileName = HeaderFileName(Descriptor_->file());
+ TProtoStringType scope = "class_scope:" + Descriptor_->full_name();
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ OutputDirectory_->OpenForInsert(fileName, scope));
+ io::Printer printer(output.get(), '$');
+
+ printer.Print("// Yandex cpp-styleguide extension\n");
+ for (int i = 0; i < Descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = Descriptor_->field(i);
+
+ TVariables vars;
+ SetCommonFieldVariables(field, &vars);
+
+ const bool hasRName = (vars.end() != vars.find("RName"));
+ if (field->is_repeated()) {
+ printer.Print(vars,
+ "inline size_t $rname$Size() const { return (size_t)$name$_size(); }\n");
+ if (hasRName)
+ printer.Print(vars,
+ "inline size_t $RName$Size() const { return (size_t)$name$_size(); }\n");
+ } else if (field->has_presence()) {
+ printer.Print(vars,
+ "inline bool Has$rname$() const { return has_$name$(); }\n");
+ if (hasRName)
+ printer.Print(vars,
+ "inline bool Has$RName$() const { return has_$name$(); }\n");
+ }
+
+ printer.Print(vars, "inline void Clear$rname$() { clear_$name$(); }\n");
+ if (hasRName)
+ printer.Print(vars,
+ "inline void Clear$RName$() { clear_$name$(); }\n");
+
+ // Generate type-specific accessor declarations.
+ FieldGenerators_[i]->GenerateAccessorDeclarations(&printer);
+
+ printer.Print("\n");
+ }
+ for (auto& extensionGenerator: ExtensionGenerators_) {
+ extensionGenerator.GenerateDeclaration(&printer);
+ }
+ for (auto& oneofGenerator: OneofGenerators_) {
+ oneofGenerator.GenerateDeclarations(&printer);
+ }
+ TVariables vars;
+ vars["class"] = ClassName(Descriptor_, false);
+ if (!IsLiteRuntimeMessage(Descriptor_)) {
+ printer.Print("TProtoStringType ShortUtf8DebugString() const;\n");
+
+ printer.Print("void PrintJSON(IOutputStream&) const override;\n");
+ printer.Print(vars, "::google::protobuf::io::TAsJSON<$class$> AsJSON() const {\n");
+ printer.Print(vars, " return ::google::protobuf::io::TAsJSON<$class$>(*this);\n");
+ printer.Print("}\n");
+
+ printer.Print("void Save(IOutputStream* output) const;\n");
+ printer.Print("void Load(IInputStream* input);\n");
+ }
+ printer.Print("// End of Yandex-specific extension\n");
+ }
+
+ void GenerateSaveLoadImplementation() {
+ TProtoStringType fileName = SourceFileName(Descriptor_->file());
+ TProtoStringType scope = "namespace_scope";
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ OutputDirectory_->OpenForInsert(fileName, scope));
+ io::Printer printer(output.get(), '$');
+
+ TVariables vars;
+ vars["class"] = Classname_;
+ if (!IsLiteRuntimeMessage(Descriptor_)) {
+ printer.Print("// Yandex-specific extension\n");
+ printer.Print(vars, "void $class$::Save(IOutputStream* output) const {\n");
+ printer.Print(" ::Save(output, static_cast<const ::google::protobuf::Message&>(*this));\n");
+ printer.Print("}\n");
+ printer.Print(vars, "void $class$::Load(IInputStream* input) {\n");
+ printer.Print(" ::Load(input, static_cast<::google::protobuf::Message&>(*this));\n");
+ printer.Print("}\n");
+ printer.Print("// End of Yandex-specific extension\n");
+ }
+ }
+
+ void GenerateDebugStringImplementation() {
+ TProtoStringType fileName = SourceFileName(Descriptor_->file());
+ TProtoStringType scope = "namespace_scope";
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ OutputDirectory_->OpenForInsert(fileName, scope));
+ io::Printer printer(output.get(), '$');
+
+ TVariables vars;
+ vars["class"] = Classname_;
+ if (!IsLiteRuntimeMessage(Descriptor_)) {
+ printer.Print("// Yandex-specific extension\n");
+ printer.Print(vars, "TProtoStringType $class$::ShortUtf8DebugString() const {\n");
+ printer.Print(" return ::ShortUtf8DebugString(*this);\n");
+ printer.Print("}\n");
+ printer.Print("// End of Yandex-specific extension\n");
+ }
+ }
+
+ void GenerateJSONImplementation() {
+ if (IsLiteRuntimeMessage(Descriptor_)) {
+ return;
+ }
+
+ TProtoStringType fileName = SourceFileName(Descriptor_->file());
+ TProtoStringType scope = "namespace_scope";
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ OutputDirectory_->OpenForInsert(fileName, scope));
+ io::Printer printer(output.get(), '$');
+ printer.Print("// Yandex JSON extension\n");
+ TVariables vars;
+ vars["class"] = ClassName(Descriptor_, true);
+ printer.Print(vars, "inline void $class$::PrintJSON(IOutputStream& out) const {\n");
+
+ printer.Indent();
+ printer.Print("out << '{';\n");
+ if (Descriptor_->field_count() > 0) {
+ printer.Print("const char* sep = \"\";\n");
+ }
+ for (int i = 0; i < Descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = Descriptor_->field(i);
+
+ TVariables vars;
+ SetCommonFieldVariables(field, &vars);
+
+ if (field->is_repeated()) {
+ // map or repeated field in both proto3 and proto2 syntax
+ printer.Print(vars, "if ($rname$Size() > 0) {\n");
+ } else if (field->has_presence()) {
+ // any optional or required field in proto2 syntax
+ // message-field or any oneof field in proto3 syntax
+ printer.Print(vars, "if (Has$rname$()) {\n");
+ } else {
+ // string, enum or primitive field in proto3 syntax
+ printer.Print(vars, "if (Get$rname$()) {\n");
+ }
+
+ printer.Indent();
+ printer.Print("out << sep;\n");
+ printer.Print(vars, "out << \"\\\"$rname$\\\":\";\n");
+ FieldGenerators_[i]->GenerateJSONPrinting(&printer);
+ printer.Print(vars, "sep = \",\";\n");
+ printer.Outdent();
+ printer.Print("}\n");
+ }
+ printer.Print("out << '}';\n");
+ printer.Outdent();
+ printer.Print("}\n");
+
+ printer.Print("// End of Yandex JSON extension\n");
+ }
+
+ void GenerateDebugOutput() {
+ TProtoStringType fileName = SourceFileName(Descriptor_->file());
+ TProtoStringType scope = "global_scope";
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ OutputDirectory_->OpenForInsert(fileName, scope));
+ io::Printer printer(output.get(), '$');
+ if (!IsLiteRuntimeMessage(Descriptor_)) {
+ printer.Print("// Yandex debug output extension\n");
+ TVariables vars;
+ vars["class"] = ClassName(Descriptor_, true);
+ printer.Print("template<>\n");
+ printer.Print(vars, "void Out< $class$>(IOutputStream& out, const $class$& msg) {\n");
+ printer.Print(" out << \"{ \" << msg.ShortUtf8DebugString() << \" }\";\n");
+ printer.Print("}\n");
+ printer.Print("// End of Yandex debug output extension\n");
+ }
+ }
+
+ void GenerateTypedefOutput(bool nested) {
+ if (!GenerateYaStyle(Descriptor_->file()))
+ return;
+ TProtoStringType fileName = HeaderFileName(Descriptor_->file());
+ TProtoStringType scope = nested ? "class_scope:" + Descriptor_->full_name().substr(0,
+ Descriptor_->full_name().size() - Descriptor_->name().size() - 1)
+ : "namespace_scope";
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ OutputDirectory_->OpenForInsert(fileName, scope));
+ io::Printer printer(output.get(), '$');
+ TString name = Descriptor_->name();
+ bool isOk = name.size() >= 2 && name[0] == 'T' && name[1] >= 'A' && name[1] <= 'Z';
+ if (!isOk) {
+ printer.Print("// Yandex typedef extension\n");
+ TVariables vars;
+ vars["class"] = name;
+ vars["base_class"] = ClassName(Descriptor_, true);
+ printer.Print(vars, "typedef $base_class$ T$class$;\n");
+ printer.Print("// End of Yandex typedef extension\n");
+ }
+ }
+
+
+ private:
+ const Descriptor* Descriptor_;
+ TProtoStringType Classname_;
+ OutputDirectory* OutputDirectory_;
+ std::vector<std::unique_ptr<TFieldExtGenerator>> FieldGenerators_;
+ std::vector<TMessageExtGenerator> NestedGenerators_;
+ std::vector<TExtensionGenerator> ExtensionGenerators_;
+ std::vector<TOneofGenerator> OneofGenerators_;
+ };
+
+ class TFileExtGenerator {
+ public:
+ TFileExtGenerator(const FileDescriptor* file, OutputDirectory* output_directory)
+ : File_(file)
+ , OutputDirectory_(output_directory)
+ {
+ MessageGenerators_.reserve(file->message_type_count());
+ for (size_t i = 0; i < file->message_type_count(); i++) {
+ MessageGenerators_.emplace_back(file->message_type(i), OutputDirectory_);
+ }
+ }
+
+ void GenerateHeaderExtensions() {
+ GenerateHeaderIncludeExtensions();
+
+ for (auto& messageGenerator: MessageGenerators_) {
+ messageGenerator.GenerateTypedefOutputExtension(false);
+ messageGenerator.GenerateDeclarations();
+ }
+ }
+
+ void GenerateSourceExtensions() {
+ GenerateSourceIncludeExtensions();
+
+ for (auto& messageGenerator: MessageGenerators_) {
+ messageGenerator.GenerateDefinitions();
+ }
+ }
+
+ private:
+ void GenerateSourceIncludeExtensions() {
+ TProtoStringType fileName = SourceFileName(File_);
+ TProtoStringType scope = "includes";
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ OutputDirectory_->OpenForInsert(fileName, scope));
+ io::Printer printer(output.get(), '$');
+ printer.Print("#include <google/protobuf/messagext.h>\n");
+ }
+
+ void GenerateHeaderIncludeExtensions() {
+ TProtoStringType fileName = HeaderFileName(File_);
+ TProtoStringType scope = "includes";
+ std::unique_ptr<io::ZeroCopyOutputStream> output(
+ OutputDirectory_->OpenForInsert(fileName, scope));
+ io::Printer printer(output.get(), '$');
+ printer.Print("#include <google/protobuf/json_util.h>\n");
+ }
+
+ private:
+ const FileDescriptor* File_;
+ OutputDirectory* OutputDirectory_;
+ size_t MessageTypeCount_;
+ std::vector<TMessageExtGenerator> MessageGenerators_;
+ };
+
+ bool TCppStyleGuideExtensionGenerator::Generate(const FileDescriptor* file,
+ const TProtoStringType&,
+ OutputDirectory* outputDirectory,
+ TProtoStringType*) const {
+
+ TFileExtGenerator fileGenerator(file, outputDirectory);
+
+ // Generate header.
+ fileGenerator.GenerateHeaderExtensions();
+
+ // Generate cc file.
+ fileGenerator.GenerateSourceExtensions();
+
+ return true;
+ }
+
+}
+}
+}
+
+int main(int argc, char* argv[]) {
+#ifdef _MSC_VER
+ // Don't print a silly message or stick a modal dialog box in my face,
+ // please.
+ _set_abort_behavior(0, ~0);
+#endif // !_MSC_VER
+
+ NProtobuf::NCompiler::NPlugins::TCppStyleGuideExtensionGenerator generator;
+ return google::protobuf::compiler::PluginMain(argc, argv, &generator);
+}