diff --git a/objectivec/GPBType.pbobjc.m b/objectivec/GPBType.pbobjc.m index 1dade29ff9..7a4b6578d6 100644 --- a/objectivec/GPBType.pbobjc.m +++ b/objectivec/GPBType.pbobjc.m @@ -83,6 +83,122 @@ BOOL GPBSyntax_IsValidValue(int32_t value__) { } } +#pragma mark - Enum GPBField_Kind + +GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "TypeUnknown\000TypeDouble\000TypeFloat\000TypeInt" + "64\000TypeUint64\000TypeInt32\000TypeFixed64\000Type" + "Fixed32\000TypeBool\000TypeString\000TypeGroup\000Ty" + "peMessage\000TypeBytes\000TypeUint32\000TypeEnum\000" + "TypeSfixed32\000TypeSfixed64\000TypeSint32\000Typ" + "eSint64\000"; + static const int32_t values[] = { + GPBField_Kind_TypeUnknown, + GPBField_Kind_TypeDouble, + GPBField_Kind_TypeFloat, + GPBField_Kind_TypeInt64, + GPBField_Kind_TypeUint64, + GPBField_Kind_TypeInt32, + GPBField_Kind_TypeFixed64, + GPBField_Kind_TypeFixed32, + GPBField_Kind_TypeBool, + GPBField_Kind_TypeString, + GPBField_Kind_TypeGroup, + GPBField_Kind_TypeMessage, + GPBField_Kind_TypeBytes, + GPBField_Kind_TypeUint32, + GPBField_Kind_TypeEnum, + GPBField_Kind_TypeSfixed32, + GPBField_Kind_TypeSfixed64, + GPBField_Kind_TypeSint32, + GPBField_Kind_TypeSint64, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Kind) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBField_Kind_IsValidValue + flags:GPBEnumDescriptorInitializationFlag_None]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBField_Kind_IsValidValue(int32_t value__) { + switch (value__) { + case GPBField_Kind_TypeUnknown: + case GPBField_Kind_TypeDouble: + case GPBField_Kind_TypeFloat: + case GPBField_Kind_TypeInt64: + case GPBField_Kind_TypeUint64: + case GPBField_Kind_TypeInt32: + case GPBField_Kind_TypeFixed64: + case GPBField_Kind_TypeFixed32: + case GPBField_Kind_TypeBool: + case GPBField_Kind_TypeString: + case GPBField_Kind_TypeGroup: + case GPBField_Kind_TypeMessage: + case GPBField_Kind_TypeBytes: + case GPBField_Kind_TypeUint32: + case GPBField_Kind_TypeEnum: + case GPBField_Kind_TypeSfixed32: + case GPBField_Kind_TypeSfixed64: + case GPBField_Kind_TypeSint32: + case GPBField_Kind_TypeSint64: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GPBField_Cardinality + +GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "CardinalityUnknown\000CardinalityOptional\000C" + "ardinalityRequired\000CardinalityRepeated\000"; + static const int32_t values[] = { + GPBField_Cardinality_CardinalityUnknown, + GPBField_Cardinality_CardinalityOptional, + GPBField_Cardinality_CardinalityRequired, + GPBField_Cardinality_CardinalityRepeated, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Cardinality) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GPBField_Cardinality_IsValidValue + flags:GPBEnumDescriptorInitializationFlag_None]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GPBField_Cardinality_IsValidValue(int32_t value__) { + switch (value__) { + case GPBField_Cardinality_CardinalityUnknown: + case GPBField_Cardinality_CardinalityOptional: + case GPBField_Cardinality_CardinalityRequired: + case GPBField_Cardinality_CardinalityRepeated: + return YES; + default: + return NO; + } +} + #pragma mark - GPBType @implementation GPBType @@ -367,122 +483,6 @@ void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) { GPBSetMessageRawEnumField(message, field, value); } -#pragma mark - Enum GPBField_Kind - -GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void) { - static _Atomic(GPBEnumDescriptor*) descriptor = nil; - if (!descriptor) { - static const char *valueNames = - "TypeUnknown\000TypeDouble\000TypeFloat\000TypeInt" - "64\000TypeUint64\000TypeInt32\000TypeFixed64\000Type" - "Fixed32\000TypeBool\000TypeString\000TypeGroup\000Ty" - "peMessage\000TypeBytes\000TypeUint32\000TypeEnum\000" - "TypeSfixed32\000TypeSfixed64\000TypeSint32\000Typ" - "eSint64\000"; - static const int32_t values[] = { - GPBField_Kind_TypeUnknown, - GPBField_Kind_TypeDouble, - GPBField_Kind_TypeFloat, - GPBField_Kind_TypeInt64, - GPBField_Kind_TypeUint64, - GPBField_Kind_TypeInt32, - GPBField_Kind_TypeFixed64, - GPBField_Kind_TypeFixed32, - GPBField_Kind_TypeBool, - GPBField_Kind_TypeString, - GPBField_Kind_TypeGroup, - GPBField_Kind_TypeMessage, - GPBField_Kind_TypeBytes, - GPBField_Kind_TypeUint32, - GPBField_Kind_TypeEnum, - GPBField_Kind_TypeSfixed32, - GPBField_Kind_TypeSfixed64, - GPBField_Kind_TypeSint32, - GPBField_Kind_TypeSint64, - }; - GPBEnumDescriptor *worker = - [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Kind) - valueNames:valueNames - values:values - count:(uint32_t)(sizeof(values) / sizeof(int32_t)) - enumVerifier:GPBField_Kind_IsValidValue - flags:GPBEnumDescriptorInitializationFlag_None]; - GPBEnumDescriptor *expected = nil; - if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { - [worker release]; - } - } - return descriptor; -} - -BOOL GPBField_Kind_IsValidValue(int32_t value__) { - switch (value__) { - case GPBField_Kind_TypeUnknown: - case GPBField_Kind_TypeDouble: - case GPBField_Kind_TypeFloat: - case GPBField_Kind_TypeInt64: - case GPBField_Kind_TypeUint64: - case GPBField_Kind_TypeInt32: - case GPBField_Kind_TypeFixed64: - case GPBField_Kind_TypeFixed32: - case GPBField_Kind_TypeBool: - case GPBField_Kind_TypeString: - case GPBField_Kind_TypeGroup: - case GPBField_Kind_TypeMessage: - case GPBField_Kind_TypeBytes: - case GPBField_Kind_TypeUint32: - case GPBField_Kind_TypeEnum: - case GPBField_Kind_TypeSfixed32: - case GPBField_Kind_TypeSfixed64: - case GPBField_Kind_TypeSint32: - case GPBField_Kind_TypeSint64: - return YES; - default: - return NO; - } -} - -#pragma mark - Enum GPBField_Cardinality - -GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void) { - static _Atomic(GPBEnumDescriptor*) descriptor = nil; - if (!descriptor) { - static const char *valueNames = - "CardinalityUnknown\000CardinalityOptional\000C" - "ardinalityRequired\000CardinalityRepeated\000"; - static const int32_t values[] = { - GPBField_Cardinality_CardinalityUnknown, - GPBField_Cardinality_CardinalityOptional, - GPBField_Cardinality_CardinalityRequired, - GPBField_Cardinality_CardinalityRepeated, - }; - GPBEnumDescriptor *worker = - [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Cardinality) - valueNames:valueNames - values:values - count:(uint32_t)(sizeof(values) / sizeof(int32_t)) - enumVerifier:GPBField_Cardinality_IsValidValue - flags:GPBEnumDescriptorInitializationFlag_None]; - GPBEnumDescriptor *expected = nil; - if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { - [worker release]; - } - } - return descriptor; -} - -BOOL GPBField_Cardinality_IsValidValue(int32_t value__) { - switch (value__) { - case GPBField_Cardinality_CardinalityUnknown: - case GPBField_Cardinality_CardinalityOptional: - case GPBField_Cardinality_CardinalityRequired: - case GPBField_Cardinality_CardinalityRepeated: - return YES; - default: - return NO; - } -} - #pragma mark - GPBEnum @implementation GPBEnum diff --git a/src/google/protobuf/compiler/objectivec/file.cc b/src/google/protobuf/compiler/objectivec/file.cc index b942e40ccc..c2093ddda3 100644 --- a/src/google/protobuf/compiler/objectivec/file.cc +++ b/src/google/protobuf/compiler/objectivec/file.cc @@ -33,11 +33,13 @@ #include #include #include +#include #include #include #include #include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" #include "absl/container/btree_set.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" @@ -68,20 +70,6 @@ std::string BundledFileName(const FileDescriptor* file) { return "GPB" + FilePathBasename(file) + kHeaderExtension; } -// Checks if a message contains any enums definitions (on the message or -// a nested message under it). -bool MessageContainsEnums(const Descriptor* message) { - if (message->enum_type_count() > 0) { - return true; - } - for (int i = 0; i < message->nested_type_count(); i++) { - if (MessageContainsEnums(message->nested_type(i))) { - return true; - } - } - return false; -} - // Checks if a message contains any extension definitions (on the message or // a nested message under it). bool MessageContainsExtensions(const Descriptor* message) { @@ -96,20 +84,6 @@ bool MessageContainsExtensions(const Descriptor* message) { return false; } -// Checks if the file contains any enum definitions (at the root or -// nested under a message). -bool FileContainsEnums(const FileDescriptor* file) { - if (file->enum_type_count() > 0) { - return true; - } - for (int i = 0; i < file->message_type_count(); i++) { - if (MessageContainsEnums(file->message_type(i))) { - return true; - } - } - return false; -} - // Checks if the file contains any extensions definitions (at the root or // nested under a message). bool FileContainsExtensions(const FileDescriptor* file) { @@ -140,6 +114,24 @@ struct FileDescriptorsOrderedByName { } }; +void MakeDescriptors( + const Descriptor* descriptor, const std::string& root_classname, + std::vector>* enum_generators, + std::vector>* extension_generators, + std::vector>* message_generators) { + for (int i = 0; i < descriptor->enum_type_count(); i++) { + enum_generators->emplace_back( + std::make_unique(descriptor->enum_type(i))); + } + for (int i = 0; i < descriptor->nested_type_count(); i++) { + message_generators->emplace_back(std::make_unique( + root_classname, descriptor->nested_type(i))); + message_generators->back()->AddExtensionGenerators(extension_generators); + MakeDescriptors(descriptor->nested_type(i), root_classname, enum_generators, + extension_generators, message_generators); + } +} + } // namespace const FileGenerator::CommonState::MinDepsEntry& @@ -233,18 +225,19 @@ FileGenerator::FileGenerator(const FileDescriptor* file, root_class_name_(FileClassName(file)), is_bundled_proto_(IsProtobufLibraryBundledProtoFile(file)) { for (int i = 0; i < file_->enum_type_count(); i++) { - EnumGenerator* generator = new EnumGenerator(file_->enum_type(i)); - enum_generators_.emplace_back(generator); - } - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator* generator = - new MessageGenerator(root_class_name_, file_->message_type(i)); - message_generators_.emplace_back(generator); + enum_generators_.emplace_back( + std::make_unique(file_->enum_type(i))); } for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator* generator = - new ExtensionGenerator(root_class_name_, file_->extension(i)); - extension_generators_.emplace_back(generator); + extension_generators_.push_back(std::make_unique( + root_class_name_, file_->extension(i))); + } + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_.emplace_back(std::make_unique( + root_class_name_, file_->message_type(i))); + message_generators_.back()->AddExtensionGenerators(&extension_generators_); + MakeDescriptors(file_->message_type(i), root_class_name_, &enum_generators_, + &extension_generators_, &message_generators_); } } @@ -345,10 +338,6 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { generator->GenerateHeader(printer); } - for (const auto& generator : message_generators_) { - generator->GenerateEnumHeader(printer); - } - // For extensions to chain together, the Root gets created even if there // are no extensions. printer->Print( @@ -371,18 +360,20 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { // clang-format off "root_class_name", root_class_name_); - if (!extension_generators_.empty()) { - // The dynamic methods block is only needed if there are extensions. + // The dynamic methods block is only needed if there are extensions that are + // file level scoped (not message scoped). The first file_->extension_count() + // of extension_generators_ are the file scoped ones. + if (file_->extension_count()) { printer->Print( "@interface $root_class_name$ (DynamicMethods)\n", "root_class_name", root_class_name_); - for (const auto& generator : extension_generators_) { - generator->GenerateMembersHeader(printer); + for (int i = 0; i < file_->extension_count(); i++) { + extension_generators_[i]->GenerateMembersHeader(printer); } printer->Print("@end\n\n"); - } // !extension_generators_.empty() + } // file_->extension_count() for (const auto& generator : message_generators_) { generator->GenerateMessageHeader(printer); @@ -412,7 +403,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { PrintFileRuntimePreamble(printer, headers); // Enums use atomic in the generated code, so add the system import as needed. - if (FileContainsEnums(file_)) { + if (!enum_generators_.empty()) { printer->Print( "#import \n" "\n"); @@ -533,7 +524,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { // clang-format on "root_class_name", root_class_name_); - const bool file_contains_extensions = FileContainsExtensions(file_); + const bool file_contains_extensions = !extension_generators_.empty(); // If there were any extensions or this file has any dependencies, output // a registry to override to create the file specific registry. @@ -558,9 +549,6 @@ void FileGenerator::GenerateSource(io::Printer* printer) { for (const auto& generator : extension_generators_) { generator->GenerateStaticVariablesInitialization(printer); } - for (const auto& generator : message_generators_) { - generator->GenerateStaticVariablesInitialization(printer); - } printer->Outdent(); // clang-format off printer->Print( diff --git a/src/google/protobuf/compiler/objectivec/file.h b/src/google/protobuf/compiler/objectivec/file.h index 0637ed0d49..3946a05cf3 100644 --- a/src/google/protobuf/compiler/objectivec/file.h +++ b/src/google/protobuf/compiler/objectivec/file.h @@ -92,6 +92,7 @@ class FileGenerator { std::vector> enum_generators_; std::vector> message_generators_; + // The first file_->extension_count() are the extensions at file level scope. std::vector> extension_generators_; void PrintFileRuntimePreamble( diff --git a/src/google/protobuf/compiler/objectivec/message.cc b/src/google/protobuf/compiler/objectivec/message.cc index 98591c85ee..5a909f672c 100644 --- a/src/google/protobuf/compiler/objectivec/message.cc +++ b/src/google/protobuf/compiler/objectivec/message.cc @@ -40,10 +40,10 @@ #include "absl/container/flat_hash_map.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" -#include "google/protobuf/compiler/objectivec/enum.h" #include "google/protobuf/compiler/objectivec/extension.h" #include "google/protobuf/compiler/objectivec/helpers.h" #include "google/protobuf/compiler/objectivec/names.h" +#include "google/protobuf/compiler/objectivec/oneof.h" #include "google/protobuf/compiler/objectivec/text_format_decode_data.h" #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/io/printer.h" @@ -188,51 +188,30 @@ MessageGenerator::MessageGenerator(const std::string& root_classname, class_name_(ClassName(descriptor_)), deprecated_attribute_(GetOptionalDeprecatedAttribute( descriptor, descriptor->file(), false, true)) { - for (int i = 0; i < descriptor_->extension_count(); i++) { - extension_generators_.emplace_back( - new ExtensionGenerator(class_name_, descriptor_->extension(i))); - } - for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { - OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i)); - oneof_generators_.emplace_back(generator); - } - - for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i)); - enum_generators_.emplace_back(generator); - } - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator* generator = - new MessageGenerator(root_classname_, descriptor_->nested_type(i)); - nested_message_generators_.emplace_back(generator); + oneof_generators_.push_back( + std::make_unique(descriptor_->oneof_decl(i))); } } -void MessageGenerator::GenerateStaticVariablesInitialization( - io::Printer* printer) { - for (const auto& generator : extension_generators_) { - generator->GenerateStaticVariablesInitialization(printer); - } - - for (const auto& generator : nested_message_generators_) { - generator->GenerateStaticVariablesInitialization(printer); +void MessageGenerator::AddExtensionGenerators( + std::vector>* extension_generators) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators->push_back(std::make_unique( + class_name_, descriptor_->extension(i))); + extension_generators_.push_back(extension_generators->back().get()); } } void MessageGenerator::DetermineForwardDeclarations( absl::btree_set* fwd_decls, bool include_external_types) { - if (!IsMapEntryMessage(descriptor_)) { - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* fieldDescriptor = descriptor_->field(i); - field_generators_.get(fieldDescriptor) - .DetermineForwardDeclarations(fwd_decls, include_external_types); - } + if (IsMapEntryMessage(descriptor_)) { + return; } - - for (const auto& generator : nested_message_generators_) { - generator->DetermineForwardDeclarations(fwd_decls, include_external_types); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + field_generators_.get(fieldDescriptor) + .DetermineForwardDeclarations(fwd_decls, include_external_types); } } @@ -246,14 +225,6 @@ void MessageGenerator::DetermineObjectiveCClassDefinitions( } } - for (const auto& generator : extension_generators_) { - generator->DetermineObjectiveCClassDefinitions(fwd_decls); - } - - for (const auto& generator : nested_message_generators_) { - generator->DetermineObjectiveCClassDefinitions(fwd_decls); - } - const Descriptor* containing_descriptor = descriptor_->containing_type(); if (containing_descriptor != nullptr) { std::string containing_class = ClassName(containing_descriptor); @@ -261,47 +232,9 @@ void MessageGenerator::DetermineObjectiveCClassDefinitions( } } -bool MessageGenerator::IncludesOneOfDefinition() const { - if (!oneof_generators_.empty()) { - return true; - } - - for (const auto& generator : nested_message_generators_) { - if (generator->IncludesOneOfDefinition()) { - return true; - } - } - - return false; -} - -void MessageGenerator::GenerateEnumHeader(io::Printer* printer) { - for (const auto& generator : enum_generators_) { - generator->GenerateHeader(printer); - } - - for (const auto& generator : nested_message_generators_) { - generator->GenerateEnumHeader(printer); - } -} - -void MessageGenerator::GenerateExtensionRegistrationSource( - io::Printer* printer) { - for (const auto& generator : extension_generators_) { - generator->GenerateRegistrationSource(printer); - } - - for (const auto& generator : nested_message_generators_) { - generator->GenerateExtensionRegistrationSource(printer); - } -} - void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { // This a a map entry message, just recurse and do nothing directly. if (IsMapEntryMessage(descriptor_)) { - for (const auto& generator : nested_message_generators_) { - generator->GenerateMessageHeader(printer); - } return; } @@ -380,280 +313,268 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { if (descriptor_->extension_count() > 0) { printer->Print("@interface $classname$ (DynamicMethods)\n\n", "classname", class_name_); - for (const auto& generator : extension_generators_) { + for (const auto generator : extension_generators_) { generator->GenerateMembersHeader(printer); } printer->Print("@end\n\n"); } - - for (const auto& generator : nested_message_generators_) { - generator->GenerateMessageHeader(printer); - } } void MessageGenerator::GenerateSource(io::Printer* printer) { - if (!IsMapEntryMessage(descriptor_)) { + if (IsMapEntryMessage(descriptor_)) { + return; + } + printer->Print( + // clang-format off + "#pragma mark - $classname$\n" + "\n", + // clang-format on + "classname", class_name_); + + if (!deprecated_attribute_.empty()) { + // No warnings when compiling the impl of this deprecated class. + // clang-format off printer->Print( - // clang-format off - "#pragma mark - $classname$\n" - "\n", - // clang-format on - "classname", class_name_); + "#pragma clang diagnostic push\n" + "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n" + "\n"); + // clang-format on + } + + printer->Print("@implementation $classname$\n\n", "classname", class_name_); + + for (const auto& generator : oneof_generators_) { + generator->GeneratePropertyImplementation(printer); + } - if (!deprecated_attribute_.empty()) { - // No warnings when compiling the impl of this deprecated class. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GeneratePropertyImplementation(printer); + } + + std::unique_ptr sorted_fields( + SortFieldsByNumber(descriptor_)); + std::unique_ptr size_order_fields( + SortFieldsByStorageSize(descriptor_)); + + std::vector sorted_extensions; + sorted_extensions.reserve(descriptor_->extension_range_count()); + for (int i = 0; i < descriptor_->extension_range_count(); ++i) { + sorted_extensions.push_back(descriptor_->extension_range(i)); + } + + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeOrdering()); + + // Assign has bits: + // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing + // who needs has bits and assigning them. + // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative + // index that groups all the elements in the oneof. + size_t num_has_bits = field_generators_.CalculateHasBits(); + size_t sizeof_has_storage = (num_has_bits + 31) / 32; + if (sizeof_has_storage == 0) { + // In the case where no field needs has bits, don't let the _has_storage_ + // end up as zero length (zero length arrays are sort of a grey area + // since it has to be at the start of the struct). This also ensures a + // field with only oneofs keeps the required negative indices they need. + sizeof_has_storage = 1; + } + // Tell all the fields the oneof base. + for (const auto& generator : oneof_generators_) { + generator->SetOneofIndexBase(sizeof_has_storage); + } + field_generators_.SetOneofIndexBase(sizeof_has_storage); + // sizeof_has_storage needs enough bits for the single fields that aren't in + // any oneof, and then one int32 for each oneof (to store the field number). + sizeof_has_storage += oneof_generators_.size(); + + printer->Print( // clang-format off - printer->Print( - "#pragma clang diagnostic push\n" - "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n" - "\n"); + "\n" + "typedef struct $classname$__storage_ {\n" + " uint32_t _has_storage_[$sizeof_has_storage$];\n", // clang-format on - } - - printer->Print("@implementation $classname$\n\n", "classname", class_name_); + "classname", class_name_, "sizeof_has_storage", + absl::StrCat(sizeof_has_storage)); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(size_order_fields[i]) + .GenerateFieldStorageDeclaration(printer); + } + printer->Outdent(); - for (const auto& generator : oneof_generators_) { - generator->GeneratePropertyImplementation(printer); - } + printer->Print("} $classname$__storage_;\n\n", "classname", class_name_); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GeneratePropertyImplementation(printer); + // clang-format off + printer->Print( + "// This method is threadsafe because it is initially called\n" + "// in +initialize for each subclass.\n" + "+ (GPBDescriptor *)descriptor {\n" + " static GPBDescriptor *descriptor = nil;\n" + " if (!descriptor) {\n"); + // clang-format on + + TextFormatDecodeData text_format_decode_data; + bool has_fields = descriptor_->field_count() > 0; + bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault(); + std::string field_description_type; + if (need_defaults) { + field_description_type = "GPBMessageFieldDescriptionWithDefault"; + } else { + field_description_type = "GPBMessageFieldDescription"; + } + if (has_fields) { + printer->Indent(); + printer->Indent(); + printer->Print("static $field_description_type$ fields[] = {\n", + "field_description_type", field_description_type); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); ++i) { + const FieldGenerator& field_generator = + field_generators_.get(sorted_fields[i]); + field_generator.GenerateFieldDescription(printer, need_defaults); + if (field_generator.needs_textformat_name_support()) { + text_format_decode_data.AddString(sorted_fields[i]->number(), + field_generator.generated_objc_name(), + field_generator.raw_field_name()); + } } + printer->Outdent(); + printer->Print("};\n"); + printer->Outdent(); + printer->Outdent(); + } - std::unique_ptr sorted_fields( - SortFieldsByNumber(descriptor_)); - std::unique_ptr size_order_fields( - SortFieldsByStorageSize(descriptor_)); + absl::flat_hash_map vars; + vars["classname"] = class_name_; + vars["rootclassname"] = root_classname_; + vars["fields"] = has_fields ? "fields" : "NULL"; + if (has_fields) { + vars["fields_count"] = absl::StrCat("(uint32_t)(sizeof(fields) / sizeof(", + field_description_type, "))"); + } else { + vars["fields_count"] = "0"; + } - std::vector sorted_extensions; - sorted_extensions.reserve(descriptor_->extension_range_count()); - for (int i = 0; i < descriptor_->extension_range_count(); ++i) { - sorted_extensions.push_back(descriptor_->extension_range(i)); - } + std::vector init_flags; + init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs"); + init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown"); + init_flags.push_back( + "GPBDescriptorInitializationFlag_ClosedEnumSupportKnown"); + if (need_defaults) { + init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault"); + } + if (descriptor_->options().message_set_wire_format()) { + init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat"); + } + vars["init_flags"] = + BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION, init_flags); - std::sort(sorted_extensions.begin(), sorted_extensions.end(), - ExtensionRangeOrdering()); - - // Assign has bits: - // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing - // who needs has bits and assigning them. - // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative - // index that groups all the elements in the oneof. - size_t num_has_bits = field_generators_.CalculateHasBits(); - size_t sizeof_has_storage = (num_has_bits + 31) / 32; - if (sizeof_has_storage == 0) { - // In the case where no field needs has bits, don't let the _has_storage_ - // end up as zero length (zero length arrays are sort of a grey area - // since it has to be at the start of the struct). This also ensures a - // field with only oneofs keeps the required negative indices they need. - sizeof_has_storage = 1; - } - // Tell all the fields the oneof base. + // clang-format off + printer->Print( + vars, + " GPBDescriptor *localDescriptor =\n" + " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" + " rootClass:[$rootclassname$ class]\n" + " file:$rootclassname$_FileDescriptor()\n" + " fields:$fields$\n" + " fieldCount:$fields_count$\n" + " storageSize:sizeof($classname$__storage_)\n" + " flags:$init_flags$];\n"); + // clang-format on + if (!oneof_generators_.empty()) { + printer->Print(" static const char *oneofs[] = {\n"); for (const auto& generator : oneof_generators_) { - generator->SetOneofIndexBase(sizeof_has_storage); + printer->Print(" \"$name$\",\n", "name", + generator->DescriptorName()); } - field_generators_.SetOneofIndexBase(sizeof_has_storage); - // sizeof_has_storage needs enough bits for the single fields that aren't in - // any oneof, and then one int32 for each oneof (to store the field number). - sizeof_has_storage += oneof_generators_.size(); - printer->Print( // clang-format off - "\n" - "typedef struct $classname$__storage_ {\n" - " uint32_t _has_storage_[$sizeof_has_storage$];\n", + " };\n" + " [localDescriptor setupOneofs:oneofs\n" + " count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n" + " firstHasIndex:$first_has_index$];\n", // clang-format on - "classname", class_name_, "sizeof_has_storage", - absl::StrCat(sizeof_has_storage)); - printer->Indent(); - - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(size_order_fields[i]) - .GenerateFieldStorageDeclaration(printer); - } - printer->Outdent(); - - printer->Print("} $classname$__storage_;\n\n", "classname", class_name_); - + "first_has_index", oneof_generators_[0]->HasIndexAsString()); + } + if (text_format_decode_data.num_entries() != 0) { + const std::string text_format_data_str(text_format_decode_data.Data()); // clang-format off printer->Print( - "// This method is threadsafe because it is initially called\n" - "// in +initialize for each subclass.\n" - "+ (GPBDescriptor *)descriptor {\n" - " static GPBDescriptor *descriptor = nil;\n" - " if (!descriptor) {\n"); + "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" + " static const char *extraTextFormatInfo ="); // clang-format on - - TextFormatDecodeData text_format_decode_data; - bool has_fields = descriptor_->field_count() > 0; - bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault(); - std::string field_description_type; - if (need_defaults) { - field_description_type = "GPBMessageFieldDescriptionWithDefault"; - } else { - field_description_type = "GPBMessageFieldDescription"; - } - if (has_fields) { - printer->Indent(); - printer->Indent(); - printer->Print("static $field_description_type$ fields[] = {\n", - "field_description_type", field_description_type); - printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); ++i) { - const FieldGenerator& field_generator = - field_generators_.get(sorted_fields[i]); - field_generator.GenerateFieldDescription(printer, need_defaults); - if (field_generator.needs_textformat_name_support()) { - text_format_decode_data.AddString( - sorted_fields[i]->number(), field_generator.generated_objc_name(), - field_generator.raw_field_name()); - } - } - printer->Outdent(); - printer->Print("};\n"); - printer->Outdent(); - printer->Outdent(); - } - - absl::flat_hash_map vars; - vars["classname"] = class_name_; - vars["rootclassname"] = root_classname_; - vars["fields"] = has_fields ? "fields" : "NULL"; - if (has_fields) { - vars["fields_count"] = absl::StrCat("(uint32_t)(sizeof(fields) / sizeof(", - field_description_type, "))"); - } else { - vars["fields_count"] = "0"; + static const int kBytesPerLine = 40; // allow for escaping + for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) { + printer->Print("\n \"$data$\"", "data", + EscapeTrigraphs(absl::CEscape( + text_format_data_str.substr(i, kBytesPerLine)))); } - - std::vector init_flags; - init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs"); - init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown"); - init_flags.push_back( - "GPBDescriptorInitializationFlag_ClosedEnumSupportKnown"); - if (need_defaults) { - init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault"); - } - if (descriptor_->options().message_set_wire_format()) { - init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat"); - } - vars["init_flags"] = - BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION, init_flags); - // clang-format off printer->Print( - vars, - " GPBDescriptor *localDescriptor =\n" - " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" - " rootClass:[$rootclassname$ class]\n" - " file:$rootclassname$_FileDescriptor()\n" - " fields:$fields$\n" - " fieldCount:$fields_count$\n" - " storageSize:sizeof($classname$__storage_)\n" - " flags:$init_flags$];\n"); + ";\n" + " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n" + "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"); // clang-format on - if (!oneof_generators_.empty()) { - printer->Print(" static const char *oneofs[] = {\n"); - for (const auto& generator : oneof_generators_) { - printer->Print(" \"$name$\",\n", "name", - generator->DescriptorName()); - } - printer->Print( - // clang-format off - " };\n" - " [localDescriptor setupOneofs:oneofs\n" - " count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n" - " firstHasIndex:$first_has_index$];\n", - // clang-format on - "first_has_index", oneof_generators_[0]->HasIndexAsString()); - } - if (text_format_decode_data.num_entries() != 0) { - const std::string text_format_data_str(text_format_decode_data.Data()); - // clang-format off - printer->Print( - "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" - " static const char *extraTextFormatInfo ="); - // clang-format on - static const int kBytesPerLine = 40; // allow for escaping - for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) { - printer->Print("\n \"$data$\"", "data", - EscapeTrigraphs(absl::CEscape( - text_format_data_str.substr(i, kBytesPerLine)))); - } - // clang-format off - printer->Print( - ";\n" - " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n" - "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"); - // clang-format on - } - if (!sorted_extensions.empty()) { - printer->Print(" static const GPBExtensionRange ranges[] = {\n"); - for (int i = 0; i < sorted_extensions.size(); i++) { - printer->Print(" { .start = $start$, .end = $end$ },\n", "start", - absl::StrCat(sorted_extensions[i]->start), "end", - absl::StrCat(sorted_extensions[i]->end)); - } - // clang-format off - printer->Print( - " };\n" - " [localDescriptor setupExtensionRanges:ranges\n" - " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n"); - // clang-format on - } - if (descriptor_->containing_type() != nullptr) { - std::string containing_class = ClassName(descriptor_->containing_type()); - std::string parent_class_ref = ObjCClass(containing_class); - printer->Print( - // clang-format off - " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n", - // clang-format on - "parent_class_ref", parent_class_ref); - } - std::string suffix_added; - ClassName(descriptor_, &suffix_added); - if (!suffix_added.empty()) { - printer->Print( - " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n", - "suffix", suffix_added); + } + if (!sorted_extensions.empty()) { + printer->Print(" static const GPBExtensionRange ranges[] = {\n"); + for (int i = 0; i < sorted_extensions.size(); i++) { + printer->Print(" { .start = $start$, .end = $end$ },\n", "start", + absl::StrCat(sorted_extensions[i]->start), "end", + absl::StrCat(sorted_extensions[i]->end)); } // clang-format off printer->Print( - " #if defined(DEBUG) && DEBUG\n" - " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" - " #endif // DEBUG\n" - " descriptor = localDescriptor;\n" - " }\n" - " return descriptor;\n" - "}\n\n" - "@end\n\n"); + " };\n" + " [localDescriptor setupExtensionRanges:ranges\n" + " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n"); + // clang-format on + } + if (descriptor_->containing_type() != nullptr) { + std::string containing_class = ClassName(descriptor_->containing_type()); + std::string parent_class_ref = ObjCClass(containing_class); + printer->Print( + // clang-format off + " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n", + // clang-format on + "parent_class_ref", parent_class_ref); + } + std::string suffix_added; + ClassName(descriptor_, &suffix_added); + if (!suffix_added.empty()) { + printer->Print( + " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n", + "suffix", suffix_added); + } + // clang-format off + printer->Print( + " #if defined(DEBUG) && DEBUG\n" + " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" + " #endif // DEBUG\n" + " descriptor = localDescriptor;\n" + " }\n" + " return descriptor;\n" + "}\n\n" + "@end\n\n"); + // clang-format on + + if (!deprecated_attribute_.empty()) { + // clang-format off + printer->Print( + "#pragma clang diagnostic pop\n" + "\n"); // clang-format on - - if (!deprecated_attribute_.empty()) { - // clang-format off - printer->Print( - "#pragma clang diagnostic pop\n" - "\n"); - // clang-format on - } - - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateCFunctionImplementations(printer); - } - - for (const auto& generator : oneof_generators_) { - generator->GenerateClearFunctionImplementation(printer); - } } - for (const auto& generator : enum_generators_) { - generator->GenerateSource(printer); + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateCFunctionImplementations(printer); } - for (const auto& generator : nested_message_generators_) { - generator->GenerateSource(printer); + for (const auto& generator : oneof_generators_) { + generator->GenerateClearFunctionImplementation(printer); } } diff --git a/src/google/protobuf/compiler/objectivec/message.h b/src/google/protobuf/compiler/objectivec/message.h index 59ccd071ba..f7ae1453c1 100644 --- a/src/google/protobuf/compiler/objectivec/message.h +++ b/src/google/protobuf/compiler/objectivec/message.h @@ -47,7 +47,6 @@ namespace compiler { namespace objectivec { class ExtensionGenerator; -class EnumGenerator; class MessageGenerator { public: @@ -58,18 +57,18 @@ class MessageGenerator { MessageGenerator(const MessageGenerator&) = delete; MessageGenerator& operator=(const MessageGenerator&) = delete; - void GenerateStaticVariablesInitialization(io::Printer* printer); - void GenerateEnumHeader(io::Printer* printer); + void AddExtensionGenerators( + std::vector>* extension_generators); + void GenerateMessageHeader(io::Printer* printer); void GenerateSource(io::Printer* printer); - void GenerateExtensionRegistrationSource(io::Printer* printer); void DetermineObjectiveCClassDefinitions( absl::btree_set* fwd_decls); void DetermineForwardDeclarations(absl::btree_set* fwd_decls, bool include_external_types); // Checks if the message or a nested message includes a oneof definition. - bool IncludesOneOfDefinition() const; + bool IncludesOneOfDefinition() const { return !oneof_generators_.empty(); } private: void GenerateParseFromMethodsHeader(io::Printer* printer); @@ -88,9 +87,7 @@ class MessageGenerator { FieldGeneratorMap field_generators_; const std::string class_name_; const std::string deprecated_attribute_; - std::vector> extension_generators_; - std::vector> enum_generators_; - std::vector> nested_message_generators_; + std::vector extension_generators_; std::vector> oneof_generators_; };