@ -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 ) ;
}
}