• 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 // Author: kenton@google.com (Kenton Varda)
9 //  Based on original Protocol Buffers design by
10 //  Sanjay Ghemawat, Jeff Dean, and others.
11 
12 #include "google/protobuf/compiler/java/names.h"
13 
14 #include <string>
15 
16 #include "absl/container/flat_hash_set.h"
17 #include "absl/strings/str_cat.h"
18 #include "absl/strings/string_view.h"
19 #include "google/protobuf/compiler/java/helpers.h"
20 #include "google/protobuf/compiler/java/name_resolver.h"
21 #include "google/protobuf/compiler/java/options.h"
22 #include "google/protobuf/descriptor.h"
23 #include "google/protobuf/descriptor.pb.h"
24 
25 // Must be last.
26 #include "google/protobuf/port_def.inc"
27 
28 namespace google {
29 namespace protobuf {
30 namespace compiler {
31 namespace java {
32 
33 namespace {
34 
DefaultPackage(Options options)35 const char* DefaultPackage(Options options) {
36   return options.opensource_runtime ? "" : "com.google.protos";
37 }
38 
IsReservedName(absl::string_view name)39 bool IsReservedName(absl::string_view name) {
40   static const auto& kReservedNames =
41       *new absl::flat_hash_set<absl::string_view>({
42           "abstract", "assert",     "boolean",  "break",     "byte",
43           "case",     "catch",      "char",     "class",     "const",
44           "continue", "default",    "do",       "double",    "else",
45           "enum",     "extends",    "false",    "final",     "finally",
46           "float",    "for",        "goto",     "if",        "implements",
47           "import",   "instanceof", "int",      "interface", "java",
48           "long",     "native",     "new",      "null",      "package",
49           "private",  "protected",  "public",   "return",    "short",
50           "static",   "strictfp",   "super",    "switch",    "synchronized",
51           "this",     "throw",      "throws",   "transient", "true",
52           "try",      "void",       "volatile", "while",
53       });
54   return kReservedNames.contains(name);
55 }
56 
IsForbidden(absl::string_view field_name)57 bool IsForbidden(absl::string_view field_name) {
58   // Names that should be avoided (in UpperCamelCase format).
59   // Using them will cause the compiler to generate accessors whose names
60   // collide with methods defined in base classes.
61   // Keep this list in sync with specialFieldNames in
62   // java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java
63   static const auto& kForbiddenNames =
64       *new absl::flat_hash_set<absl::string_view>({
65         // java.lang.Object:
66           "Class",
67           // com.google.protobuf.MessageLiteOrBuilder:
68           "DefaultInstanceForType",
69           // com.google.protobuf.MessageLite:
70           "ParserForType",
71           "SerializedSize",
72           // com.google.protobuf.MessageOrBuilder:
73           "AllFields",
74           "DescriptorForType",
75           "InitializationErrorString",
76           "UnknownFields",
77           // obsolete. kept for backwards compatibility of generated code
78           "CachedSize",
79       });
80   return kForbiddenNames.contains(UnderscoresToCamelCase(field_name, true));
81 }
82 
FieldName(const FieldDescriptor * field)83 std::string FieldName(const FieldDescriptor* field) {
84   std::string field_name;
85   // Groups are hacky:  The name of the field is just the lower-cased name
86   // of the group type.  In Java, though, we would like to retain the original
87   // capitalization of the type name.
88   if (internal::cpp::IsGroupLike(*field)) {
89     field_name = field->message_type()->name();
90   } else {
91     field_name = field->name();
92   }
93   if (IsForbidden(field_name)) {
94     // Append a trailing "#" to indicate that the name should be decorated to
95     // avoid collision with other names.
96     absl::StrAppend(&field_name, "#");
97   }
98   return field_name;
99 }
100 
101 }  // namespace
102 
ClassName(const Descriptor * descriptor)103 std::string ClassName(const Descriptor* descriptor) {
104   ClassNameResolver name_resolver;
105   return name_resolver.GetClassName(descriptor, true);
106 }
107 
ClassName(const EnumDescriptor * descriptor)108 std::string ClassName(const EnumDescriptor* descriptor) {
109   ClassNameResolver name_resolver;
110   return name_resolver.GetClassName(descriptor, true);
111 }
112 
ClassName(const ServiceDescriptor * descriptor)113 std::string ClassName(const ServiceDescriptor* descriptor) {
114   ClassNameResolver name_resolver;
115   return name_resolver.GetClassName(descriptor, true);
116 }
117 
ClassName(const FileDescriptor * descriptor)118 std::string ClassName(const FileDescriptor* descriptor) {
119   ClassNameResolver name_resolver;
120   return name_resolver.GetClassName(descriptor, true);
121 }
122 
FileJavaPackage(const FileDescriptor * file,bool immutable,Options options)123 std::string FileJavaPackage(const FileDescriptor* file, bool immutable,
124                             Options options) {
125   std::string result;
126 
127   if (file->options().has_java_package()) {
128     result = file->options().java_package();
129   } else {
130     result = DefaultPackage(options);
131     if (!file->package().empty()) {
132       if (!result.empty()) result += '.';
133       result += file->package();
134     }
135   }
136 
137   return result;
138 }
139 
FileJavaPackage(const FileDescriptor * file,Options options)140 std::string FileJavaPackage(const FileDescriptor* file, Options options) {
141   return FileJavaPackage(file, true /* immutable */, options);
142 }
143 
JavaPackageDirectory(const FileDescriptor * file)144 std::string JavaPackageDirectory(const FileDescriptor* file) {
145   return JavaPackageToDir(FileJavaPackage(file));
146 }
147 
FileClassName(const FileDescriptor * file)148 std::string FileClassName(const FileDescriptor* file) {
149   return FileClassName(file, /*immutable=*/true);
150 }
151 
CapitalizedFieldName(const FieldDescriptor * field)152 std::string CapitalizedFieldName(const FieldDescriptor* field) {
153   return UnderscoresToCamelCase(FieldName(field), true);
154 }
155 
CapitalizedOneofName(const OneofDescriptor * oneof)156 std::string CapitalizedOneofName(const OneofDescriptor* oneof) {
157   return UnderscoresToCamelCase(oneof->name(), true);
158 }
159 
UnderscoresToCamelCase(const FieldDescriptor * field)160 std::string UnderscoresToCamelCase(const FieldDescriptor* field) {
161   return UnderscoresToCamelCase(FieldName(field), false);
162 }
163 
UnderscoresToCapitalizedCamelCase(const FieldDescriptor * field)164 std::string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
165   return UnderscoresToCamelCase(FieldName(field), true);
166 }
167 
UnderscoresToCamelCase(const MethodDescriptor * method)168 std::string UnderscoresToCamelCase(const MethodDescriptor* method) {
169   return UnderscoresToCamelCase(method->name(), false);
170 }
171 
UnderscoresToCamelCaseCheckReserved(const FieldDescriptor * field)172 std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field) {
173   std::string name = UnderscoresToCamelCase(field);
174   if (IsReservedName(name)) {
175     absl::StrAppend(&name, "_");
176   }
177   return name;
178 }
179 
180 
181 }  // namespace java
182 }  // namespace compiler
183 }  // namespace protobuf
184 }  // namespace google
185 
186 #include "google/protobuf/port_undef.inc"
187