cpp_styleguide.cpp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. #include <google/protobuf/compiler/code_generator.h>
  2. #include <google/protobuf/compiler/cpp/helpers.h>
  3. #include <google/protobuf/descriptor.h>
  4. #include <google/protobuf/descriptor.pb.h>
  5. #include <google/protobuf/io/printer.h>
  6. #include <google/protobuf/io/zero_copy_stream.h>
  7. #include "cpp_styleguide.h"
  8. #include <util/stream/output.h>
  9. namespace NProtobuf {
  10. namespace NCompiler {
  11. namespace NPlugins {
  12. using namespace google::protobuf;
  13. using namespace google::protobuf::compiler;
  14. using namespace google::protobuf::compiler::cpp;
  15. typedef std::map<TProtoStringType, TProtoStringType> TVariables;
  16. bool GenerateYaStyle(const FileDescriptor* fileDescriptor) {
  17. const auto& extension = fileDescriptor->FindExtensionByName("GenerateYaStyle");
  18. return extension;
  19. }
  20. bool GenerateYaStyle(const FieldDescriptor* descriptor) {
  21. const auto& fileDescriptor = descriptor->file();
  22. return GenerateYaStyle(fileDescriptor);
  23. }
  24. void SetCommonFieldVariables(const FieldDescriptor* descriptor, TVariables* variables) {
  25. const auto& name = descriptor->name();
  26. if (GenerateYaStyle(descriptor))
  27. (*variables)["rname"] = UnderscoresToCamelCase(name, true);
  28. else
  29. (*variables)["rname"] = name;
  30. (*variables)["name"] = FieldName(descriptor);
  31. }
  32. TProtoStringType HeaderFileName(const FileDescriptor* file) {
  33. TProtoStringType basename = compiler::StripProto(file->name());
  34. return basename.append(".pb.h");
  35. }
  36. TProtoStringType SourceFileName(const FileDescriptor* file) {
  37. TProtoStringType basename = compiler::StripProto(file->name());
  38. return basename.append(".pb.cc");
  39. }
  40. bool IsLiteRuntimeMessage(const Descriptor* desc) {
  41. return desc->file() != NULL && desc->file()->options().optimize_for() == google::protobuf::FileOptions::LITE_RUNTIME;
  42. }
  43. bool IsAutogeneratedNestedType(const Descriptor* desc) {
  44. return desc->options().map_entry();
  45. }
  46. class TFieldExtGenerator {
  47. public:
  48. TFieldExtGenerator(const FieldDescriptor* field)
  49. : Field_(field)
  50. {
  51. SetCommonFieldVariables(Field_, &Variables_);
  52. }
  53. virtual ~TFieldExtGenerator() {
  54. }
  55. virtual void GenerateAccessorDeclarations(io::Printer* printer) = 0;
  56. virtual void GenerateJSONPrinting(io::Printer* printer) = 0;
  57. protected:
  58. void GenerateRepeatedJSONPrinting(io::Printer* printer, const char* itemPrinter) {
  59. printer->Print("out << '[';\n");
  60. printer->Print("{\n");
  61. printer->Indent();
  62. printer->Print("const char* separator = \"\";\n");
  63. printer->Print(Variables_, "for (size_t _index = 0; _index < $rname$Size(); ++_index) {\n");
  64. printer->Indent();
  65. printer->Print("out << separator;\n");
  66. printer->Print(Variables_, itemPrinter);
  67. printer->Print(";\n");
  68. printer->Print("separator = \",\";\n");
  69. printer->Outdent();
  70. printer->Print("}\n");
  71. printer->Outdent();
  72. printer->Print("}\n");
  73. printer->Print("out << ']';\n");
  74. }
  75. protected:
  76. const FieldDescriptor* Field_;
  77. TVariables Variables_;
  78. };
  79. class TMessageFieldExtGenerator: public TFieldExtGenerator {
  80. public:
  81. TMessageFieldExtGenerator(const FieldDescriptor* field)
  82. : TFieldExtGenerator(field)
  83. {
  84. }
  85. void GenerateAccessorDeclarations(io::Printer* printer) override {
  86. Variables_["type"] = QualifiedClassName(Field_->message_type());
  87. printer->Print(Variables_,
  88. "inline const $type$& Get$rname$() const { return $name$(); }\n"
  89. "inline $type$* Mutable$rname$() { return mutable_$name$(); }\n");
  90. }
  91. void GenerateJSONPrinting(io::Printer* printer) override {
  92. printer->Print(Variables_, "Get$rname$().PrintJSON(out);\n");
  93. }
  94. };
  95. class TMapFieldExtGenerator: public TFieldExtGenerator {
  96. public:
  97. TMapFieldExtGenerator(const FieldDescriptor* field)
  98. : TFieldExtGenerator(field)
  99. , Key_(field->message_type()->FindFieldByName("key"))
  100. , Val_(field->message_type()->FindFieldByName("value"))
  101. {
  102. Variables_["key_cpp"] = PrimitiveTypeName(Key_->cpp_type());
  103. switch (Val_->cpp_type()) {
  104. case FieldDescriptor::CPPTYPE_MESSAGE:
  105. Variables_["val_cpp"] = QualifiedClassName(Val_->message_type());
  106. break;
  107. case FieldDescriptor::CPPTYPE_ENUM:
  108. Variables_["val_cpp"] = ClassName(Val_->enum_type(), true);
  109. break;
  110. default:
  111. Variables_["val_cpp"] = PrimitiveTypeName(Val_->cpp_type());
  112. }
  113. }
  114. void GenerateAccessorDeclarations(io::Printer* printer) {
  115. printer->Print(Variables_,
  116. "inline const ::google::protobuf::Map<$key_cpp$, $val_cpp$>& Get$rname$() const { return $name$(); }\n"
  117. "inline ::google::protobuf::Map<$key_cpp$, $val_cpp$>* Mutable$rname$() { return mutable_$name$(); }\n");
  118. }
  119. void GenerateKeyValuePrinting(io::Printer* printer, const char* scopeName, bool isKey) {
  120. const FieldDescriptor* desc = isKey ? Key_ : Val_;
  121. switch(desc->cpp_type()) {
  122. case FieldDescriptor::CPPTYPE_STRING:
  123. printer->Print(TString::Join("::google::protobuf::io::PrintJSONString(out, ", scopeName , ");\n").data());
  124. break;
  125. case FieldDescriptor::CPPTYPE_ENUM:
  126. printer->Print(TString::Join("out << int(", scopeName, ");\n").data());
  127. break;
  128. case FieldDescriptor::CPPTYPE_MESSAGE:
  129. printer->Print(TString::Join(scopeName, ".PrintJSON(out);\n").data());
  130. break;
  131. default:
  132. if (isKey) {
  133. printer->Print(TString::Join("out << '\"' << ", scopeName, " << '\"';\n").data());
  134. } else {
  135. printer->Print(TString::Join("out << ", scopeName, ";\n").data());
  136. }
  137. }
  138. }
  139. void GenerateJSONPrinting(io::Printer* printer) {
  140. printer->Print(Variables_,
  141. "out << '{';\n"
  142. "const ::google::protobuf::Map<$key_cpp$, $val_cpp$>& map = Get$rname$();\n"
  143. "for (auto it = map.begin(); it != map.end(); ++it) {\n"
  144. );
  145. printer->Indent();
  146. printer->Print("if (it != map.begin()) { out << ','; }\n");
  147. GenerateKeyValuePrinting(printer, "it->first", true);
  148. printer->Print("out << ':';\n");
  149. GenerateKeyValuePrinting(printer, "it->second", false);
  150. printer->Outdent();
  151. printer->Print("}\n");
  152. printer->Print("out << '}';\n");
  153. }
  154. private:
  155. const FieldDescriptor* Key_;
  156. const FieldDescriptor* Val_;
  157. };
  158. class TRepeatedMessageFieldExtGenerator: public TFieldExtGenerator {
  159. public:
  160. TRepeatedMessageFieldExtGenerator(const FieldDescriptor* field)
  161. : TFieldExtGenerator(field)
  162. {
  163. }
  164. void GenerateAccessorDeclarations(io::Printer* printer) override {
  165. Variables_["type"] = QualifiedClassName(Field_->message_type());
  166. printer->Print(Variables_,
  167. "inline const $type$& Get$rname$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(int(_index)); }\n"
  168. "inline $type$* Mutable$rname$(size_t _index) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return mutable_$name$(int(_index)); }\n"
  169. "inline $type$* Add$rname$() { return add_$name$(); }\n"
  170. "inline const $type$& get_idx_$name$(int _index) const { return $name$(_index); }\n"
  171. "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
  172. " get_arr_$name$() const { return $name$(); }\n"
  173. "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
  174. " Get$rname$() const { return $name$(); }\n"
  175. "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
  176. " Mutable$rname$() { return mutable_$name$(); }\n");
  177. }
  178. void GenerateJSONPrinting(io::Printer* printer) override {
  179. GenerateRepeatedJSONPrinting(printer, "Get$rname$(_index).PrintJSON(out)");
  180. }
  181. };
  182. class TStringFieldExtGenerator: public TFieldExtGenerator {
  183. public:
  184. TStringFieldExtGenerator(const FieldDescriptor* field)
  185. : TFieldExtGenerator(field)
  186. {
  187. }
  188. void GenerateAccessorDeclarations(io::Printer* printer) override {
  189. Variables_["pointer_type"] = Field_->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
  190. if (Field_->options().ctype() != FieldOptions::STRING) {
  191. printer->Outdent();
  192. printer->Print(
  193. " private:\n"
  194. " // Hidden due to unknown ctype option.\n");
  195. printer->Indent();
  196. }
  197. printer->Print(Variables_,
  198. "inline const TProtoStringType& Get$rname$() const { return $name$(); }\n"
  199. "inline void Set$rname$(const TProtoStringType& value) { set_$name$(value); }\n"
  200. "inline void Set$rname$(TProtoStringType&& value) { set_$name$(std::move(value)); }\n"
  201. "inline void Set$rname$(const char* value) { set_$name$(value); }\n"
  202. "inline void Set$rname$(const $pointer_type$* value, size_t size) { set_$name$(value, size); }\n"
  203. "inline TProtoStringType* Mutable$rname$() { return mutable_$name$(); }\n");
  204. if (Field_->options().ctype() != FieldOptions::STRING) {
  205. printer->Outdent();
  206. printer->Print(" public:\n");
  207. printer->Indent();
  208. }
  209. }
  210. void GenerateJSONPrinting(io::Printer* printer) override {
  211. printer->Print(Variables_, "::google::protobuf::io::PrintJSONString(out, Get$rname$());\n");
  212. }
  213. };
  214. class TRepeatedStringFieldExtGenerator: public TFieldExtGenerator {
  215. public:
  216. TRepeatedStringFieldExtGenerator(const FieldDescriptor* field)
  217. : TFieldExtGenerator(field)
  218. {
  219. }
  220. void GenerateAccessorDeclarations(io::Printer* printer) override {
  221. Variables_["pointer_type"] = Field_->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
  222. if (Field_->options().ctype() != FieldOptions::STRING) {
  223. printer->Outdent();
  224. printer->Print(
  225. " private:\n"
  226. " // Hidden due to unknown ctype option.\n");
  227. printer->Indent();
  228. }
  229. printer->Print(Variables_,
  230. "inline const TProtoStringType& Get$rname$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(_index); }\n"
  231. "inline TProtoStringType* Mutable$rname$(size_t _index) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return mutable_$name$(_index); }\n"
  232. "inline void Set$rname$(size_t _index, const TProtoStringType& value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
  233. "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"
  234. "inline void Set$rname$(size_t _index, const char* value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
  235. "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"
  236. "inline TProtoStringType* Add$rname$() { return add_$name$(); }\n"
  237. "inline void Add$rname$(const TProtoStringType& value) { add_$name$(value); }\n"
  238. "inline void Add$rname$(TProtoStringType&& value) { add_$name$(std::move(value)); }\n"
  239. "inline void Add$rname$(const char* value) { add_$name$(value); }\n"
  240. "inline void Add$rname$(const $pointer_type$* value, size_t size) { add_$name$(value, size); }\n"
  241. "inline const TProtoStringType& get_idx_$name$(int _index) const { return $name$(_index); }\n"
  242. "inline const ::google::protobuf::RepeatedPtrField<TProtoStringType>& get_arr_$name$() const"
  243. "{ return $name$(); }\n"
  244. "inline const ::google::protobuf::RepeatedPtrField<TProtoStringType>& Get$rname$() const"
  245. "{ return $name$(); }\n"
  246. "inline ::google::protobuf::RepeatedPtrField<TProtoStringType>* Mutable$rname$()"
  247. "{ return mutable_$name$(); }\n");
  248. if (Field_->options().ctype() != FieldOptions::STRING) {
  249. printer->Outdent();
  250. printer->Print(" public:\n");
  251. printer->Indent();
  252. }
  253. }
  254. void GenerateJSONPrinting(io::Printer* printer) override {
  255. GenerateRepeatedJSONPrinting(
  256. printer,
  257. "::google::protobuf::io::PrintJSONString(out, Get$rname$(_index))"
  258. );
  259. }
  260. };
  261. class TEnumFieldExtGenerator: public TFieldExtGenerator {
  262. public:
  263. TEnumFieldExtGenerator(const FieldDescriptor* field)
  264. : TFieldExtGenerator(field)
  265. {
  266. }
  267. void GenerateAccessorDeclarations(io::Printer* printer) override {
  268. Variables_["type"] = ClassName(Field_->enum_type(), true);
  269. printer->Print(Variables_,
  270. "inline $type$ Get$rname$() const { return $name$(); }\n"
  271. "inline void Set$rname$($type$ value) { set_$name$(value); }\n");
  272. }
  273. void GenerateJSONPrinting(io::Printer* printer) override {
  274. printer->Print(Variables_, "out << (int)Get$rname$();\n");
  275. }
  276. };
  277. class TRepeatedEnumFieldExtGenerator: public TFieldExtGenerator {
  278. public:
  279. TRepeatedEnumFieldExtGenerator(const FieldDescriptor* field)
  280. : TFieldExtGenerator(field)
  281. {
  282. }
  283. void GenerateAccessorDeclarations(io::Printer* printer) override {
  284. Variables_["type"] = ClassName(Field_->enum_type(), true);
  285. printer->Print(Variables_,
  286. "inline $type$ Get$rname$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(_index); }\n"
  287. "inline void Set$rname$(size_t _index, $type$ value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
  288. "inline void Add$rname$($type$ value) { add_$name$(value); }\n"
  289. "inline $type$ get_idx_$name$(int _index) const {return $name$(_index); }\n"
  290. "inline const ::google::protobuf::RepeatedField<int>& get_arr_$name$() const { return $name$(); }\n"
  291. "inline const ::google::protobuf::RepeatedField<int>& Get$rname$() const { return $name$(); }\n"
  292. "inline ::google::protobuf::RepeatedField<int>* Mutable$rname$() { return mutable_$name$(); }\n");
  293. }
  294. void GenerateJSONPrinting(io::Printer* printer) override {
  295. GenerateRepeatedJSONPrinting(printer, "out << (int)Get$rname$(_index)");
  296. }
  297. };
  298. class TPrimitiveFieldExtGenerator: public TFieldExtGenerator {
  299. public:
  300. TPrimitiveFieldExtGenerator(const FieldDescriptor* field)
  301. : TFieldExtGenerator(field)
  302. {
  303. }
  304. void GenerateAccessorDeclarations(io::Printer* printer) override {
  305. Variables_["type"] = PrimitiveTypeName(Field_->cpp_type());
  306. printer->Print(Variables_,
  307. "inline $type$ Get$rname$() const { return $name$();}\n"
  308. "inline void Set$rname$($type$ value) { set_$name$(value); }\n");
  309. }
  310. void GenerateJSONPrinting(io::Printer* printer) override {
  311. printer->Print(Variables_, "out << Get$rname$();\n");
  312. }
  313. };
  314. class TRepeatedPrimitiveFieldExtGenerator: public TFieldExtGenerator {
  315. public:
  316. TRepeatedPrimitiveFieldExtGenerator(const FieldDescriptor* field)
  317. : TFieldExtGenerator(field)
  318. {
  319. }
  320. void GenerateAccessorDeclarations(io::Printer* printer) override {
  321. Variables_["type"] = PrimitiveTypeName(Field_->cpp_type());
  322. printer->Print(Variables_,
  323. "inline $type$ Get$rname$(size_t _index) const {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); return $name$(_index); }\n"
  324. "inline void Set$rname$(size_t _index, $type$ value) {Y_ASSERT(_index < static_cast<size_t>(::Max<int>())); set_$name$(_index, value); }\n"
  325. "inline void Add$rname$($type$ value) { add_$name$(value); }\n"
  326. "inline $type$ get_idx_$name$(int _index) const { return $name$(_index); }\n"
  327. "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
  328. " get_arr_$name$() const { return $name$(); }\n"
  329. "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
  330. " Get$rname$() const { return $name$(); }\n"
  331. "inline ::google::protobuf::RepeatedField< $type$ >*\n"
  332. " Mutable$rname$() { return mutable_$name$(); }\n");
  333. }
  334. void GenerateJSONPrinting(io::Printer* printer) override {
  335. GenerateRepeatedJSONPrinting(printer, "out << Get$rname$(_index)");
  336. }
  337. };
  338. class TBoolFieldExtGenerator: public TPrimitiveFieldExtGenerator {
  339. public:
  340. TBoolFieldExtGenerator(const FieldDescriptor* field)
  341. : TPrimitiveFieldExtGenerator(field)
  342. {
  343. }
  344. void GenerateJSONPrinting(io::Printer* printer) override {
  345. printer->Print(Variables_, "out << (Get$rname$() ? \"true\" : \"false\");\n");
  346. }
  347. };
  348. class TRepeatedBoolFieldExtGenerator: public TRepeatedPrimitiveFieldExtGenerator {
  349. public:
  350. TRepeatedBoolFieldExtGenerator(const FieldDescriptor* field)
  351. : TRepeatedPrimitiveFieldExtGenerator(field)
  352. {
  353. }
  354. void GenerateJSONPrinting(io::Printer* printer) override {
  355. GenerateRepeatedJSONPrinting(printer, "out << (Get$rname$(_index) ? \"true\" : \"false\")");
  356. }
  357. };
  358. class TFloatFieldExtGenerator: public TPrimitiveFieldExtGenerator {
  359. public:
  360. TFloatFieldExtGenerator(const FieldDescriptor* field)
  361. : TPrimitiveFieldExtGenerator(field)
  362. {
  363. }
  364. void GenerateJSONPrinting(io::Printer* printer) override {
  365. printer->Print(Variables_, "out << double(Get$rname$());\n");
  366. }
  367. };
  368. class TRepeatedFloatFieldExtGenerator: public TRepeatedPrimitiveFieldExtGenerator {
  369. public:
  370. TRepeatedFloatFieldExtGenerator(const FieldDescriptor* field)
  371. : TRepeatedPrimitiveFieldExtGenerator(field)
  372. {
  373. }
  374. void GenerateJSONPrinting(io::Printer* printer) override {
  375. GenerateRepeatedJSONPrinting(printer, "out << double(Get$rname$(_index))");
  376. }
  377. };
  378. // borrowed mostly from protobuf/compiler/cpp/cpp_extension.cc
  379. class TExtensionGenerator {
  380. public:
  381. TExtensionGenerator(const FieldDescriptor* descriptor)
  382. : Descriptor_(descriptor)
  383. {
  384. if (Descriptor_->is_repeated()) {
  385. type_traits_ = "Repeated";
  386. }
  387. TProtoStringType clsName;
  388. switch (Descriptor_->cpp_type()) {
  389. case FieldDescriptor::CPPTYPE_ENUM:
  390. type_traits_.append("EnumTypeTraits< ");
  391. clsName = ClassName(Descriptor_->enum_type(), true);
  392. type_traits_.append(clsName);
  393. type_traits_.append(", ");
  394. type_traits_.append(clsName);
  395. type_traits_.append("_IsValid>");
  396. break;
  397. case FieldDescriptor::CPPTYPE_STRING:
  398. type_traits_.append("StringTypeTraits");
  399. break;
  400. case FieldDescriptor::CPPTYPE_MESSAGE:
  401. type_traits_.append("MessageTypeTraits< ");
  402. type_traits_.append(ClassName(Descriptor_->message_type(), true));
  403. type_traits_.append(" >");
  404. break;
  405. default:
  406. type_traits_.append("PrimitiveTypeTraits< ");
  407. type_traits_.append(PrimitiveTypeName(Descriptor_->cpp_type()));
  408. type_traits_.append(" >");
  409. break;
  410. }
  411. }
  412. void GenerateDeclaration(io::Printer* printer) const
  413. {
  414. TVariables vars;
  415. vars["extendee" ] = ClassName(Descriptor_->containing_type(), true);
  416. vars["type_traits" ] = type_traits_;
  417. vars["name" ] = Descriptor_->name();
  418. vars["field_type" ] = std::to_string(static_cast<int>(Descriptor_->type()));
  419. vars["packed" ] = Descriptor_->options().packed() ? "true" : "false";
  420. printer->Print(vars,
  421. "typedef ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
  422. " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
  423. " Td$name$;\n"
  424. );
  425. }
  426. private:
  427. const FieldDescriptor* Descriptor_;
  428. TProtoStringType type_traits_;
  429. };
  430. class TOneofGenerator {
  431. public:
  432. TOneofGenerator(const OneofDescriptor* Descriptor_)
  433. : Descriptor_(Descriptor_)
  434. {
  435. Variables_["camel_oneof_name"] = UnderscoresToCamelCase(Descriptor_->name(), true);
  436. Variables_["rname"] = Descriptor_->name();
  437. }
  438. void GenerateDeclarations(io::Printer* printer) const {
  439. printer->Print(Variables_, "$camel_oneof_name$Case Get$rname$Case() const { return $rname$_case(); }\n");
  440. printer->Print(Variables_, "void Clear$rname$() { clear_$rname$(); }\n");
  441. if (Descriptor_->name() != UnderscoresToCamelCase(Descriptor_->name(), true)) {
  442. printer->Print(Variables_, "$camel_oneof_name$Case Get$camel_oneof_name$Case() const { return $rname$_case(); }\n");
  443. printer->Print(Variables_, "void Clear$camel_oneof_name$() { clear_$rname$(); }\n");
  444. }
  445. }
  446. private:
  447. const OneofDescriptor* Descriptor_;
  448. TVariables Variables_;
  449. };
  450. TFieldExtGenerator* MakeGenerator(const FieldDescriptor* field) {
  451. if (field->is_repeated()) {
  452. switch (field->cpp_type()) {
  453. case FieldDescriptor::CPPTYPE_MESSAGE:
  454. if (field->is_map()) {
  455. return new TMapFieldExtGenerator(field);
  456. }
  457. return new TRepeatedMessageFieldExtGenerator(field);
  458. case FieldDescriptor::CPPTYPE_BOOL:
  459. return new TRepeatedBoolFieldExtGenerator(field);
  460. case FieldDescriptor::CPPTYPE_FLOAT:
  461. return new TRepeatedFloatFieldExtGenerator(field);
  462. case FieldDescriptor::CPPTYPE_STRING:
  463. switch (field->options().ctype()) {
  464. default: // RepeatedStringFieldExtGenerator handles unknown ctypes.
  465. case FieldOptions::STRING:
  466. return new TRepeatedStringFieldExtGenerator(field);
  467. }
  468. case FieldDescriptor::CPPTYPE_ENUM:
  469. return new TRepeatedEnumFieldExtGenerator(field);
  470. default:
  471. return new TRepeatedPrimitiveFieldExtGenerator(field);
  472. }
  473. } else {
  474. switch (field->cpp_type()) {
  475. case FieldDescriptor::CPPTYPE_MESSAGE:
  476. return new TMessageFieldExtGenerator(field);
  477. case FieldDescriptor::CPPTYPE_BOOL:
  478. return new TBoolFieldExtGenerator(field);
  479. case FieldDescriptor::CPPTYPE_FLOAT:
  480. return new TFloatFieldExtGenerator(field);
  481. case FieldDescriptor::CPPTYPE_STRING:
  482. switch (field->options().ctype()) {
  483. default: // StringFieldGenerator handles unknown ctypes.
  484. case FieldOptions::STRING:
  485. return new TStringFieldExtGenerator(field);
  486. }
  487. case FieldDescriptor::CPPTYPE_ENUM:
  488. return new TEnumFieldExtGenerator(field);
  489. default:
  490. return new TPrimitiveFieldExtGenerator(field);
  491. }
  492. }
  493. }
  494. class TMessageExtGenerator {
  495. public:
  496. TMessageExtGenerator(const Descriptor* descriptor, OutputDirectory* outputDirectory)
  497. : Descriptor_(descriptor)
  498. , Classname_(ClassName(descriptor, false))
  499. , OutputDirectory_(outputDirectory)
  500. {
  501. for (int i = 0; i < descriptor->nested_type_count(); i++) {
  502. if (!IsAutogeneratedNestedType(descriptor->nested_type(i))) {
  503. NestedGenerators_.emplace_back(descriptor->nested_type(i), OutputDirectory_);
  504. }
  505. }
  506. FieldGenerators_.reserve(descriptor->field_count());
  507. for (int i = 0; i < descriptor->field_count(); i++) {
  508. FieldGenerators_.emplace_back(MakeGenerator(descriptor->field(i)));
  509. }
  510. ExtensionGenerators_.reserve(descriptor->extension_count());
  511. for (int i = 0; i < descriptor->extension_count(); i++) {
  512. ExtensionGenerators_.emplace_back(descriptor->extension(i));
  513. }
  514. OneofGenerators_.reserve(descriptor->real_oneof_decl_count());
  515. for (int i = 0; i < descriptor->real_oneof_decl_count(); i++) {
  516. OneofGenerators_.emplace_back(descriptor->oneof_decl(i));
  517. }
  518. }
  519. void GenerateClassDefinitionExtension() {
  520. GenerateSaveLoadImplementation();
  521. GenerateJSONImplementation();
  522. for (auto& nestedGenerator: NestedGenerators_) {
  523. nestedGenerator.GenerateClassDefinitionExtension();
  524. }
  525. }
  526. void GenerateDebugOutputExtension() {
  527. GenerateDebugOutput();
  528. for (auto& nestedGenerator: NestedGenerators_) {
  529. nestedGenerator.GenerateDebugOutputExtension();
  530. }
  531. }
  532. void GenerateTypedefOutputExtension(bool nested) {
  533. GenerateTypedefOutput(nested);
  534. for (auto& nestedGenerator: NestedGenerators_) {
  535. nestedGenerator.GenerateTypedefOutputExtension(true);
  536. }
  537. }
  538. void GenerateClassExtension() {
  539. GenerateDebugStringImplementation();
  540. for (auto& nestedGenerator: NestedGenerators_) {
  541. nestedGenerator.GenerateClassExtension();
  542. }
  543. }
  544. void GenerateDeclarations() {
  545. GenerateFieldAccessorDeclarations();
  546. for (auto& nestedGenerator: NestedGenerators_) {
  547. nestedGenerator.GenerateDeclarations();
  548. }
  549. }
  550. void GenerateDefinitions() {
  551. GenerateClassExtension();
  552. GenerateDebugOutputExtension();
  553. GenerateClassDefinitionExtension();
  554. }
  555. private:
  556. void GenerateFieldAccessorDeclarations() {
  557. TProtoStringType fileName = HeaderFileName(Descriptor_->file());
  558. TProtoStringType scope = "class_scope:" + Descriptor_->full_name();
  559. std::unique_ptr<io::ZeroCopyOutputStream> output(
  560. OutputDirectory_->OpenForInsert(fileName, scope));
  561. io::Printer printer(output.get(), '$');
  562. printer.Print("// Yandex cpp-styleguide extension\n");
  563. for (int i = 0; i < Descriptor_->field_count(); i++) {
  564. const FieldDescriptor* field = Descriptor_->field(i);
  565. TVariables vars;
  566. SetCommonFieldVariables(field, &vars);
  567. if (field->is_repeated()) {
  568. printer.Print(vars,
  569. "inline size_t $rname$Size() const { return (size_t)$name$_size(); }\n");
  570. } else if (field->has_presence()) {
  571. printer.Print(vars,
  572. "inline bool Has$rname$() const { return has_$name$(); }\n");
  573. }
  574. printer.Print(vars, "inline void Clear$rname$() { clear_$name$(); }\n");
  575. // Generate type-specific accessor declarations.
  576. FieldGenerators_[i]->GenerateAccessorDeclarations(&printer);
  577. printer.Print("\n");
  578. }
  579. for (auto& extensionGenerator: ExtensionGenerators_) {
  580. extensionGenerator.GenerateDeclaration(&printer);
  581. }
  582. for (auto& oneofGenerator: OneofGenerators_) {
  583. oneofGenerator.GenerateDeclarations(&printer);
  584. }
  585. TVariables vars;
  586. vars["class"] = ClassName(Descriptor_, false);
  587. if (!IsLiteRuntimeMessage(Descriptor_)) {
  588. printer.Print("TProtoStringType ShortUtf8DebugString() const;\n");
  589. printer.Print("void PrintJSON(IOutputStream&) const override;\n");
  590. printer.Print(vars, "::google::protobuf::io::TAsJSON<$class$> AsJSON() const {\n");
  591. printer.Print(vars, " return ::google::protobuf::io::TAsJSON<$class$>(*this);\n");
  592. printer.Print("}\n");
  593. printer.Print("void Save(IOutputStream* output) const;\n");
  594. printer.Print("void Load(IInputStream* input);\n");
  595. }
  596. printer.Print("// End of Yandex-specific extension\n");
  597. }
  598. void GenerateSaveLoadImplementation() {
  599. TProtoStringType fileName = SourceFileName(Descriptor_->file());
  600. TProtoStringType scope = "namespace_scope";
  601. std::unique_ptr<io::ZeroCopyOutputStream> output(
  602. OutputDirectory_->OpenForInsert(fileName, scope));
  603. io::Printer printer(output.get(), '$');
  604. TVariables vars;
  605. vars["class"] = Classname_;
  606. if (!IsLiteRuntimeMessage(Descriptor_)) {
  607. printer.Print("// Yandex-specific extension\n");
  608. printer.Print(vars, "void $class$::Save(IOutputStream* output) const {\n");
  609. printer.Print(" ::Save(output, static_cast<const ::google::protobuf::Message&>(*this));\n");
  610. printer.Print("}\n");
  611. printer.Print(vars, "void $class$::Load(IInputStream* input) {\n");
  612. printer.Print(" ::Load(input, static_cast<::google::protobuf::Message&>(*this));\n");
  613. printer.Print("}\n");
  614. printer.Print("// End of Yandex-specific extension\n");
  615. }
  616. }
  617. void GenerateDebugStringImplementation() {
  618. TProtoStringType fileName = SourceFileName(Descriptor_->file());
  619. TProtoStringType scope = "namespace_scope";
  620. std::unique_ptr<io::ZeroCopyOutputStream> output(
  621. OutputDirectory_->OpenForInsert(fileName, scope));
  622. io::Printer printer(output.get(), '$');
  623. TVariables vars;
  624. vars["class"] = Classname_;
  625. if (!IsLiteRuntimeMessage(Descriptor_)) {
  626. printer.Print("// Yandex-specific extension\n");
  627. printer.Print(vars, "TProtoStringType $class$::ShortUtf8DebugString() const {\n");
  628. printer.Print(" return ::ShortUtf8DebugString(*this);\n");
  629. printer.Print("}\n");
  630. printer.Print("// End of Yandex-specific extension\n");
  631. }
  632. }
  633. void GenerateJSONImplementation() {
  634. if (IsLiteRuntimeMessage(Descriptor_)) {
  635. return;
  636. }
  637. TProtoStringType fileName = SourceFileName(Descriptor_->file());
  638. TProtoStringType scope = "namespace_scope";
  639. std::unique_ptr<io::ZeroCopyOutputStream> output(
  640. OutputDirectory_->OpenForInsert(fileName, scope));
  641. io::Printer printer(output.get(), '$');
  642. printer.Print("// Yandex JSON extension\n");
  643. TVariables vars;
  644. vars["class"] = ClassName(Descriptor_, true);
  645. printer.Print(vars, "inline void $class$::PrintJSON(IOutputStream& out) const {\n");
  646. printer.Indent();
  647. printer.Print("out << '{';\n");
  648. if (Descriptor_->field_count() > 0) {
  649. printer.Print("const char* sep = \"\";\n");
  650. }
  651. for (int i = 0; i < Descriptor_->field_count(); i++) {
  652. const FieldDescriptor* field = Descriptor_->field(i);
  653. TVariables vars;
  654. SetCommonFieldVariables(field, &vars);
  655. if (field->is_repeated()) {
  656. // map or repeated field in both proto3 and proto2 syntax
  657. printer.Print(vars, "if ($rname$Size() > 0) {\n");
  658. } else if (field->has_presence()) {
  659. // any optional or required field in proto2 syntax
  660. // message-field or any oneof field in proto3 syntax
  661. printer.Print(vars, "if (Has$rname$()) {\n");
  662. } else {
  663. // string, enum or primitive field in proto3 syntax
  664. printer.Print(vars, "if (Get$rname$()) {\n");
  665. }
  666. printer.Indent();
  667. printer.Print("out << sep;\n");
  668. printer.Print(vars, "out << \"\\\"$rname$\\\":\";\n");
  669. FieldGenerators_[i]->GenerateJSONPrinting(&printer);
  670. printer.Print(vars, "sep = \",\";\n");
  671. printer.Outdent();
  672. printer.Print("}\n");
  673. }
  674. printer.Print("out << '}';\n");
  675. printer.Outdent();
  676. printer.Print("}\n");
  677. printer.Print("// End of Yandex JSON extension\n");
  678. }
  679. void GenerateDebugOutput() {
  680. TProtoStringType fileName = SourceFileName(Descriptor_->file());
  681. TProtoStringType scope = "global_scope";
  682. std::unique_ptr<io::ZeroCopyOutputStream> output(
  683. OutputDirectory_->OpenForInsert(fileName, scope));
  684. io::Printer printer(output.get(), '$');
  685. if (!IsLiteRuntimeMessage(Descriptor_)) {
  686. printer.Print("// Yandex debug output extension\n");
  687. TVariables vars;
  688. vars["class"] = ClassName(Descriptor_, true);
  689. printer.Print("template<>\n");
  690. printer.Print(vars, "void Out< $class$>(IOutputStream& out, const $class$& msg) {\n");
  691. printer.Print(" out << \"{ \" << msg.ShortUtf8DebugString() << \" }\";\n");
  692. printer.Print("}\n");
  693. printer.Print("// End of Yandex debug output extension\n");
  694. }
  695. }
  696. void GenerateTypedefOutput(bool nested) {
  697. if (!GenerateYaStyle(Descriptor_->file()))
  698. return;
  699. TProtoStringType fileName = HeaderFileName(Descriptor_->file());
  700. TProtoStringType scope = nested ? "class_scope:" + Descriptor_->full_name().substr(0,
  701. Descriptor_->full_name().size() - Descriptor_->name().size() - 1)
  702. : "namespace_scope";
  703. std::unique_ptr<io::ZeroCopyOutputStream> output(
  704. OutputDirectory_->OpenForInsert(fileName, scope));
  705. io::Printer printer(output.get(), '$');
  706. TString name = Descriptor_->name();
  707. bool isOk = name.size() >= 2 && name[0] == 'T' && name[1] >= 'A' && name[1] <= 'Z';
  708. if (!isOk) {
  709. printer.Print("// Yandex typedef extension\n");
  710. TVariables vars;
  711. vars["class"] = name;
  712. vars["base_class"] = ClassName(Descriptor_, true);
  713. printer.Print(vars, "typedef $base_class$ T$class$;\n");
  714. printer.Print("// End of Yandex typedef extension\n");
  715. }
  716. }
  717. private:
  718. const Descriptor* Descriptor_;
  719. TProtoStringType Classname_;
  720. OutputDirectory* OutputDirectory_;
  721. std::vector<std::unique_ptr<TFieldExtGenerator>> FieldGenerators_;
  722. std::vector<TMessageExtGenerator> NestedGenerators_;
  723. std::vector<TExtensionGenerator> ExtensionGenerators_;
  724. std::vector<TOneofGenerator> OneofGenerators_;
  725. };
  726. class TFileExtGenerator {
  727. public:
  728. TFileExtGenerator(const FileDescriptor* file, OutputDirectory* output_directory)
  729. : File_(file)
  730. , OutputDirectory_(output_directory)
  731. {
  732. MessageGenerators_.reserve(file->message_type_count());
  733. for (int i = 0; i < file->message_type_count(); i++) {
  734. MessageGenerators_.emplace_back(file->message_type(i), OutputDirectory_);
  735. }
  736. }
  737. void GenerateHeaderExtensions() {
  738. GenerateHeaderIncludeExtensions();
  739. for (auto& messageGenerator: MessageGenerators_) {
  740. messageGenerator.GenerateTypedefOutputExtension(false);
  741. messageGenerator.GenerateDeclarations();
  742. }
  743. }
  744. void GenerateSourceExtensions() {
  745. GenerateSourceIncludeExtensions();
  746. for (auto& messageGenerator: MessageGenerators_) {
  747. messageGenerator.GenerateDefinitions();
  748. }
  749. }
  750. private:
  751. void GenerateSourceIncludeExtensions() {
  752. TProtoStringType fileName = SourceFileName(File_);
  753. TProtoStringType scope = "includes";
  754. std::unique_ptr<io::ZeroCopyOutputStream> output(
  755. OutputDirectory_->OpenForInsert(fileName, scope));
  756. io::Printer printer(output.get(), '$');
  757. printer.Print("#include <google/protobuf/messagext.h>\n");
  758. }
  759. void GenerateHeaderIncludeExtensions() {
  760. TProtoStringType fileName = HeaderFileName(File_);
  761. TProtoStringType scope = "includes";
  762. std::unique_ptr<io::ZeroCopyOutputStream> output(
  763. OutputDirectory_->OpenForInsert(fileName, scope));
  764. io::Printer printer(output.get(), '$');
  765. printer.Print("#include <google/protobuf/json_util.h>\n");
  766. }
  767. private:
  768. const FileDescriptor* File_;
  769. OutputDirectory* OutputDirectory_;
  770. size_t MessageTypeCount_;
  771. std::vector<TMessageExtGenerator> MessageGenerators_;
  772. };
  773. bool TCppStyleGuideExtensionGenerator::Generate(const FileDescriptor* file,
  774. const TProtoStringType&,
  775. OutputDirectory* outputDirectory,
  776. TProtoStringType*) const {
  777. TFileExtGenerator fileGenerator(file, outputDirectory);
  778. // Generate header.
  779. fileGenerator.GenerateHeaderExtensions();
  780. // Generate cc file.
  781. fileGenerator.GenerateSourceExtensions();
  782. return true;
  783. }
  784. }
  785. }
  786. }
  787. int main(int argc, char* argv[]) {
  788. #ifdef _MSC_VER
  789. // Don't print a silly message or stick a modal dialog box in my face,
  790. // please.
  791. _set_abort_behavior(0, ~0);
  792. #endif // !_MSC_VER
  793. NProtobuf::NCompiler::NPlugins::TCppStyleGuideExtensionGenerator generator;
  794. return google::protobuf::compiler::PluginMain(argc, argv, &generator);
  795. }