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 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
13 #define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
14
15 #include <cstdint>
16 #include <string>
17
18 #include "absl/strings/string_view.h"
19 #include "google/protobuf/compiler/java/names.h"
20 #include "google/protobuf/compiler/java/options.h"
21 #include "google/protobuf/descriptor.h"
22 #include "google/protobuf/descriptor.pb.h"
23 #include "google/protobuf/io/printer.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 // Commonly-used separator comments. Thick is a line of '=', thin is a line
34 // of '-'.
35 extern const char kThickSeparator[];
36 extern const char kThinSeparator[];
37
38 bool IsForbiddenKotlin(absl::string_view field_name);
39
40 // If annotation_file is non-empty, prints a javax.annotation.Generated
41 // annotation to the given Printer. annotation_file will be referenced in the
42 // annotation's comments field. delimiter should be the Printer's delimiter
43 // character. annotation_file will be included verbatim into a Java literal
44 // string, so it should not contain quotes or invalid Java escape sequences;
45 // however, these are unlikely to appear in practice, as the value of
46 // annotation_file should be generated from the filename of the source file
47 // being annotated (which in turn must be a Java identifier plus ".java").
48 void PrintGeneratedAnnotation(io::Printer* printer, char delimiter = '$',
49 absl::string_view annotation_file = "",
50 Options options = {});
51
52 // If a GeneratedMessageLite contains non-lite enums, then its verifier
53 // must be instantiated inline, rather than retrieved from the enum class.
54 void PrintEnumVerifierLogic(
55 io::Printer* printer, const FieldDescriptor* descriptor,
56 const absl::flat_hash_map<absl::string_view, std::string>& variables,
57 absl::string_view var_name, absl::string_view terminating_string,
58 bool enforce_lite);
59
60 // Prints the Protobuf Java Version validator checking that the runtime and
61 // gencode versions are compatible.
62 void PrintGencodeVersionValidator(io::Printer* printer, bool oss_runtime,
63 absl::string_view java_class_name);
64
65 // Converts a name to camel-case. If cap_first_letter is true, capitalize the
66 // first letter.
67 std::string ToCamelCase(absl::string_view input, bool lower_first);
68
69 // Similar to UnderscoresToCamelCase, but guarantees that the result is a
70 // complete Java identifier by adding a _ if needed.
71 std::string CamelCaseFieldName(const FieldDescriptor* field);
72
73 // Get an identifier that uniquely identifies this type within the file.
74 // This is used to declare static variables related to this type at the
75 // outermost file scope.
76 std::string UniqueFileScopeIdentifier(const Descriptor* descriptor);
77
78 // Gets the unqualified class name for the file. For each .proto file, there
79 // will be one Java class containing all the immutable messages and another
80 // Java class containing all the mutable messages.
81 std::string FileClassName(const FileDescriptor* file, bool immutable);
82
83 // Returns the file's Java package name.
84 std::string FileJavaPackage(const FileDescriptor* file, bool immutable,
85 Options options = {});
86
87 // Returns output directory for the given package name.
88 std::string JavaPackageToDir(std::string package_name);
89
90 // Returns the name with Kotlin keywords enclosed in backticks
91 std::string EscapeKotlinKeywords(std::string name);
92
93 // Comma-separate list of option-specified interfaces implemented by the
94 // Message, to follow the "implements" declaration of the Message definition.
95 std::string ExtraMessageInterfaces(const Descriptor* descriptor);
96 // Comma-separate list of option-specified interfaces implemented by the
97 // MutableMessage, to follow the "implements" declaration of the MutableMessage
98 // definition.
99 std::string ExtraMutableMessageInterfaces(const Descriptor* descriptor);
100 // Comma-separate list of option-specified interfaces implemented by the
101 // Builder, to follow the "implements" declaration of the Builder definition.
102 std::string ExtraBuilderInterfaces(const Descriptor* descriptor);
103 // Comma-separate list of option-specified interfaces extended by the
104 // MessageOrBuilder, to follow the "extends" declaration of the
105 // MessageOrBuilder definition.
106 std::string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor);
107
108 // Get the unqualified Java class name for mutable messages. i.e. without
109 // package or outer classnames.
ShortMutableJavaClassName(const Descriptor * descriptor)110 inline std::string ShortMutableJavaClassName(const Descriptor* descriptor) {
111 return std::string(descriptor->name());
112 }
113
114 // Whether the given descriptor is for one of the core descriptor protos. We
115 // cannot currently use the new runtime with core protos since there is a
116 // bootstrapping problem with obtaining their descriptors.
IsDescriptorProto(const Descriptor * descriptor)117 inline bool IsDescriptorProto(const Descriptor* descriptor) {
118 return descriptor->file()->name() == "net/proto2/proto/descriptor.proto" ||
119 descriptor->file()->name() == "google/protobuf/descriptor.proto";
120 }
121
122 // Returns the stored type string used by the experimental runtime for oneof
123 // fields.
124 std::string GetOneofStoredType(const FieldDescriptor* field);
125
126 // We use either the proto1 enums if the enum is generated, otherwise fall back
127 // to use integers.
128 enum class Proto1EnumRepresentation {
129 kEnum,
130 kInteger,
131 };
132
133 // Returns which representation we should use.
GetProto1EnumRepresentation(const EnumDescriptor * descriptor)134 inline Proto1EnumRepresentation GetProto1EnumRepresentation(
135 const EnumDescriptor* descriptor) {
136 if (descriptor->containing_type() != nullptr) {
137 return Proto1EnumRepresentation::kEnum;
138 }
139 return Proto1EnumRepresentation::kInteger;
140 }
141
142 // Whether we should generate multiple java files for messages.
MultipleJavaFiles(const FileDescriptor * descriptor,bool immutable)143 inline bool MultipleJavaFiles(const FileDescriptor* descriptor,
144 bool immutable) {
145 (void)immutable;
146 return descriptor->options().java_multiple_files();
147 }
148
149
150 // Returns true if `descriptor` will be written to its own .java file.
151 // `immutable` should be set to true if we're generating for the immutable API.
152 template <typename Descriptor>
IsOwnFile(const Descriptor * descriptor,bool immutable)153 bool IsOwnFile(const Descriptor* descriptor, bool immutable) {
154 return descriptor->containing_type() == nullptr &&
155 MultipleJavaFiles(descriptor->file(), immutable);
156 }
157
158 template <>
IsOwnFile(const ServiceDescriptor * descriptor,bool immutable)159 inline bool IsOwnFile(const ServiceDescriptor* descriptor, bool immutable) {
160 return MultipleJavaFiles(descriptor->file(), immutable);
161 }
162
163 // If `descriptor` describes an object with its own .java file,
164 // returns the name (relative to that .java file) of the file that stores
165 // annotation data for that descriptor. `suffix` is usually empty, but may
166 // (e.g.) be "OrBuilder" for some generated interfaces.
167 template <typename Descriptor>
AnnotationFileName(const Descriptor * descriptor,absl::string_view suffix)168 std::string AnnotationFileName(const Descriptor* descriptor,
169 absl::string_view suffix) {
170 return absl::StrCat(descriptor->name(), suffix, ".java.pb.meta");
171 }
172
173 // Get the unqualified name that should be used for a field's field
174 // number constant.
175 std::string FieldConstantName(const FieldDescriptor* field);
176
177 // Returns the type of the FieldDescriptor.
178 // This does nothing interesting for the open source release, but is used for
179 // hacks that improve compatibility with version 1 protocol buffers at Google.
180 FieldDescriptor::Type GetType(const FieldDescriptor* field);
181
182 enum JavaType {
183 JAVATYPE_INT,
184 JAVATYPE_LONG,
185 JAVATYPE_FLOAT,
186 JAVATYPE_DOUBLE,
187 JAVATYPE_BOOLEAN,
188 JAVATYPE_STRING,
189 JAVATYPE_BYTES,
190 JAVATYPE_ENUM,
191 JAVATYPE_MESSAGE
192 };
193
194 JavaType GetJavaType(const FieldDescriptor* field);
195
196 absl::string_view PrimitiveTypeName(JavaType type);
197
198 // Get the fully-qualified class name for a boxed primitive type, e.g.
199 // "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
200 // types.
201 absl::string_view BoxedPrimitiveTypeName(JavaType type);
202
203 // Kotlin source does not distinguish between primitives and non-primitives,
204 // but does use Kotlin-specific qualified types for them.
205 absl::string_view KotlinTypeName(JavaType type);
206
207 // Get the name of the java enum constant representing this type. E.g.,
208 // "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full
209 // name is "com.google.protobuf.WireFormat.FieldType.INT32".
210 absl::string_view FieldTypeName(const FieldDescriptor::Type field_type);
211
212 class ClassNameResolver;
213 std::string DefaultValue(const FieldDescriptor* field, bool immutable,
214 ClassNameResolver* name_resolver,
215 Options options = {});
216 inline std::string ImmutableDefaultValue(const FieldDescriptor* field,
217 ClassNameResolver* name_resolver,
218 Options options = {}) {
219 return DefaultValue(field, true, name_resolver, options);
220 }
221 bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
222 bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field);
223
224 // Does this message class have descriptor and reflection methods?
HasDescriptorMethods(const Descriptor *,bool enforce_lite)225 inline bool HasDescriptorMethods(const Descriptor* /* descriptor */,
226 bool enforce_lite) {
227 return !enforce_lite;
228 }
HasDescriptorMethods(const EnumDescriptor *,bool enforce_lite)229 inline bool HasDescriptorMethods(const EnumDescriptor* /* descriptor */,
230 bool enforce_lite) {
231 return !enforce_lite;
232 }
HasDescriptorMethods(const FileDescriptor *,bool enforce_lite)233 inline bool HasDescriptorMethods(const FileDescriptor* /* descriptor */,
234 bool enforce_lite) {
235 return !enforce_lite;
236 }
237
238 // Should we generate generic services for this file?
HasGenericServices(const FileDescriptor * file,bool enforce_lite)239 inline bool HasGenericServices(const FileDescriptor* file, bool enforce_lite) {
240 return file->service_count() > 0 &&
241 HasDescriptorMethods(file, enforce_lite) &&
242 file->options().java_generic_services();
243 }
244
245 // Methods for shared bitfields.
246
247 // Gets the name of the shared bitfield for the given index.
248 std::string GetBitFieldName(int index);
249
250 // Gets the name of the shared bitfield for the given bit index.
251 // Effectively, GetBitFieldName(bitIndex / 32)
252 std::string GetBitFieldNameForBit(int bitIndex);
253
254 // Generates the java code for the expression that returns the boolean value
255 // of the bit of the shared bitfields for the given bit index.
256 // Example: "((bitField1_ & 0x04) == 0x04)"
257 std::string GenerateGetBit(int bitIndex);
258
259 // Generates the java code for the expression that sets the bit of the shared
260 // bitfields for the given bit index.
261 // Example: "bitField1_ = (bitField1_ | 0x04)"
262 std::string GenerateSetBit(int bitIndex);
263
264 // Generates the java code for the expression that clears the bit of the shared
265 // bitfields for the given bit index.
266 // Example: "bitField1_ = (bitField1_ & ~0x04)"
267 std::string GenerateClearBit(int bitIndex);
268
269 // Does the same as GenerateGetBit but operates on the bit field on a local
270 // variable. This is used by the builder to copy the value in the builder to
271 // the message.
272 // Example: "((from_bitField1_ & 0x04) == 0x04)"
273 std::string GenerateGetBitFromLocal(int bitIndex);
274
275 // Does the same as GenerateSetBit but operates on the bit field on a local
276 // variable. This is used by the builder to copy the value in the builder to
277 // the message.
278 // Example: "to_bitField1_ = (to_bitField1_ | 0x04)"
279 std::string GenerateSetBitToLocal(int bitIndex);
280
281 // Does the same as GenerateGetBit but operates on the bit field on a local
282 // variable. This is used by the parsing constructor to record if a repeated
283 // field is mutable.
284 // Example: "((mutable_bitField1_ & 0x04) == 0x04)"
285 std::string GenerateGetBitMutableLocal(int bitIndex);
286
287 // Does the same as GenerateSetBit but operates on the bit field on a local
288 // variable. This is used by the parsing constructor to record if a repeated
289 // field is mutable.
290 // Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)"
291 std::string GenerateSetBitMutableLocal(int bitIndex);
292
293 // Returns whether the JavaType is a reference type.
294 bool IsReferenceType(JavaType type);
295
296 // Returns the capitalized name for calling relative functions in
297 // CodedInputStream
298 absl::string_view GetCapitalizedType(const FieldDescriptor* field,
299 bool immutable, Options options);
300
301 // For encodings with fixed sizes, returns that size in bytes. Otherwise
302 // returns -1.
303 int FixedSize(FieldDescriptor::Type type);
304
305 // Comparators used to sort fields in MessageGenerator
306 struct FieldOrderingByNumber {
operatorFieldOrderingByNumber307 inline bool operator()(const FieldDescriptor* a,
308 const FieldDescriptor* b) const {
309 return a->number() < b->number();
310 }
311 };
312
313 struct ExtensionRangeOrdering {
operatorExtensionRangeOrdering314 bool operator()(const Descriptor::ExtensionRange* a,
315 const Descriptor::ExtensionRange* b) const {
316 return a->start_number() < b->start_number();
317 }
318 };
319
320 // Sort the fields of the given Descriptor by number into a new[]'d array
321 // and return it. The caller should delete the returned array.
322 const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor);
323
324 // Does this message class have any packed fields?
HasPackedFields(const Descriptor * descriptor)325 inline bool HasPackedFields(const Descriptor* descriptor) {
326 for (int i = 0; i < descriptor->field_count(); i++) {
327 if (descriptor->field(i)->is_packed()) {
328 return true;
329 }
330 }
331 return false;
332 }
333
334 // Check a message type and its sub-message types recursively to see if any of
335 // them has a required field. Return true if a required field is found.
336 bool HasRequiredFields(const Descriptor* descriptor);
337
338 bool IsRealOneof(const FieldDescriptor* descriptor);
339
HasHasbit(const FieldDescriptor * descriptor)340 inline bool HasHasbit(const FieldDescriptor* descriptor) {
341 return internal::cpp::HasHasbit(descriptor);
342 }
343
344 // Check whether a message has repeated fields.
345 bool HasRepeatedFields(const Descriptor* descriptor);
346
IsMapEntry(const Descriptor * descriptor)347 inline bool IsMapEntry(const Descriptor* descriptor) {
348 return descriptor->options().map_entry();
349 }
350
IsMapField(const FieldDescriptor * descriptor)351 inline bool IsMapField(const FieldDescriptor* descriptor) {
352 return descriptor->is_map();
353 }
354
IsAnyMessage(const Descriptor * descriptor)355 inline bool IsAnyMessage(const Descriptor* descriptor) {
356 return descriptor->full_name() == "google.protobuf.Any";
357 }
358
IsWrappersProtoFile(const FileDescriptor * descriptor)359 inline bool IsWrappersProtoFile(const FileDescriptor* descriptor) {
360 return descriptor->name() == "google/protobuf/wrappers.proto";
361 }
362
363 void WriteUInt32ToUtf16CharSequence(uint32_t number,
364 std::vector<uint16_t>* output);
365
WriteIntToUtf16CharSequence(int value,std::vector<uint16_t> * output)366 inline void WriteIntToUtf16CharSequence(int value,
367 std::vector<uint16_t>* output) {
368 WriteUInt32ToUtf16CharSequence(static_cast<uint32_t>(value), output);
369 }
370
371 // Escape a UTF-16 character so it can be embedded in a Java string literal.
372 void EscapeUtf16ToString(uint16_t code, std::string* output);
373
374 // To get the total number of entries need to be built for experimental runtime
375 // and the first field number that are not in the table part
376 std::pair<int, int> GetTableDrivenNumberOfEntriesAndLookUpStartFieldNumber(
377 const FieldDescriptor** fields, int count);
378
379 const FieldDescriptor* MapKeyField(const FieldDescriptor* descriptor);
380
381 const FieldDescriptor* MapValueField(const FieldDescriptor* descriptor);
382
JvmSynthetic(bool jvm_dsl)383 inline std::string JvmSynthetic(bool jvm_dsl) {
384 return jvm_dsl ? "@kotlin.jvm.JvmSynthetic\n" : "";
385 }
386
387 struct JvmNameContext {
388 const Options& options;
389 io::Printer* printer;
390 bool lite = true;
391 };
392
JvmName(absl::string_view name,const JvmNameContext & context)393 inline void JvmName(absl::string_view name, const JvmNameContext& context) {
394 if (context.lite && !context.options.jvm_dsl) return;
395 context.printer->Emit("@kotlin.jvm.JvmName(\"");
396 // Note: `name` will likely have vars in it that we do want to interpolate.
397 context.printer->Emit(name);
398 context.printer->Emit("\")\n");
399 }
400
401 } // namespace java
402 } // namespace compiler
403 } // namespace protobuf
404 } // namespace google
405
406 #include "google/protobuf/port_undef.inc"
407 #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
408