• 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 #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