| // Protocol Buffers - Google's data interchange format |
| // Copyright 2008 Google Inc. All rights reserved. |
| // https://developers.google.com/protocol-buffers/ |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| // Author: kenton@google.com (Kenton Varda) |
| // Based on original Protocol Buffers design by |
| // Sanjay Ghemawat, Jeff Dean, and others. |
| |
| #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ |
| #define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ |
| |
| #include <string> |
| #include <google/protobuf/compiler/java/java_context.h> |
| #include <google/protobuf/io/printer.h> |
| #include <google/protobuf/descriptor.pb.h> |
| #include <google/protobuf/descriptor.h> |
| |
| namespace google { |
| namespace protobuf { |
| namespace compiler { |
| namespace java { |
| |
| // Commonly-used separator comments. Thick is a line of '=', thin is a line |
| // of '-'. |
| extern const char kThickSeparator[]; |
| extern const char kThinSeparator[]; |
| |
| // If annotation_file is non-empty, prints a javax.annotation.Generated |
| // annotation to the given Printer. annotation_file will be referenced in the |
| // annotation's comments field. delimiter should be the Printer's delimiter |
| // character. annotation_file will be included verbatim into a Java literal |
| // string, so it should not contain quotes or invalid Java escape sequences; |
| // however, these are unlikely to appear in practice, as the value of |
| // annotation_file should be generated from the filename of the source file |
| // being annotated (which in turn must be a Java identifier plus ".java"). |
| void PrintGeneratedAnnotation(io::Printer* printer, char delimiter = '$', |
| const string& annotation_file = ""); |
| |
| // Converts a name to camel-case. If cap_first_letter is true, capitalize the |
| // first letter. |
| string UnderscoresToCamelCase(const string& name, bool cap_first_letter); |
| // Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes |
| // "fooBarBaz" or "FooBarBaz", respectively. |
| string UnderscoresToCamelCase(const FieldDescriptor* field); |
| string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); |
| |
| // Similar, but for method names. (Typically, this merely has the effect |
| // of lower-casing the first letter of the name.) |
| string UnderscoresToCamelCase(const MethodDescriptor* method); |
| |
| // Similar to UnderscoresToCamelCase, but guarentees that the result is a |
| // complete Java identifier by adding a _ if needed. |
| string CamelCaseFieldName(const FieldDescriptor* field); |
| |
| // Get an identifier that uniquely identifies this type within the file. |
| // This is used to declare static variables related to this type at the |
| // outermost file scope. |
| string UniqueFileScopeIdentifier(const Descriptor* descriptor); |
| |
| // Strips ".proto" or ".protodevel" from the end of a filename. |
| string StripProto(const string& filename); |
| |
| // Gets the unqualified class name for the file. For each .proto file, there |
| // will be one Java class containing all the immutable messages and another |
| // Java class containing all the mutable messages. |
| // TODO(xiaofeng): remove the default value after updating client code. |
| string FileClassName(const FileDescriptor* file, bool immutable = true); |
| |
| // Returns the file's Java package name. |
| string FileJavaPackage(const FileDescriptor* file, bool immutable = true); |
| |
| // Returns output directory for the given package name. |
| string JavaPackageToDir(string package_name); |
| |
| // Converts the given fully-qualified name in the proto namespace to its |
| // fully-qualified name in the Java namespace, given that it is in the given |
| // file. |
| // TODO(xiaofeng): this method is deprecated and should be removed in the |
| // future. |
| string ToJavaName(const string& full_name, |
| const FileDescriptor* file); |
| |
| // TODO(xiaofeng): the following methods are kept for they are exposed |
| // publicly in //google/protobuf/compiler/java/names.h. They return |
| // immutable names only and should be removed after mutable API is |
| // integrated into google3. |
| string ClassName(const Descriptor* descriptor); |
| string ClassName(const EnumDescriptor* descriptor); |
| string ClassName(const ServiceDescriptor* descriptor); |
| string ClassName(const FileDescriptor* descriptor); |
| |
| // Comma-separate list of option-specified interfaces implemented by the |
| // Message, to follow the "implements" declaration of the Message definition. |
| string ExtraMessageInterfaces(const Descriptor* descriptor); |
| // Comma-separate list of option-specified interfaces implemented by the |
| // MutableMessage, to follow the "implements" declaration of the MutableMessage |
| // definition. |
| string ExtraMutableMessageInterfaces(const Descriptor* descriptor); |
| // Comma-separate list of option-specified interfaces implemented by the |
| // Builder, to follow the "implements" declaration of the Builder definition. |
| string ExtraBuilderInterfaces(const Descriptor* descriptor); |
| // Comma-separate list of option-specified interfaces extended by the |
| // MessageOrBuilder, to follow the "extends" declaration of the |
| // MessageOrBuilder definition. |
| string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor); |
| |
| // Get the unqualified Java class name for mutable messages. i.e. without |
| // package or outer classnames. |
| inline string ShortMutableJavaClassName(const Descriptor* descriptor) { |
| return descriptor->name(); |
| } |
| |
| // Whether the given descriptor is for one of the core descriptor protos. We |
| // cannot currently use the new runtime with core protos since there is a |
| // bootstrapping problem with obtaining their descriptors. |
| inline bool IsDescriptorProto(const Descriptor* descriptor) { |
| return descriptor->file()->name() == "google/protobuf/descriptor.proto"; |
| } |
| |
| |
| // Whether we should generate multiple java files for messages. |
| inline bool MultipleJavaFiles( |
| const FileDescriptor* descriptor, bool immutable) { |
| return descriptor->options().java_multiple_files(); |
| } |
| |
| // Returns true if `descriptor` will be written to its own .java file. |
| // `immutable` should be set to true if we're generating for the immutable API. |
| template <typename Descriptor> |
| bool IsOwnFile(const Descriptor* descriptor, bool immutable) { |
| return descriptor->containing_type() == NULL && |
| MultipleJavaFiles(descriptor->file(), immutable); |
| } |
| |
| template <> |
| inline bool IsOwnFile(const ServiceDescriptor* descriptor, bool immutable) { |
| return MultipleJavaFiles(descriptor->file(), immutable); |
| } |
| |
| // If `descriptor` describes an object with its own .java file, |
| // returns the name (relative to that .java file) of the file that stores |
| // annotation data for that descriptor. `suffix` is usually empty, but may |
| // (e.g.) be "OrBuilder" for some generated interfaces. |
| template <typename Descriptor> |
| string AnnotationFileName(const Descriptor* descriptor, const string& suffix) { |
| return descriptor->name() + suffix + ".java.pb.meta"; |
| } |
| |
| template <typename Descriptor> |
| void MaybePrintGeneratedAnnotation(Context* context, io::Printer* printer, |
| Descriptor* descriptor, bool immutable, |
| const string& suffix = "") { |
| if (context->options().annotate_code && IsOwnFile(descriptor, immutable)) { |
| PrintGeneratedAnnotation(printer, '$', |
| AnnotationFileName(descriptor, suffix)); |
| } |
| } |
| |
| // Get the unqualified name that should be used for a field's field |
| // number constant. |
| string FieldConstantName(const FieldDescriptor *field); |
| |
| // Returns the type of the FieldDescriptor. |
| // This does nothing interesting for the open source release, but is used for |
| // hacks that improve compatibility with version 1 protocol buffers at Google. |
| FieldDescriptor::Type GetType(const FieldDescriptor* field); |
| |
| enum JavaType { |
| JAVATYPE_INT, |
| JAVATYPE_LONG, |
| JAVATYPE_FLOAT, |
| JAVATYPE_DOUBLE, |
| JAVATYPE_BOOLEAN, |
| JAVATYPE_STRING, |
| JAVATYPE_BYTES, |
| JAVATYPE_ENUM, |
| JAVATYPE_MESSAGE |
| }; |
| |
| JavaType GetJavaType(const FieldDescriptor* field); |
| |
| const char* PrimitiveTypeName(JavaType type); |
| |
| // Get the fully-qualified class name for a boxed primitive type, e.g. |
| // "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message |
| // types. |
| const char* BoxedPrimitiveTypeName(JavaType type); |
| |
| // Get the name of the java enum constant representing this type. E.g., |
| // "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full |
| // name is "com.google.protobuf.WireFormat.FieldType.INT32". |
| const char* FieldTypeName(const FieldDescriptor::Type field_type); |
| |
| class ClassNameResolver; |
| string DefaultValue(const FieldDescriptor* field, bool immutable, |
| ClassNameResolver* name_resolver); |
| inline string ImmutableDefaultValue(const FieldDescriptor* field, |
| ClassNameResolver* name_resolver) { |
| return DefaultValue(field, true, name_resolver); |
| } |
| bool IsDefaultValueJavaDefault(const FieldDescriptor* field); |
| bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field); |
| |
| // Does this message class have descriptor and reflection methods? |
| inline bool HasDescriptorMethods(const Descriptor* descriptor, |
| bool enforce_lite) { |
| return !enforce_lite && |
| descriptor->file()->options().optimize_for() != |
| FileOptions::LITE_RUNTIME; |
| } |
| inline bool HasDescriptorMethods(const EnumDescriptor* descriptor, |
| bool enforce_lite) { |
| return !enforce_lite && |
| descriptor->file()->options().optimize_for() != |
| FileOptions::LITE_RUNTIME; |
| } |
| inline bool HasDescriptorMethods(const FileDescriptor* descriptor, |
| bool enforce_lite) { |
| return !enforce_lite && |
| descriptor->options().optimize_for() != FileOptions::LITE_RUNTIME; |
| } |
| |
| // Should we generate generic services for this file? |
| inline bool HasGenericServices(const FileDescriptor *file, bool enforce_lite) { |
| return file->service_count() > 0 && |
| HasDescriptorMethods(file, enforce_lite) && |
| file->options().java_generic_services(); |
| } |
| |
| // Methods for shared bitfields. |
| |
| // Gets the name of the shared bitfield for the given index. |
| string GetBitFieldName(int index); |
| |
| // Gets the name of the shared bitfield for the given bit index. |
| // Effectively, GetBitFieldName(bitIndex / 32) |
| string GetBitFieldNameForBit(int bitIndex); |
| |
| // Generates the java code for the expression that returns the boolean value |
| // of the bit of the shared bitfields for the given bit index. |
| // Example: "((bitField1_ & 0x04) == 0x04)" |
| string GenerateGetBit(int bitIndex); |
| |
| // Generates the java code for the expression that sets the bit of the shared |
| // bitfields for the given bit index. |
| // Example: "bitField1_ = (bitField1_ | 0x04)" |
| string GenerateSetBit(int bitIndex); |
| |
| // Generates the java code for the expression that clears the bit of the shared |
| // bitfields for the given bit index. |
| // Example: "bitField1_ = (bitField1_ & ~0x04)" |
| string GenerateClearBit(int bitIndex); |
| |
| // Does the same as GenerateGetBit but operates on the bit field on a local |
| // variable. This is used by the builder to copy the value in the builder to |
| // the message. |
| // Example: "((from_bitField1_ & 0x04) == 0x04)" |
| string GenerateGetBitFromLocal(int bitIndex); |
| |
| // Does the same as GenerateSetBit but operates on the bit field on a local |
| // variable. This is used by the builder to copy the value in the builder to |
| // the message. |
| // Example: "to_bitField1_ = (to_bitField1_ | 0x04)" |
| string GenerateSetBitToLocal(int bitIndex); |
| |
| // Does the same as GenerateGetBit but operates on the bit field on a local |
| // variable. This is used by the parsing constructor to record if a repeated |
| // field is mutable. |
| // Example: "((mutable_bitField1_ & 0x04) == 0x04)" |
| string GenerateGetBitMutableLocal(int bitIndex); |
| |
| // Does the same as GenerateSetBit but operates on the bit field on a local |
| // variable. This is used by the parsing constructor to record if a repeated |
| // field is mutable. |
| // Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)" |
| string GenerateSetBitMutableLocal(int bitIndex); |
| |
| // Returns whether the JavaType is a reference type. |
| bool IsReferenceType(JavaType type); |
| |
| // Returns the capitalized name for calling relative functions in |
| // CodedInputStream |
| const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable); |
| |
| // For encodings with fixed sizes, returns that size in bytes. Otherwise |
| // returns -1. |
| int FixedSize(FieldDescriptor::Type type); |
| |
| // Comparators used to sort fields in MessageGenerator |
| struct FieldOrderingByNumber { |
| inline bool operator()(const FieldDescriptor* a, |
| const FieldDescriptor* b) const { |
| return a->number() < b->number(); |
| } |
| }; |
| |
| struct ExtensionRangeOrdering { |
| bool operator()(const Descriptor::ExtensionRange* a, |
| const Descriptor::ExtensionRange* b) const { |
| return a->start < b->start; |
| } |
| }; |
| |
| // Sort the fields of the given Descriptor by number into a new[]'d array |
| // and return it. The caller should delete the returned array. |
| const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor); |
| |
| // Does this message class have any packed fields? |
| inline bool HasPackedFields(const Descriptor* descriptor) { |
| for (int i = 0; i < descriptor->field_count(); i++) { |
| if (descriptor->field(i)->is_packed()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| // Check a message type and its sub-message types recursively to see if any of |
| // them has a required field. Return true if a required field is found. |
| bool HasRequiredFields(const Descriptor* descriptor); |
| |
| // Whether a .proto file supports field presence test for non-message types. |
| inline bool SupportFieldPresence(const FileDescriptor* descriptor) { |
| return descriptor->syntax() != FileDescriptor::SYNTAX_PROTO3; |
| } |
| |
| // Whether generate classes expose public PARSER instances. |
| inline bool ExposePublicParser(const FileDescriptor* descriptor) { |
| // TODO(liujisi): Mark the PARSER private in 3.1.x releases. |
| return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2; |
| } |
| |
| // Whether unknown enum values are kept (i.e., not stored in UnknownFieldSet |
| // but in the message and can be queried using additional getters that return |
| // ints. |
| inline bool SupportUnknownEnumValue(const FileDescriptor* descriptor) { |
| return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3; |
| } |
| |
| // Check whether a mesasge has repeated fields. |
| bool HasRepeatedFields(const Descriptor* descriptor); |
| |
| inline bool IsMapEntry(const Descriptor* descriptor) { |
| return descriptor->options().map_entry(); |
| } |
| |
| inline bool IsMapField(const FieldDescriptor* descriptor) { |
| return descriptor->is_map(); |
| } |
| |
| inline bool IsAnyMessage(const Descriptor* descriptor) { |
| return descriptor->full_name() == "google.protobuf.Any"; |
| } |
| |
| inline bool IsWrappersProtoFile(const FileDescriptor* descriptor) { |
| return descriptor->name() == "google/protobuf/wrappers.proto"; |
| } |
| |
| inline bool CheckUtf8(const FieldDescriptor* descriptor) { |
| return descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 || |
| descriptor->file()->options().java_string_check_utf8(); |
| } |
| |
| inline string GeneratedCodeVersionSuffix() { |
| return "V3"; |
| } |
| |
| inline bool EnableExperimentalRuntime(Context* context) { |
| return false; |
| } |
| |
| void WriteUInt32ToUtf16CharSequence(uint32 number, std::vector<uint16>* output); |
| |
| inline void WriteIntToUtf16CharSequence(int value, |
| std::vector<uint16>* output) { |
| WriteUInt32ToUtf16CharSequence(static_cast<uint32>(value), output); |
| } |
| |
| // Escape a UTF-16 character so it can be embedded in a Java string literal. |
| void EscapeUtf16ToString(uint16 code, string* output); |
| |
| // Only the lowest two bytes of the return value are used. The lowest byte |
| // is the integer value of a j/c/g/protobuf/FieldType enum. For the other |
| // byte: |
| // bit 0: whether the field is required. |
| // bit 1: whether the field requires UTF-8 validation. |
| // bit 2: whether the field needs isInitialized check. |
| // bit 3: whether the field is a map field with proto2 enum value. |
| // bits 4-7: unused |
| int GetExperimentalJavaFieldType(const FieldDescriptor* field); |
| } // namespace java |
| } // namespace compiler |
| } // namespace protobuf |
| |
| } // namespace google |
| #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ |