• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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