[ObjC] Move all Message, Enum, & Extension Generators up to the File.

Create/Collect all the MessageGenerators/EnumGenerators/ExtensionGeneators up at
the FileGenerator level and remove the need for some helpers and need for
generation apis to recurse through the generators.

The only change to the .pbobjc.m files is positionally where the enum support
for nested enums appears, it now is the same order as it was in the .pbobjc.h
files instead of being closer the the type it was nested in.

PiperOrigin-RevId: 491343515
pull/11051/head
Protobuf Team Bot 2 years ago committed by Copybara-Service
parent 4ac90bbb69
commit 64d3eeb1b3
  1. 232
      objectivec/GPBType.pbobjc.m
  2. 92
      src/google/protobuf/compiler/objectivec/file.cc
  3. 1
      src/google/protobuf/compiler/objectivec/file.h
  4. 559
      src/google/protobuf/compiler/objectivec/message.cc
  5. 13
      src/google/protobuf/compiler/objectivec/message.h

@ -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

@ -33,11 +33,13 @@
#include <algorithm>
#include <iostream>
#include <iterator>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#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<std::unique_ptr<EnumGenerator>>* enum_generators,
std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators,
std::vector<std::unique_ptr<MessageGenerator>>* message_generators) {
for (int i = 0; i < descriptor->enum_type_count(); i++) {
enum_generators->emplace_back(
std::make_unique<EnumGenerator>(descriptor->enum_type(i)));
}
for (int i = 0; i < descriptor->nested_type_count(); i++) {
message_generators->emplace_back(std::make_unique<MessageGenerator>(
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<EnumGenerator>(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<ExtensionGenerator>(
root_class_name_, file_->extension(i)));
}
for (int i = 0; i < file_->message_type_count(); i++) {
message_generators_.emplace_back(std::make_unique<MessageGenerator>(
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 <stdatomic.h>\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(

@ -92,6 +92,7 @@ class FileGenerator {
std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
std::vector<std::unique_ptr<MessageGenerator>> message_generators_;
// The first file_->extension_count() are the extensions at file level scope.
std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
void PrintFileRuntimePreamble(

@ -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<OneofGenerator>(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<std::unique_ptr<ExtensionGenerator>>* extension_generators) {
for (int i = 0; i < descriptor_->extension_count(); i++) {
extension_generators->push_back(std::make_unique<ExtensionGenerator>(
class_name_, descriptor_->extension(i)));
extension_generators_.push_back(extension_generators->back().get());
}
}
void MessageGenerator::DetermineForwardDeclarations(
absl::btree_set<std::string>* 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<const FieldDescriptor*[]> sorted_fields(
SortFieldsByNumber(descriptor_));
std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
SortFieldsByStorageSize(descriptor_));
std::vector<const Descriptor::ExtensionRange*> 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<const FieldDescriptor*[]> sorted_fields(
SortFieldsByNumber(descriptor_));
std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
SortFieldsByStorageSize(descriptor_));
absl::flat_hash_map<absl::string_view, std::string> 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<const Descriptor::ExtensionRange*> 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<std::string> 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<absl::string_view, std::string> 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<std::string> 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);
}
}

@ -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<std::unique_ptr<ExtensionGenerator>>* extension_generators);
void GenerateMessageHeader(io::Printer* printer);
void GenerateSource(io::Printer* printer);
void GenerateExtensionRegistrationSource(io::Printer* printer);
void DetermineObjectiveCClassDefinitions(
absl::btree_set<std::string>* fwd_decls);
void DetermineForwardDeclarations(absl::btree_set<std::string>* 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<std::unique_ptr<ExtensionGenerator>> extension_generators_;
std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
std::vector<std::unique_ptr<MessageGenerator>> nested_message_generators_;
std::vector<ExtensionGenerator*> extension_generators_;
std::vector<std::unique_ptr<OneofGenerator>> oneof_generators_;
};

Loading…
Cancel
Save