cpp_styleguide.cpp 41 KB

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