Commit 74956e1c authored by Dave MacLachlan's avatar Dave MacLachlan Committed by Thomas Van Lenten

Use references to Objective C classes instead of looking classes up by name.

This should reduce binary size slightly, small performance improvement, and improve linkage by forcing references to all used classes.

Note that this maintains backwards compatibility for sources generated by older protoc for the time being. If you want the benefits
you will need to recompile your protos with the newer protoc.
parent 948740bc
......@@ -687,6 +687,7 @@ objectivec_EXTRA_DIST= \
objectivec/Tests/GPBDictionaryTests.m \
objectivec/Tests/GPBDictionaryTests.pddm \
objectivec/Tests/GPBExtensionRegistryTest.m \
objectivec/Tests/GPBMessageTests+ClassNames.m \
objectivec/Tests/GPBMessageTests+Merge.m \
objectivec/Tests/GPBMessageTests+Runtime.m \
objectivec/Tests/GPBMessageTests+Serialization.m \
......
......@@ -44,7 +44,7 @@
// The addresses of these variables are used as keys for objc_getAssociatedObject.
static const char kTextFormatExtraValueKey = 0;
static const char kParentClassNameValueKey = 0;
static const char kParentClassValueKey = 0;
static const char kClassNameSuffixKey = 0;
// Utility function to generate selectors on the fly.
......@@ -126,6 +126,8 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
GPBFileSyntax syntax = file.syntax;
BOOL fieldsIncludeDefault =
(flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0;
BOOL usesClassRefs =
(flags & GPBDescriptorInitializationFlag_UsesClassRefs) != 0;
void *desc;
for (uint32_t i = 0; i < fieldCount; ++i) {
......@@ -143,6 +145,7 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
GPBFieldDescriptor *fieldDescriptor =
[[GPBFieldDescriptor alloc] initWithFieldDescription:desc
includesDefault:fieldsIncludeDefault
usesClassRefs:usesClassRefs
syntax:syntax];
[fields addObject:fieldDescriptor];
[fieldDescriptor release];
......@@ -217,15 +220,19 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
extensionRangesCount_ = count;
}
- (void)setupContainingMessageClass:(Class)messageClass {
objc_setAssociatedObject(self, &kParentClassValueKey,
messageClass,
OBJC_ASSOCIATION_ASSIGN);
}
- (void)setupContainingMessageClassName:(const char *)msgClassName {
// Note: Only fetch the class here, can't send messages to it because
// that could cause cycles back to this class within +initialize if
// two messages have each other in fields (i.e. - they build a graph).
NSAssert(objc_getClass(msgClassName), @"Class %s not defined", msgClassName);
NSValue *parentNameValue = [NSValue valueWithPointer:msgClassName];
objc_setAssociatedObject(self, &kParentClassNameValueKey,
parentNameValue,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
Class clazz = objc_getClass(msgClassName);
NSAssert(clazz, @"Class %s not defined", msgClassName);
[self setupContainingMessageClass:clazz];
}
- (void)setupMessageClassNameSuffix:(NSString *)suffix {
......@@ -241,14 +248,7 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
}
- (GPBDescriptor *)containingType {
NSValue *parentNameValue =
objc_getAssociatedObject(self, &kParentClassNameValueKey);
if (!parentNameValue) {
return nil;
}
const char *parentName = [parentNameValue pointerValue];
Class parentClass = objc_getClass(parentName);
NSAssert(parentClass, @"Class %s not defined", parentName);
Class parentClass = objc_getAssociatedObject(self, &kParentClassValueKey);
return [parentClass descriptor];
}
......@@ -487,6 +487,7 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
- (instancetype)initWithFieldDescription:(void *)description
includesDefault:(BOOL)includesDefault
usesClassRefs:(BOOL)usesClassRefs
syntax:(GPBFileSyntax)syntax {
if ((self = [super init])) {
GPBMessageFieldDescription *coreDesc;
......@@ -524,12 +525,17 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
// Extra type specific data.
if (isMessage) {
const char *className = coreDesc->dataTypeSpecific.className;
// Note: Only fetch the class here, can't send messages to it because
// that could cause cycles back to this class within +initialize if
// two messages have each other in fields (i.e. - they build a graph).
msgClass_ = objc_getClass(className);
NSAssert(msgClass_, @"Class %s not defined", className);
if (usesClassRefs) {
msgClass_ = coreDesc->dataTypeSpecific.clazz;
} else {
// Backwards compatibility for sources generated with older protoc.
const char *className = coreDesc->dataTypeSpecific.className;
msgClass_ = objc_getClass(className);
NSAssert(msgClass_, @"Class %s not defined", className);
}
} else if (dataType == GPBDataTypeEnum) {
if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) {
enumHandling_.enumDescriptor_ =
......@@ -561,6 +567,15 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
return self;
}
- (instancetype)initWithFieldDescription:(void *)description
includesDefault:(BOOL)includesDefault
syntax:(GPBFileSyntax)syntax {
return [self initWithFieldDescription:description
includesDefault:includesDefault
usesClassRefs:NO
syntax:syntax];
}
- (void)dealloc {
if (description_->dataType == GPBDataTypeBytes &&
!(description_->flags & GPBFieldRepeated)) {
......@@ -957,33 +972,32 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
GPBGenericValue defaultValue_;
}
@synthesize containingMessageClass = containingMessageClass_;
- (instancetype)initWithExtensionDescription:
(GPBExtensionDescription *)description {
- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc
usesClassRefs:(BOOL)usesClassRefs {
if ((self = [super init])) {
description_ = description;
#if defined(DEBUG) && DEBUG
const char *className = description->messageOrGroupClassName;
if (className) {
NSAssert(objc_lookUpClass(className) != Nil,
@"Class %s not defined", className);
}
#endif
description_ = desc;
if (!usesClassRefs) {
// Legacy without class ref support.
const char *className = description_->messageOrGroupClass.name;
if (className) {
Class clazz = objc_lookUpClass(className);
NSAssert(clazz != Nil, @"Class %s not defined", className);
description_->messageOrGroupClass.clazz = clazz;
}
if (description->extendedClass) {
Class containingClass = objc_lookUpClass(description->extendedClass);
NSAssert(containingClass, @"Class %s not defined",
description->extendedClass);
containingMessageClass_ = containingClass;
const char *extendedClassName = description_->extendedClass.name;
if (extendedClassName) {
Class clazz = objc_lookUpClass(extendedClassName);
NSAssert(clazz, @"Class %s not defined", extendedClassName);
description_->extendedClass.clazz = clazz;
}
}
GPBDataType type = description_->dataType;
if (type == GPBDataTypeBytes) {
// Data stored as a length prefixed c-string in descriptor records.
const uint8_t *bytes =
(const uint8_t *)description->defaultValue.valueData;
(const uint8_t *)description_->defaultValue.valueData;
if (bytes) {
uint32_t length;
memcpy(&length, bytes, sizeof(length));
......@@ -998,12 +1012,16 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
// aren't common, we avoid the hit startup hit and it avoid initialization
// order issues.
} else {
defaultValue_ = description->defaultValue;
defaultValue_ = description_->defaultValue;
}
}
return self;
}
- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc {
return [self initWithExtensionDescription:desc usesClassRefs:NO];
}
- (void)dealloc {
if ((description_->dataType == GPBDataTypeBytes) &&
!GPBExtensionIsRepeated(description_)) {
......@@ -1055,7 +1073,11 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
}
- (Class)msgClass {
return objc_getClass(description_->messageOrGroupClassName);
return description_->messageOrGroupClass.clazz;
}
- (Class)containingMessageClass {
return description_->extendedClass.clazz;
}
- (GPBEnumDescriptor *)enumDescriptor {
......
......@@ -80,7 +80,11 @@ typedef struct GPBMessageFieldDescription {
// Name of ivar.
const char *name;
union {
const char *className; // Name for message class.
// className is deprecated and will be removed in favor of clazz.
// kept around right now for backwards compatibility.
// clazz is used iff GPBDescriptorInitializationFlag_UsesClassRefs is set.
char *className; // Name of the class of the message.
Class clazz; // Class of the message.
// For enums only: If EnumDescriptors are compiled in, it will be that,
// otherwise it will be the verifier.
GPBEnumDescriptorFunc enumDescFunc;
......@@ -123,8 +127,14 @@ typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) {
typedef struct GPBExtensionDescription {
GPBGenericValue defaultValue;
const char *singletonName;
const char *extendedClass;
const char *messageOrGroupClassName;
union {
const char *name;
Class clazz;
} extendedClass;
union {
const char *name;
Class clazz;
} messageOrGroupClass;
GPBEnumDescriptorFunc enumDescriptorFunc;
int32_t fieldNumber;
GPBDataType dataType;
......@@ -135,6 +145,11 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
GPBDescriptorInitializationFlag_None = 0,
GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0,
GPBDescriptorInitializationFlag_WireFormat = 1 << 1,
// This is used as a stopgap as we move from using class names to class
// references. The runtime needs to support both until we allow a
// breaking change in the runtime.
GPBDescriptorInitializationFlag_UsesClassRefs = 1 << 2,
};
@interface GPBDescriptor () {
......@@ -168,9 +183,12 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
firstHasIndex:(int32_t)firstHasIndex;
- (void)setupExtraTextInfo:(const char *)extraTextFormatInfo;
- (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count;
- (void)setupContainingMessageClassName:(const char *)msgClassName;
- (void)setupContainingMessageClass:(Class)msgClass;
- (void)setupMessageClassNameSuffix:(NSString *)suffix;
// Deprecated. Use setupContainingMessageClass instead.
- (void)setupContainingMessageClassName:(const char *)msgClassName;
@end
@interface GPBFileDescriptor ()
......@@ -206,7 +224,15 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
// description has to be long lived, it is held as a raw pointer.
- (instancetype)initWithFieldDescription:(void *)description
includesDefault:(BOOL)includesDefault
usesClassRefs:(BOOL)usesClassRefs
syntax:(GPBFileSyntax)syntax;
// Deprecated. Equivalent to calling above with `usesClassRefs = NO`.
- (instancetype)initWithFieldDescription:(void *)description
includesDefault:(BOOL)includesDefault
syntax:(GPBFileSyntax)syntax;
@end
@interface GPBEnumDescriptor ()
......@@ -246,8 +272,11 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
@property(nonatomic, readonly) GPBWireFormat alternateWireType;
// description has to be long lived, it is held as a raw pointer.
- (instancetype)initWithExtensionDescription:
(GPBExtensionDescription *)description;
- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc
usesClassRefs:(BOOL)usesClassRefs;
// Deprecated. Calls above with `usesClassRefs = NO`
- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc;
- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other;
@end
......
......@@ -142,3 +142,10 @@ typedef struct GPBExtensionRange {
/** Exclusive. */
uint32_t end;
} GPBExtensionRange;
/**
A type to represent a reference to an Objective C class.
This is actually an `objc_class` but the runtime headers will not allow us to
reference `objc_class`.
*/
typedef struct GPBObjcClassReference GPBObjcClassReference;
......@@ -35,6 +35,7 @@
8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; };
8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; };
8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
8BFF9D1A23AD582300E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */; };
F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC2B1A8D444600FCC765 /* GPBArray.m */; };
F401DC331A8E5C0200FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */; };
F40EE4AB206BF8B90071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE488206BF8B00071091A /* GPBCompileTest01.m */; };
......@@ -181,6 +182,7 @@
8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = "<group>"; };
8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = "<group>"; };
8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = "<group>"; };
8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = "<group>"; };
F401DC2A1A8D444600FCC765 /* GPBArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBArray.h; sourceTree = "<group>"; };
F401DC2B1A8D444600FCC765 /* GPBArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArray.m; sourceTree = "<group>"; };
F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = "<group>"; };
......@@ -485,6 +487,7 @@
7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */,
F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */,
F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */,
8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */,
F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */,
F4B51B1D1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm */,
F41C175C1833D3310064ED4D /* GPBPerfTests.m */,
......@@ -656,6 +659,7 @@
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
en,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
......@@ -770,6 +774,7 @@
8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */,
F40EE50C206C06640071091A /* GPBCompileTest25.m in Sources */,
F4584D821ECCB52A00803AB6 /* GPBExtensionRegistryTest.m in Sources */,
8BFF9D1A23AD582300E63E32 /* GPBMessageTests+ClassNames.m in Sources */,
5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */,
F40EE4AC206BF8B90071091A /* GPBCompileTest02.m in Sources */,
......
......@@ -36,6 +36,7 @@
8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; };
8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; };
8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
8BFF9D1C23AD593C00E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */; };
F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */; };
F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CD206BF9170071091A /* GPBCompileTest01.m */; };
F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C6206BF9170071091A /* GPBCompileTest02.m */; };
......@@ -183,6 +184,7 @@
8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = "<group>"; };
8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = "<group>"; };
8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = "<group>"; };
8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = "<group>"; };
F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = "<group>"; };
F40EE4C2206BF9160071091A /* GPBCompileTest08.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest08.m; sourceTree = "<group>"; };
F40EE4C3206BF9160071091A /* GPBCompileTest04.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest04.m; sourceTree = "<group>"; };
......@@ -491,6 +493,7 @@
7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */,
F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */,
F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */,
8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */,
F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */,
F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */,
F41C175C1833D3310064ED4D /* GPBPerfTests.m */,
......@@ -663,6 +666,7 @@
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
en,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
......@@ -777,6 +781,7 @@
8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */,
F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */,
F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */,
8BFF9D1C23AD593C00E63E32 /* GPBMessageTests+ClassNames.m in Sources */,
5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */,
F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */,
......@@ -851,6 +856,7 @@
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
ENABLE_BITCODE = YES;
FRAMEWORK_SEARCH_PATHS = (
"\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
"$(inherited)",
......@@ -883,6 +889,7 @@
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
ENABLE_BITCODE = YES;
FRAMEWORK_SEARCH_PATHS = (
"\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
"$(inherited)",
......
......@@ -36,6 +36,7 @@
8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; };
8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; };
8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
8BFF9D1E23AD599400E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */; };
F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */; };
F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CD206BF9170071091A /* GPBCompileTest01.m */; };
F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C6206BF9170071091A /* GPBCompileTest02.m */; };
......@@ -183,6 +184,7 @@
8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = "<group>"; };
8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = "<group>"; };
8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = "<group>"; };
8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = "<group>"; };
F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = "<group>"; };
F40EE4C2206BF9160071091A /* GPBCompileTest08.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest08.m; sourceTree = "<group>"; };
F40EE4C3206BF9160071091A /* GPBCompileTest04.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest04.m; sourceTree = "<group>"; };
......@@ -491,6 +493,7 @@
7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */,
F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */,
F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */,
8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */,
F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */,
F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */,
F41C175C1833D3310064ED4D /* GPBPerfTests.m */,
......@@ -663,6 +666,7 @@
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
en,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
......@@ -777,6 +781,7 @@
8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */,
F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */,
F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */,
8BFF9D1E23AD599400E63E32 /* GPBMessageTests+ClassNames.m in Sources */,
5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */,
F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */,
......
// Protocol Buffers - Google's data interchange format
// Copyright 2015 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import "GPBTestUtilities.h"
#import <objc/runtime.h>
#import "GPBDescriptor_PackagePrivate.h"
#import "GPBExtensionRegistry.h"
#import "GPBMessage.h"
#import "GPBRootObject_PackagePrivate.h"
// Support classes for tests using old class name (vs classrefs) interfaces.
@interface MessageLackingClazzRoot : GPBRootObject
@end
@interface MessageLackingClazzRoot (DynamicMethods)
+ (GPBExtensionDescriptor *)ext1;
@end
@interface MessageLackingClazz : GPBMessage
@property(copy, nonatomic) NSString *foo;
@end
@implementation MessageLackingClazz
@dynamic foo;
typedef struct MessageLackingClazz_storage_ {
uint32_t _has_storage_[1];
NSString *foo;
} MessageLackingClazz_storage_;
+ (GPBDescriptor *)descriptor {
static GPBDescriptor *descriptor = nil;
if (!descriptor) {
static GPBMessageFieldDescription fields[] = {
{
.name = "foo",
.dataTypeSpecific.className = "NSString",
.number = 1,
.hasIndex = 0,
.offset = (uint32_t)offsetof(MessageLackingClazz_storage_, foo),
.flags = (GPBFieldFlags)(GPBFieldOptional),
.dataType = GPBDataTypeMessage,
},
};
GPBFileDescriptor *desc =
[[[GPBFileDescriptor alloc] initWithPackage:@"test"
objcPrefix:@"TEST"
syntax:GPBFileSyntaxProto3] autorelease];
// GPBDescriptorInitializationFlag_UsesClassRefs intentionally not set here
descriptor =
[GPBDescriptor allocDescriptorForClass:[MessageLackingClazz class]
rootClass:[MessageLackingClazzRoot class]
file:desc
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(MessageLackingClazz_storage_)
flags:GPBDescriptorInitializationFlag_None];
[descriptor setupContainingMessageClassName:"MessageLackingClazz"];
}
return descriptor;
}
@end
@implementation MessageLackingClazzRoot
+ (GPBExtensionRegistry*)extensionRegistry {
// This is called by +initialize so there is no need to worry
// about thread safety and initialization of registry.
static GPBExtensionRegistry* registry = nil;
if (!registry) {
registry = [[GPBExtensionRegistry alloc] init];
static GPBExtensionDescription descriptions[] = {
{
.defaultValue.valueMessage = NULL,
.singletonName = "MessageLackingClazzRoot_ext1",
.extendedClass.name = "MessageLackingClazz",
.messageOrGroupClass.name = "MessageLackingClazz",
.enumDescriptorFunc = NULL,
.fieldNumber = 1,
.dataType = GPBDataTypeMessage,
// GPBExtensionUsesClazz Intentionally not set
.options = 0,
},
};
for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {
// Intentionall using `-initWithExtensionDescription:` and not `
// -initWithExtensionDescription:usesClassRefs:` to test backwards
// compatibility
GPBExtensionDescriptor *extension =
[[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];
[registry addExtension:extension];
[self globallyRegisterExtension:extension];
[extension release];
}
// None of the imports (direct or indirect) defined extensions, so no need to add
// them to this registry.
}
return registry;
}
@end
@interface MessageClassNameTests : GPBTestCase
@end
@implementation MessageClassNameTests
- (void)testClassNameSupported {
// This tests backwards compatibility to make sure we support older sources
// that use class names instead of references.
GPBDescriptor *desc = [MessageLackingClazz descriptor];
GPBFieldDescriptor *fieldDesc = [desc fieldWithName:@"foo"];
XCTAssertEqualObjects(fieldDesc.msgClass, [NSString class]);
}
- (void)testSetupContainingMessageClassNameSupported {
// This tests backwards compatibility to make sure we support older sources
// that use class names instead of references.
GPBDescriptor *desc = [MessageLackingClazz descriptor];
GPBDescriptor *container = [desc containingType];
XCTAssertEqualObjects(container.messageClass, [MessageLackingClazz class]);
}
- (void)testExtensionsNameSupported {
// This tests backwards compatibility to make sure we support older sources
// that use class names instead of references.
GPBExtensionDescriptor *desc = [MessageLackingClazzRoot ext1];
Class containerClass = [desc containingMessageClass];
XCTAssertEqualObjects(containerClass, [MessageLackingClazz class]);
Class msgClass = [desc msgClass];
XCTAssertEqualObjects(msgClass, [MessageLackingClazz class]);
}
@end
......@@ -68,7 +68,7 @@ typedef struct GPBAny__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "typeURL",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBAny_FieldNumber_TypeURL,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBAny__storage_, typeURL),
......@@ -77,7 +77,7 @@ typedef struct GPBAny__storage_ {
},
{
.name = "value",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBAny_FieldNumber_Value,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBAny__storage_, value),
......@@ -92,7 +92,7 @@ typedef struct GPBAny__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBAny__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
static const char *extraTextFormatInfo =
"\001\001\004\241!!\000";
......
......@@ -26,6 +26,18 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"
#pragma mark - Objective C Class references
// This somewhat arcane code forces linkage of classes from static archives by
// adding a concrete reference to the classes.
// We don't use `[Foo class]` because we need a static value for our initializer.
// This also has the added benefit of reducing size in that we don't have to
// encode the class names and look them up at runtime.
extern const GPBObjcClassReference OBJC_CLASS_$_GPBMethod;
extern const GPBObjcClassReference OBJC_CLASS_$_GPBMixin;
extern const GPBObjcClassReference OBJC_CLASS_$_GPBOption;
extern const GPBObjcClassReference OBJC_CLASS_$_GPBSourceContext;
#pragma mark - GPBApiRoot
......@@ -82,7 +94,7 @@ typedef struct GPBApi__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "name",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBApi_FieldNumber_Name,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBApi__storage_, name),
......@@ -91,7 +103,7 @@ typedef struct GPBApi__storage_ {
},
{
.name = "methodsArray",
.dataTypeSpecific.className = GPBStringifySymbol(GPBMethod),
.dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBMethod),
.number = GPBApi_FieldNumber_MethodsArray,
.hasIndex = GPBNoHasBit,
.offset = (uint32_t)offsetof(GPBApi__storage_, methodsArray),
......@@ -100,7 +112,7 @@ typedef struct GPBApi__storage_ {
},
{
.name = "optionsArray",
.dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
.dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBOption),
.number = GPBApi_FieldNumber_OptionsArray,
.hasIndex = GPBNoHasBit,
.offset = (uint32_t)offsetof(GPBApi__storage_, optionsArray),
......@@ -109,7 +121,7 @@ typedef struct GPBApi__storage_ {
},
{
.name = "version",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBApi_FieldNumber_Version,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBApi__storage_, version),
......@@ -118,7 +130,7 @@ typedef struct GPBApi__storage_ {
},
{
.name = "sourceContext",
.dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext),
.dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBSourceContext),
.number = GPBApi_FieldNumber_SourceContext,
.hasIndex = 2,
.offset = (uint32_t)offsetof(GPBApi__storage_, sourceContext),
......@@ -127,7 +139,7 @@ typedef struct GPBApi__storage_ {
},
{
.name = "mixinsArray",
.dataTypeSpecific.className = GPBStringifySymbol(GPBMixin),
.dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBMixin),
.number = GPBApi_FieldNumber_MixinsArray,
.hasIndex = GPBNoHasBit,
.offset = (uint32_t)offsetof(GPBApi__storage_, mixinsArray),
......@@ -151,7 +163,7 @@ typedef struct GPBApi__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBApi__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......@@ -203,7 +215,7 @@ typedef struct GPBMethod__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "name",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBMethod_FieldNumber_Name,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBMethod__storage_, name),
......@@ -212,7 +224,7 @@ typedef struct GPBMethod__storage_ {
},
{
.name = "requestTypeURL",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBMethod_FieldNumber_RequestTypeURL,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL),
......@@ -221,7 +233,7 @@ typedef struct GPBMethod__storage_ {
},
{
.name = "requestStreaming",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBMethod_FieldNumber_RequestStreaming,
.hasIndex = 2,
.offset = 3, // Stored in _has_storage_ to save space.
......@@ -230,7 +242,7 @@ typedef struct GPBMethod__storage_ {
},
{
.name = "responseTypeURL",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBMethod_FieldNumber_ResponseTypeURL,
.hasIndex = 4,
.offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL),
......@@ -239,7 +251,7 @@ typedef struct GPBMethod__storage_ {
},
{
.name = "responseStreaming",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBMethod_FieldNumber_ResponseStreaming,
.hasIndex = 5,
.offset = 6, // Stored in _has_storage_ to save space.
......@@ -248,7 +260,7 @@ typedef struct GPBMethod__storage_ {
},
{
.name = "optionsArray",
.dataTypeSpecific.className = GPBStringifySymbol(GPBOption),
.dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBOption),
.number = GPBMethod_FieldNumber_OptionsArray,
.hasIndex = GPBNoHasBit,
.offset = (uint32_t)offsetof(GPBMethod__storage_, optionsArray),
......@@ -272,7 +284,7 @@ typedef struct GPBMethod__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBMethod__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
static const char *extraTextFormatInfo =
"\002\002\007\244\241!!\000\004\010\244\241!!\000";
......@@ -321,7 +333,7 @@ typedef struct GPBMixin__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "name",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBMixin_FieldNumber_Name,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBMixin__storage_, name),
......@@ -330,7 +342,7 @@ typedef struct GPBMixin__storage_ {
},
{
.name = "root",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBMixin_FieldNumber_Root,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBMixin__storage_, root),
......@@ -345,7 +357,7 @@ typedef struct GPBMixin__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBMixin__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......
......@@ -68,7 +68,7 @@ typedef struct GPBDuration__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "seconds",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBDuration_FieldNumber_Seconds,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBDuration__storage_, seconds),
......@@ -77,7 +77,7 @@ typedef struct GPBDuration__storage_ {
},
{
.name = "nanos",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBDuration_FieldNumber_Nanos,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBDuration__storage_, nanos),
......@@ -92,7 +92,7 @@ typedef struct GPBDuration__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBDuration__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......
......@@ -68,7 +68,7 @@ typedef struct GPBEmpty__storage_ {
fields:NULL
fieldCount:0
storageSize:sizeof(GPBEmpty__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......
......@@ -66,7 +66,7 @@ typedef struct GPBFieldMask__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "pathsArray",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBFieldMask_FieldNumber_PathsArray,
.hasIndex = GPBNoHasBit,
.offset = (uint32_t)offsetof(GPBFieldMask__storage_, pathsArray),
......@@ -81,7 +81,7 @@ typedef struct GPBFieldMask__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBFieldMask__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......
......@@ -66,7 +66,7 @@ typedef struct GPBSourceContext__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "fileName",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBSourceContext_FieldNumber_FileName,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBSourceContext__storage_, fileName),
......@@ -81,7 +81,7 @@ typedef struct GPBSourceContext__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBSourceContext__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......
......@@ -25,6 +25,17 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-Wdirect-ivar-access"
#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"
#pragma mark - Objective C Class references
// This somewhat arcane code forces linkage of classes from static archives by
// adding a concrete reference to the classes.
// We don't use `[Foo class]` because we need a static value for our initializer.
// This also has the added benefit of reducing size in that we don't have to
// encode the class names and look them up at runtime.
extern const GPBObjcClassReference OBJC_CLASS_$_GPBListValue;
extern const GPBObjcClassReference OBJC_CLASS_$_GPBStruct;
extern const GPBObjcClassReference OBJC_CLASS_$_GPBValue;
#pragma mark - GPBStructRoot
......@@ -102,7 +113,7 @@ typedef struct GPBStruct__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "fields",
.dataTypeSpecific.className = GPBStringifySymbol(GPBValue),
.dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBValue),
.number = GPBStruct_FieldNumber_Fields,
.hasIndex = GPBNoHasBit,
.offset = (uint32_t)offsetof(GPBStruct__storage_, fields),
......@@ -117,7 +128,7 @@ typedef struct GPBStruct__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBStruct__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......@@ -166,7 +177,7 @@ typedef struct GPBValue__storage_ {
},
{
.name = "numberValue",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBValue_FieldNumber_NumberValue,
.hasIndex = -1,
.offset = (uint32_t)offsetof(GPBValue__storage_, numberValue),
......@@ -175,7 +186,7 @@ typedef struct GPBValue__storage_ {
},
{
.name = "stringValue",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBValue_FieldNumber_StringValue,
.hasIndex = -1,
.offset = (uint32_t)offsetof(GPBValue__storage_, stringValue),
......@@ -184,7 +195,7 @@ typedef struct GPBValue__storage_ {
},
{
.name = "boolValue",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBValue_FieldNumber_BoolValue,
.hasIndex = -1,
.offset = 0, // Stored in _has_storage_ to save space.
......@@ -193,7 +204,7 @@ typedef struct GPBValue__storage_ {
},
{
.name = "structValue",
.dataTypeSpecific.className = GPBStringifySymbol(GPBStruct),
.dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBStruct),
.number = GPBValue_FieldNumber_StructValue,
.hasIndex = -1,
.offset = (uint32_t)offsetof(GPBValue__storage_, structValue),
......@@ -202,7 +213,7 @@ typedef struct GPBValue__storage_ {
},
{
.name = "listValue",
.dataTypeSpecific.className = GPBStringifySymbol(GPBListValue),
.dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBListValue),
.number = GPBValue_FieldNumber_ListValue,
.hasIndex = -1,
.offset = (uint32_t)offsetof(GPBValue__storage_, listValue),
......@@ -217,7 +228,7 @@ typedef struct GPBValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBValue__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
static const char *oneofs[] = {
"kind",
};
......@@ -270,7 +281,7 @@ typedef struct GPBListValue__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "valuesArray",
.dataTypeSpecific.className = GPBStringifySymbol(GPBValue),
.dataTypeSpecific.clazz = ((__bridge Class)&OBJC_CLASS_$_GPBValue),
.number = GPBListValue_FieldNumber_ValuesArray,
.hasIndex = GPBNoHasBit,
.offset = (uint32_t)offsetof(GPBListValue__storage_, valuesArray),
......@@ -285,7 +296,7 @@ typedef struct GPBListValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBListValue__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......
......@@ -68,7 +68,7 @@ typedef struct GPBTimestamp__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "seconds",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBTimestamp_FieldNumber_Seconds,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBTimestamp__storage_, seconds),
......@@ -77,7 +77,7 @@ typedef struct GPBTimestamp__storage_ {
},
{
.name = "nanos",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBTimestamp_FieldNumber_Nanos,
.hasIndex = 1,
.offset = (uint32_t)offsetof(GPBTimestamp__storage_, nanos),
......@@ -92,7 +92,7 @@ typedef struct GPBTimestamp__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBTimestamp__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......
This diff is collapsed.
......@@ -66,7 +66,7 @@ typedef struct GPBDoubleValue__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "value",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBDoubleValue_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBDoubleValue__storage_, value),
......@@ -81,7 +81,7 @@ typedef struct GPBDoubleValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBDoubleValue__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......@@ -111,7 +111,7 @@ typedef struct GPBFloatValue__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "value",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBFloatValue_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBFloatValue__storage_, value),
......@@ -126,7 +126,7 @@ typedef struct GPBFloatValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBFloatValue__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......@@ -156,7 +156,7 @@ typedef struct GPBInt64Value__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "value",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBInt64Value_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBInt64Value__storage_, value),
......@@ -171,7 +171,7 @@ typedef struct GPBInt64Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBInt64Value__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......@@ -201,7 +201,7 @@ typedef struct GPBUInt64Value__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "value",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBUInt64Value_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBUInt64Value__storage_, value),
......@@ -216,7 +216,7 @@ typedef struct GPBUInt64Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBUInt64Value__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......@@ -246,7 +246,7 @@ typedef struct GPBInt32Value__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "value",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBInt32Value_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBInt32Value__storage_, value),
......@@ -261,7 +261,7 @@ typedef struct GPBInt32Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBInt32Value__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......@@ -291,7 +291,7 @@ typedef struct GPBUInt32Value__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "value",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBUInt32Value_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBUInt32Value__storage_, value),
......@@ -306,7 +306,7 @@ typedef struct GPBUInt32Value__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBUInt32Value__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......@@ -335,7 +335,7 @@ typedef struct GPBBoolValue__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "value",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBBoolValue_FieldNumber_Value,
.hasIndex = 0,
.offset = 1, // Stored in _has_storage_ to save space.
......@@ -350,7 +350,7 @@ typedef struct GPBBoolValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBBoolValue__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......@@ -380,7 +380,7 @@ typedef struct GPBStringValue__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "value",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBStringValue_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBStringValue__storage_, value),
......@@ -395,7 +395,7 @@ typedef struct GPBStringValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBStringValue__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......@@ -425,7 +425,7 @@ typedef struct GPBBytesValue__storage_ {
static GPBMessageFieldDescription fields[] = {
{
.name = "value",
.dataTypeSpecific.className = NULL,
.dataTypeSpecific.clazz = Nil,
.number = GPBBytesValue_FieldNumber_Value,
.hasIndex = 0,
.offset = (uint32_t)offsetof(GPBBytesValue__storage_, value),
......@@ -440,7 +440,7 @@ typedef struct GPBBytesValue__storage_ {
fields:fields
fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
storageSize:sizeof(GPBBytesValue__storage_)
flags:GPBDescriptorInitializationFlag_None];
flags:GPBDescriptorInitializationFlag_UsesClassRefs];
#if defined(DEBUG) && DEBUG
NSAssert(descriptor == nil, @"Startup recursed!");
#endif // DEBUG
......
......@@ -84,24 +84,24 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization(
io::Printer* printer) {
std::map<string, string> vars;
vars["root_class_and_method_name"] = root_class_and_method_name_;
vars["extended_type"] = ClassName(descriptor_->containing_type());
const string containing_type = ClassName(descriptor_->containing_type());
vars["extended_type"] = ObjCClassSymbolReference(containing_type);
vars["number"] = StrCat(descriptor_->number());
std::vector<string> options;
if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated");
if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked");
if (descriptor_->containing_type()->options().message_set_wire_format())
if (descriptor_->containing_type()->options().message_set_wire_format()) {
options.push_back("GPBExtensionSetWireFormat");
}
vars["options"] = BuildFlagsString(FLAGTYPE_EXTENSION, options);
ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
string singular_type;
if (objc_type == OBJECTIVECTYPE_MESSAGE) {
vars["type"] = string("GPBStringifySymbol(") +
ClassName(descriptor_->message_type()) + ")";
std::string message_type = ClassName(descriptor_->message_type());
vars["type"] = ObjCClassSymbolReference(message_type);
} else {
vars["type"] = "NULL";
vars["type"] = "Nil";
}
vars["default_name"] = GPBGenericValueFieldName(descriptor_);
......@@ -124,8 +124,8 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization(
"{\n"
" .defaultValue.$default_name$ = $default$,\n"
" .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
" .extendedClass = GPBStringifySymbol($extended_type$),\n"
" .messageOrGroupClassName = $type$,\n"
" .extendedClass.clazz = $extended_type$,\n"
" .messageOrGroupClass.clazz = $type$,\n"
" .enumDescriptorFunc = $enum_desc_func_name$,\n"
" .fieldNumber = $number$,\n"
" .dataType = $extension_type$,\n"
......@@ -133,11 +133,23 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization(
"},\n");
}
void ExtensionGenerator::DetermineObjectiveCClassDefinitions(
std::set<string>* fwd_decls) {
string extended_type = ClassName(descriptor_->containing_type());
fwd_decls->insert(ObjCClassSymbolDefinition(extended_type));
ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
if (objc_type == OBJECTIVECTYPE_MESSAGE) {
string message_type = ClassName(descriptor_->message_type());
fwd_decls->insert(ObjCClassSymbolDefinition(message_type));
}
}
void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) {
printer->Print(
"[registry addExtension:$root_class_and_method_name$];\n",
"root_class_and_method_name", root_class_and_method_name_);
}
} // namespace objectivec
} // namespace compiler
} // namespace protobuf
......
......@@ -51,6 +51,7 @@ class ExtensionGenerator {
void GenerateMembersHeader(io::Printer* printer);
void GenerateStaticVariablesInitialization(io::Printer* printer);
void GenerateRegistrationSource(io::Printer* printer);
void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls);
private:
string method_name_;
......
......@@ -97,8 +97,8 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
(*variables)["dataTypeSpecific_name"] = "className";
(*variables)["dataTypeSpecific_value"] = "NULL";
(*variables)["dataTypeSpecific_name"] = "clazz";
(*variables)["dataTypeSpecific_value"] = "Nil";
(*variables)["storage_offset_value"] =
"(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")";
......@@ -181,6 +181,11 @@ void FieldGenerator::DetermineForwardDeclarations(
// Nothing
}
void FieldGenerator::DetermineObjectiveCClassDefinitions(
std::set<string>* fwd_decls) const {
// Nothing
}
void FieldGenerator::GenerateFieldDescription(
io::Printer* printer, bool include_default) const {
// Printed in the same order as the structure decl.
......
......@@ -66,6 +66,7 @@ class FieldGenerator {
// Exposed for subclasses, should always call it on the parent class also.
virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
virtual void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls) const;
// Used during generation, not intended to be extended by subclasses.
void GenerateFieldDescription(
......
......@@ -398,10 +398,20 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
}
}
std::set<string> fwd_decls;
for (const auto& generator : message_generators_) {
generator->DetermineObjectiveCClassDefinitions(&fwd_decls);
}
for (const auto& generator : extension_generators_) {
generator->DetermineObjectiveCClassDefinitions(&fwd_decls);
}
// Note:
// deprecated-declarations suppression is only needed if some place in this
// proto file is something deprecated or if it references something from
// another file that is deprecated.
// dollar-in-identifier-extension is needed because we use references to
// objc class names that have $ in identifiers.
printer->Print(
"// @@protoc_insertion_point(imports)\n"
"\n"
......@@ -414,9 +424,28 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
printer->Print(
"#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n");
}
if (fwd_decls.size() > 0) {
printer->Print(
"#pragma clang diagnostic ignored \"-Wdollar-in-identifier-extension\"\n");
}
printer->Print(
"\n");
if (fwd_decls.size() > 0) {
printer->Print(
"#pragma mark - Objective C Class references\n"
"// This somewhat arcane code forces linkage of classes from static archives by\n"
"// adding a concrete reference to the classes.\n"
"// We don't use `[Foo class]` because we need a static value for our initializer.\n"
"// This also has the added benefit of reducing size in that we don't have to\n"
"// encode the class names and look them up at runtime.\n");
}
for (const auto& i : fwd_decls) {
printer->Print("$value$\n", "value", i);
}
if (fwd_decls.size() > 0) {
printer->Print("\n");
}
printer->Print(
"\n"
"#pragma mark - $root_class_name$\n"
"\n"
"@implementation $root_class_name$\n\n",
......@@ -454,7 +483,8 @@ void FileGenerator::GenerateSource(io::Printer *printer) {
"};\n"
"for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
" GPBExtensionDescriptor *extension =\n"
" [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];\n"
" [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]\n"
" usesClassRefs:YES];\n"
" [registry addExtension:extension];\n"
" [self globallyRegisterExtension:extension];\n"
" [extension release];\n"
......
......@@ -585,6 +585,19 @@ string OneofNameCapitalized(const OneofDescriptor* descriptor) {
return result;
}
static string ObjCClassSymbolName(const string& class_name) {
return string("OBJC_CLASS_$_") + class_name;
}
string ObjCClassSymbolReference(const string& class_name) {
return "((__bridge Class)&" + ObjCClassSymbolName(class_name) + ")";
}
string ObjCClassSymbolDefinition(const string& class_name) {
const string &ref = ObjCClassSymbolName(class_name);
return "extern const GPBObjcClassReference " + ref + ";";
}
string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) {
string worker(name);
if (HasSuffixString(worker, "_p")) {
......
......@@ -118,6 +118,15 @@ string PROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor);
string PROTOC_EXPORT OneofName(const OneofDescriptor* descriptor);
string PROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor);
// Returns a symbol that can be used in C code to refer to an Objective C
// class without initializing the class.
string PROTOC_EXPORT ObjCClassSymbolReference(const string& className);
// Defines a symbol that can be used in C code to refer to an Objective C
// class without initializing the class. Use a corresponding
// ObjCClassSymbolReference to reference it.
string PROTOC_EXPORT ObjCClassSymbolDefinition(const string& className);
inline bool HasFieldPresence(const FileDescriptor* file) {
return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
}
......
......@@ -112,6 +112,7 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) {
field_flags.push_back("GPBFieldHasEnumDescriptor");
}
variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
......@@ -170,6 +171,17 @@ void MapFieldGenerator::DetermineForwardDeclarations(
}
}
void MapFieldGenerator::DetermineObjectiveCClassDefinitions(
std::set<string>* fwd_decls) const {
// Class name is already in "storage_type".
const FieldDescriptor* value_descriptor =
descriptor_->message_type()->FindFieldByName("value");
if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) {
fwd_decls->insert(ObjCClassSymbolDefinition(
value_field_generator_->variable("storage_type")));
}
}
} // namespace objectivec
} // namespace compiler
......
......@@ -54,6 +54,7 @@ class MapFieldGenerator : public RepeatedFieldGenerator {
MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
virtual ~MapFieldGenerator();
virtual void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls) const;
virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
private:
......
......@@ -234,6 +234,30 @@ void MessageGenerator::DetermineForwardDeclarations(std::set<string>* fwd_decls)
}
}
void MessageGenerator::DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls) {
if (!IsMapEntryMessage(descriptor_)) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
field_generators_.get(fieldDescriptor)
.DetermineObjectiveCClassDefinitions(fwd_decls);
}
}
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 != NULL) {
string containing_class = ClassName(containing_descriptor);
fwd_decls->insert(ObjCClassSymbolDefinition(containing_class));
}
}
bool MessageGenerator::IncludesOneOfDefinition() const {
if (!oneof_generators_.empty()) {
return true;
......@@ -457,11 +481,11 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
field_description_type = "GPBMessageFieldDescription";
}
if (has_fields) {
printer->Print(
" static $field_description_type$ fields[] = {\n",
"field_description_type", field_description_type);
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 =
......@@ -474,10 +498,10 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
}
}
printer->Outdent();
printer->Print(
"};\n");
printer->Outdent();
printer->Outdent();
printer->Print(
" };\n");
}
std::map<string, string> vars;
......@@ -492,6 +516,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
}
std::vector<string> init_flags;
init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs");
if (need_defaults) {
init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
}
......@@ -556,10 +581,11 @@ void MessageGenerator::GenerateSource(io::Printer* printer) {
" count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
}
if (descriptor_->containing_type() != NULL) {
string parent_class_name = ClassName(descriptor_->containing_type());
string containing_class = ClassName(descriptor_->containing_type());
string parent_class_ref = ObjCClassSymbolReference(containing_class);
printer->Print(
" [localDescriptor setupContainingMessageClassName:GPBStringifySymbol($parent_name$)];\n",
"parent_name", parent_class_name);
" [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n",
"parent_class_ref", parent_class_ref);
}
string suffix_added;
ClassName(descriptor_, &suffix_added);
......
......@@ -63,6 +63,7 @@ class MessageGenerator {
void GenerateMessageHeader(io::Printer* printer);
void GenerateSource(io::Printer* printer);
void GenerateExtensionRegistrationSource(io::Printer* printer);
void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls);
void DetermineForwardDeclarations(std::set<string>* fwd_decls);
// Checks if the message or a nested message includes a oneof definition.
......
......@@ -46,13 +46,14 @@ namespace {
void SetMessageVariables(const FieldDescriptor* descriptor,
std::map<string, string>* variables) {
const string& message_type = ClassName(descriptor->message_type());
const string& containing_class = ClassName(descriptor->containing_type());
(*variables)["type"] = message_type;
(*variables)["containing_class"] = ClassName(descriptor->containing_type());
(*variables)["containing_class"] = containing_class;
(*variables)["storage_type"] = message_type;
(*variables)["group_or_message"] =
(descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message";
(*variables)["dataTypeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")";
(*variables)["dataTypeSpecific_value"] =
ObjCClassSymbolReference(message_type);
}
} // namespace
......@@ -72,6 +73,11 @@ void MessageFieldGenerator::DetermineForwardDeclarations(
fwd_decls->insert("@class " + variable("storage_type"));
}
void MessageFieldGenerator::DetermineObjectiveCClassDefinitions(
std::set<string>* fwd_decls) const {
fwd_decls->insert(ObjCClassSymbolDefinition(variable("storage_type")));
}
bool MessageFieldGenerator::WantsHasProperty(void) const {
if (descriptor_->containing_oneof() != NULL) {
// If in a oneof, it uses the oneofcase instead of a has bit.
......@@ -100,6 +106,10 @@ void RepeatedMessageFieldGenerator::DetermineForwardDeclarations(
fwd_decls->insert("@class " + variable("storage_type"));
}
void RepeatedMessageFieldGenerator::DetermineObjectiveCClassDefinitions(
std::set<string>* fwd_decls) const {
fwd_decls->insert(ObjCClassSymbolDefinition(variable("storage_type")));
}
} // namespace objectivec
} // namespace compiler
......
......@@ -56,6 +56,7 @@ class MessageFieldGenerator : public ObjCObjFieldGenerator {
public:
virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
virtual void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls) const;
};
class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
......@@ -72,6 +73,7 @@ class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
public:
virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
virtual void DetermineObjectiveCClassDefinitions(std::set<string>* fwd_decls) const;
};
} // namespace objectivec
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment