1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "google/protobuf/compiler/csharp/csharp_enum.h"
9
10 #include <sstream>
11 #include <string>
12
13 #include "google/protobuf/compiler/code_generator.h"
14 #include "absl/container/flat_hash_set.h"
15 #include "absl/log/absl_log.h"
16 #include "absl/strings/str_cat.h"
17 #include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
18 #include "google/protobuf/compiler/csharp/csharp_helpers.h"
19 #include "google/protobuf/compiler/csharp/csharp_options.h"
20 #include "google/protobuf/descriptor.h"
21 #include "google/protobuf/descriptor.pb.h"
22 #include "google/protobuf/io/printer.h"
23
24 namespace google {
25 namespace protobuf {
26 namespace compiler {
27 namespace csharp {
28
EnumGenerator(const EnumDescriptor * descriptor,const Options * options)29 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options* options) :
30 SourceGeneratorBase(options),
31 descriptor_(descriptor) {
32 }
33
~EnumGenerator()34 EnumGenerator::~EnumGenerator() {
35 }
36
Generate(io::Printer * printer)37 void EnumGenerator::Generate(io::Printer* printer) {
38 WriteEnumDocComment(printer, options(), descriptor_);
39 if (descriptor_->options().deprecated()) {
40 printer->Print("[global::System.ObsoleteAttribute]\n");
41 }
42 printer->Print("$access_level$ enum $name$ {\n",
43 "access_level", class_access_level(),
44 "name", descriptor_->name());
45 printer->Indent();
46 absl::flat_hash_set<std::string> used_names;
47 absl::flat_hash_set<int> used_number;
48 for (int i = 0; i < descriptor_->value_count(); i++) {
49 WriteEnumValueDocComment(printer, options(), descriptor_->value(i));
50 if (descriptor_->value(i)->options().deprecated()) {
51 printer->Print("[global::System.ObsoleteAttribute]\n");
52 }
53 const absl::string_view original_name = descriptor_->value(i)->name();
54 std::string name =
55 GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
56 // Make sure we don't get any duplicate names due to prefix removal.
57 while (!used_names.insert(name).second) {
58 // It's possible we'll end up giving this warning multiple times, but
59 // that's better than not at all.
60 ABSL_LOG(WARNING) << "Duplicate enum value " << name << " (originally "
61 << original_name << ") in " << descriptor_->name()
62 << "; adding underscore to distinguish";
63 absl::StrAppend(&name, "_");
64 }
65 int number = descriptor_->value(i)->number();
66 if (!used_number.insert(number).second) {
67 printer->Print(
68 "[pbr::OriginalName(\"$original_name$\", PreferredAlias = false)] "
69 "$name$ = $number$,\n",
70 "original_name", original_name, "name", name, "number",
71 absl::StrCat(number));
72 } else {
73 printer->Print(
74 "[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n",
75 "original_name", original_name, "name", name, "number",
76 absl::StrCat(number));
77 }
78 }
79 printer->Outdent();
80 printer->Print("}\n");
81 printer->Print("\n");
82 }
83
84 } // namespace csharp
85 } // namespace compiler
86 } // namespace protobuf
87 } // namespace google
88