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