csharp_message.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #include <sstream>
  31. #include <algorithm>
  32. #include <map>
  33. #include <google/protobuf/compiler/code_generator.h>
  34. #include <google/protobuf/compiler/plugin.h>
  35. #include <google/protobuf/descriptor.h>
  36. #include <google/protobuf/descriptor.pb.h>
  37. #include <google/protobuf/io/printer.h>
  38. #include <google/protobuf/io/zero_copy_stream.h>
  39. #include <google/protobuf/stubs/strutil.h>
  40. #include <google/protobuf/wire_format.h>
  41. #include <google/protobuf/wire_format_lite.h>
  42. #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
  43. #include <google/protobuf/compiler/csharp/csharp_enum.h>
  44. #include <google/protobuf/compiler/csharp/csharp_field_base.h>
  45. #include <google/protobuf/compiler/csharp/csharp_helpers.h>
  46. #include <google/protobuf/compiler/csharp/csharp_message.h>
  47. #include <google/protobuf/compiler/csharp/csharp_names.h>
  48. using google::protobuf::internal::scoped_ptr;
  49. namespace google {
  50. namespace protobuf {
  51. namespace compiler {
  52. namespace csharp {
  53. bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) {
  54. return d1->number() < d2->number();
  55. }
  56. MessageGenerator::MessageGenerator(const Descriptor* descriptor,
  57. const Options* options)
  58. : SourceGeneratorBase(descriptor->file(), options),
  59. descriptor_(descriptor) {
  60. // sorted field names
  61. for (int i = 0; i < descriptor_->field_count(); i++) {
  62. field_names_.push_back(descriptor_->field(i)->name());
  63. }
  64. std::sort(field_names_.begin(), field_names_.end());
  65. // fields by number
  66. for (int i = 0; i < descriptor_->field_count(); i++) {
  67. fields_by_number_.push_back(descriptor_->field(i));
  68. }
  69. std::sort(fields_by_number_.begin(), fields_by_number_.end(),
  70. CompareFieldNumbers);
  71. }
  72. MessageGenerator::~MessageGenerator() {
  73. }
  74. std::string MessageGenerator::class_name() {
  75. return descriptor_->name();
  76. }
  77. std::string MessageGenerator::full_class_name() {
  78. return GetClassName(descriptor_);
  79. }
  80. const std::vector<std::string>& MessageGenerator::field_names() {
  81. return field_names_;
  82. }
  83. const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
  84. return fields_by_number_;
  85. }
  86. void MessageGenerator::AddDeprecatedFlag(io::Printer* printer) {
  87. if (descriptor_->options().deprecated()) {
  88. printer->Print("[global::System.ObsoleteAttribute]\n");
  89. }
  90. }
  91. void MessageGenerator::Generate(io::Printer* printer) {
  92. map<string, string> vars;
  93. vars["class_name"] = class_name();
  94. vars["access_level"] = class_access_level();
  95. WriteMessageDocComment(printer, descriptor_);
  96. AddDeprecatedFlag(printer);
  97. printer->Print(
  98. vars,
  99. "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n");
  100. printer->Indent();
  101. // All static fields and properties
  102. printer->Print(
  103. vars,
  104. "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n");
  105. WriteGeneratedCodeAttributes(printer);
  106. printer->Print(
  107. vars,
  108. "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n");
  109. // Access the message descriptor via the relevant file descriptor or containing message descriptor.
  110. if (!descriptor_->containing_type()) {
  111. vars["descriptor_accessor"] = GetReflectionClassName(descriptor_->file())
  112. + ".Descriptor.MessageTypes[" + SimpleItoa(descriptor_->index()) + "]";
  113. } else {
  114. vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
  115. + ".Descriptor.NestedTypes[" + SimpleItoa(descriptor_->index()) + "]";
  116. }
  117. WriteGeneratedCodeAttributes(printer);
  118. printer->Print(
  119. vars,
  120. "public static pbr::MessageDescriptor Descriptor {\n"
  121. " get { return $descriptor_accessor$; }\n"
  122. "}\n"
  123. "\n");
  124. WriteGeneratedCodeAttributes(printer);
  125. printer->Print(
  126. vars,
  127. "pbr::MessageDescriptor pb::IMessage.Descriptor {\n"
  128. " get { return Descriptor; }\n"
  129. "}\n"
  130. "\n");
  131. // Parameterless constructor and partial OnConstruction method.
  132. WriteGeneratedCodeAttributes(printer);
  133. printer->Print(
  134. vars,
  135. "public $class_name$() {\n"
  136. " OnConstruction();\n"
  137. "}\n\n"
  138. "partial void OnConstruction();\n\n");
  139. GenerateCloningCode(printer);
  140. GenerateFreezingCode(printer);
  141. // Fields/properties
  142. for (int i = 0; i < descriptor_->field_count(); i++) {
  143. const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
  144. // Rats: we lose the debug comment here :(
  145. printer->Print(
  146. "/// <summary>Field number for the \"$field_name$\" field.</summary>\n"
  147. "public const int $field_constant_name$ = $index$;\n",
  148. "field_name", fieldDescriptor->name(),
  149. "field_constant_name", GetFieldConstantName(fieldDescriptor),
  150. "index", SimpleItoa(fieldDescriptor->number()));
  151. scoped_ptr<FieldGeneratorBase> generator(
  152. CreateFieldGeneratorInternal(fieldDescriptor));
  153. generator->GenerateMembers(printer);
  154. printer->Print("\n");
  155. }
  156. // oneof properties
  157. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
  158. vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
  159. vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
  160. vars["original_name"] = descriptor_->oneof_decl(i)->name();
  161. printer->Print(
  162. vars,
  163. "private object $name$_;\n"
  164. "/// <summary>Enum of possible cases for the \"$original_name$\" oneof.</summary>\n"
  165. "public enum $property_name$OneofCase {\n");
  166. printer->Indent();
  167. printer->Print("None = 0,\n");
  168. for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
  169. const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
  170. printer->Print("$field_property_name$ = $index$,\n",
  171. "field_property_name", GetPropertyName(field),
  172. "index", SimpleItoa(field->number()));
  173. }
  174. printer->Outdent();
  175. printer->Print("}\n");
  176. // TODO: Should we put the oneof .proto comments here?
  177. // It's unclear exactly where they should go.
  178. printer->Print(
  179. vars,
  180. "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n");
  181. WriteGeneratedCodeAttributes(printer);
  182. printer->Print(
  183. vars,
  184. "public $property_name$OneofCase $property_name$Case {\n"
  185. " get { return $name$Case_; }\n"
  186. "}\n\n");
  187. WriteGeneratedCodeAttributes(printer);
  188. printer->Print(
  189. vars,
  190. "public void Clear$property_name$() {\n"
  191. " $name$Case_ = $property_name$OneofCase.None;\n"
  192. " $name$_ = null;\n"
  193. "}\n\n");
  194. }
  195. // Standard methods
  196. GenerateFrameworkMethods(printer);
  197. GenerateMessageSerializationMethods(printer);
  198. GenerateMergingMethods(printer);
  199. // Nested messages and enums
  200. if (HasNestedGeneratedTypes()) {
  201. printer->Print(
  202. vars,
  203. "#region Nested types\n"
  204. "/// <summary>Container for nested types declared in the $class_name$ message type.</summary>\n");
  205. WriteGeneratedCodeAttributes(printer);
  206. printer->Print("public static partial class Types {\n");
  207. printer->Indent();
  208. for (int i = 0; i < descriptor_->enum_type_count(); i++) {
  209. EnumGenerator enumGenerator(descriptor_->enum_type(i), this->options());
  210. enumGenerator.Generate(printer);
  211. }
  212. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  213. // Don't generate nested types for maps...
  214. if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
  215. MessageGenerator messageGenerator(
  216. descriptor_->nested_type(i), this->options());
  217. messageGenerator.Generate(printer);
  218. }
  219. }
  220. printer->Outdent();
  221. printer->Print("}\n"
  222. "#endregion\n"
  223. "\n");
  224. }
  225. printer->Outdent();
  226. printer->Print("}\n");
  227. printer->Print("\n");
  228. }
  229. // Helper to work out whether we need to generate a class to hold nested types/enums.
  230. // Only tricky because we don't want to generate map entry types.
  231. bool MessageGenerator::HasNestedGeneratedTypes()
  232. {
  233. if (descriptor_->enum_type_count() > 0) {
  234. return true;
  235. }
  236. for (int i = 0; i < descriptor_->nested_type_count(); i++) {
  237. if (!IsMapEntryMessage(descriptor_->nested_type(i))) {
  238. return true;
  239. }
  240. }
  241. return false;
  242. }
  243. void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
  244. map<string, string> vars;
  245. WriteGeneratedCodeAttributes(printer);
  246. vars["class_name"] = class_name();
  247. printer->Print(
  248. vars,
  249. "public $class_name$($class_name$ other) : this() {\n");
  250. printer->Indent();
  251. // Clone non-oneof fields first
  252. for (int i = 0; i < descriptor_->field_count(); i++) {
  253. if (!descriptor_->field(i)->containing_oneof()) {
  254. scoped_ptr<FieldGeneratorBase> generator(
  255. CreateFieldGeneratorInternal(descriptor_->field(i)));
  256. generator->GenerateCloningCode(printer);
  257. }
  258. }
  259. // Clone just the right field for each oneof
  260. for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
  261. vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
  262. vars["property_name"] = UnderscoresToCamelCase(
  263. descriptor_->oneof_decl(i)->name(), true);
  264. printer->Print(vars, "switch (other.$property_name$Case) {\n");
  265. printer->Indent();
  266. for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
  267. const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
  268. scoped_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
  269. vars["field_property_name"] = GetPropertyName(field);
  270. printer->Print(
  271. vars,
  272. "case $property_name$OneofCase.$field_property_name$:\n");
  273. printer->Indent();
  274. generator->GenerateCloningCode(printer);
  275. printer->Print("break;\n");
  276. printer->Outdent();
  277. }
  278. printer->Outdent();
  279. printer->Print("}\n\n");
  280. }
  281. printer->Outdent();
  282. printer->Print("}\n\n");
  283. WriteGeneratedCodeAttributes(printer);
  284. printer->Print(
  285. vars,
  286. "public $class_name$ Clone() {\n"
  287. " return new $class_name$(this);\n"
  288. "}\n\n");
  289. }
  290. void MessageGenerator::GenerateFreezingCode(io::Printer* printer) {
  291. }
  292. void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
  293. map<string, string> vars;
  294. vars["class_name"] = class_name();
  295. // Equality
  296. WriteGeneratedCodeAttributes(printer);
  297. printer->Print(
  298. vars,
  299. "public override bool Equals(object other) {\n"
  300. " return Equals(other as $class_name$);\n"
  301. "}\n\n");
  302. WriteGeneratedCodeAttributes(printer);
  303. printer->Print(
  304. vars,
  305. "public bool Equals($class_name$ other) {\n"
  306. " if (ReferenceEquals(other, null)) {\n"
  307. " return false;\n"
  308. " }\n"
  309. " if (ReferenceEquals(other, this)) {\n"
  310. " return true;\n"
  311. " }\n");
  312. printer->Indent();
  313. for (int i = 0; i < descriptor_->field_count(); i++) {
  314. scoped_ptr<FieldGeneratorBase> generator(
  315. CreateFieldGeneratorInternal(descriptor_->field(i)));
  316. generator->WriteEquals(printer);
  317. }
  318. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
  319. printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n",
  320. "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
  321. }
  322. printer->Outdent();
  323. printer->Print(
  324. " return true;\n"
  325. "}\n\n");
  326. // GetHashCode
  327. // Start with a non-zero value to easily distinguish between null and "empty" messages.
  328. WriteGeneratedCodeAttributes(printer);
  329. printer->Print(
  330. "public override int GetHashCode() {\n"
  331. " int hash = 1;\n");
  332. printer->Indent();
  333. for (int i = 0; i < descriptor_->field_count(); i++) {
  334. scoped_ptr<FieldGeneratorBase> generator(
  335. CreateFieldGeneratorInternal(descriptor_->field(i)));
  336. generator->WriteHash(printer);
  337. }
  338. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
  339. printer->Print("hash ^= (int) $name$Case_;\n",
  340. "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false));
  341. }
  342. printer->Print("return hash;\n");
  343. printer->Outdent();
  344. printer->Print("}\n\n");
  345. WriteGeneratedCodeAttributes(printer);
  346. printer->Print(
  347. "public override string ToString() {\n"
  348. " return pb::JsonFormatter.ToDiagnosticString(this);\n"
  349. "}\n\n");
  350. }
  351. void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) {
  352. WriteGeneratedCodeAttributes(printer);
  353. printer->Print(
  354. "public void WriteTo(pb::CodedOutputStream output) {\n");
  355. printer->Indent();
  356. // Serialize all the fields
  357. for (int i = 0; i < fields_by_number().size(); i++) {
  358. scoped_ptr<FieldGeneratorBase> generator(
  359. CreateFieldGeneratorInternal(fields_by_number()[i]));
  360. generator->GenerateSerializationCode(printer);
  361. }
  362. // TODO(jonskeet): Memoize size of frozen messages?
  363. printer->Outdent();
  364. printer->Print(
  365. "}\n"
  366. "\n");
  367. WriteGeneratedCodeAttributes(printer);
  368. printer->Print(
  369. "public int CalculateSize() {\n");
  370. printer->Indent();
  371. printer->Print("int size = 0;\n");
  372. for (int i = 0; i < descriptor_->field_count(); i++) {
  373. scoped_ptr<FieldGeneratorBase> generator(
  374. CreateFieldGeneratorInternal(descriptor_->field(i)));
  375. generator->GenerateSerializedSizeCode(printer);
  376. }
  377. printer->Print("return size;\n");
  378. printer->Outdent();
  379. printer->Print("}\n\n");
  380. }
  381. void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
  382. // Note: These are separate from GenerateMessageSerializationMethods()
  383. // because they need to be generated even for messages that are optimized
  384. // for code size.
  385. map<string, string> vars;
  386. vars["class_name"] = class_name();
  387. WriteGeneratedCodeAttributes(printer);
  388. printer->Print(
  389. vars,
  390. "public void MergeFrom($class_name$ other) {\n");
  391. printer->Indent();
  392. printer->Print(
  393. "if (other == null) {\n"
  394. " return;\n"
  395. "}\n");
  396. // Merge non-oneof fields
  397. for (int i = 0; i < descriptor_->field_count(); i++) {
  398. if (!descriptor_->field(i)->containing_oneof()) {
  399. scoped_ptr<FieldGeneratorBase> generator(
  400. CreateFieldGeneratorInternal(descriptor_->field(i)));
  401. generator->GenerateMergingCode(printer);
  402. }
  403. }
  404. // Merge oneof fields
  405. for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
  406. vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
  407. vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
  408. printer->Print(vars, "switch (other.$property_name$Case) {\n");
  409. printer->Indent();
  410. for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
  411. const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
  412. vars["field_property_name"] = GetPropertyName(field);
  413. printer->Print(
  414. vars,
  415. "case $property_name$OneofCase.$field_property_name$:\n"
  416. " $field_property_name$ = other.$field_property_name$;\n"
  417. " break;\n");
  418. }
  419. printer->Outdent();
  420. printer->Print("}\n\n");
  421. }
  422. printer->Outdent();
  423. printer->Print("}\n\n");
  424. WriteGeneratedCodeAttributes(printer);
  425. printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n");
  426. printer->Indent();
  427. printer->Print(
  428. "uint tag;\n"
  429. "while ((tag = input.ReadTag()) != 0) {\n"
  430. " switch(tag) {\n");
  431. printer->Indent();
  432. printer->Indent();
  433. printer->Print(
  434. "default:\n"
  435. " input.SkipLastField();\n" // We're not storing the data, but we still need to consume it.
  436. " break;\n");
  437. for (int i = 0; i < fields_by_number().size(); i++) {
  438. const FieldDescriptor* field = fields_by_number()[i];
  439. internal::WireFormatLite::WireType wt =
  440. internal::WireFormat::WireTypeForFieldType(field->type());
  441. uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt);
  442. // Handle both packed and unpacked repeated fields with the same Read*Array call;
  443. // the two generated cases are the packed and unpacked tags.
  444. // TODO(jonskeet): Check that is_packable is equivalent to
  445. // is_repeated && wt in { VARINT, FIXED32, FIXED64 }.
  446. // It looks like it is...
  447. if (field->is_packable()) {
  448. printer->Print(
  449. "case $packed_tag$:\n",
  450. "packed_tag",
  451. SimpleItoa(
  452. internal::WireFormatLite::MakeTag(
  453. field->number(),
  454. internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
  455. }
  456. printer->Print("case $tag$: {\n", "tag", SimpleItoa(tag));
  457. printer->Indent();
  458. scoped_ptr<FieldGeneratorBase> generator(
  459. CreateFieldGeneratorInternal(field));
  460. generator->GenerateParsingCode(printer);
  461. printer->Print("break;\n");
  462. printer->Outdent();
  463. printer->Print("}\n");
  464. }
  465. printer->Outdent();
  466. printer->Print("}\n"); // switch
  467. printer->Outdent();
  468. printer->Print("}\n"); // while
  469. printer->Outdent();
  470. printer->Print("}\n\n"); // method
  471. }
  472. int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
  473. for (int i = 0; i < field_names().size(); i++) {
  474. if (field_names()[i] == descriptor->name()) {
  475. return i;
  476. }
  477. }
  478. GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name();
  479. return -1;
  480. }
  481. FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
  482. const FieldDescriptor* descriptor) {
  483. return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options());
  484. }
  485. } // namespace csharp
  486. } // namespace compiler
  487. } // namespace protobuf
  488. } // namespace google