Index: src/OFIntrospection.h ================================================================== --- src/OFIntrospection.h +++ src/OFIntrospection.h @@ -94,24 +94,51 @@ * \return The type encoding for the instance variable */ - (const char*)typeEncoding; @end +#ifdef OF_HAVE_PROPERTIES +/** + * \brief A class for describing a property. + */ +@interface OFProperty: OFObject +{ + OFString *name; + const char *attributes; +} + +/// The name of the property. +@property (readonly, copy) OFString *name; +/// The attributes of the property. +@property (readonly) const char *attributes; +@end +#endif + /** * \brief A class for introspecting classes. */ @interface OFIntrospection: OFObject { OFMutableArray *classMethods; OFMutableArray *instanceMethods; OFMutableArray *instanceVariables; +#ifdef OF_HAVE_PROPERTIES + OFMutableArray *properties; +#endif } #ifdef OF_HAVE_PROPERTIES @property (readonly, copy) OFArray *classMethods; @property (readonly, copy) OFArray *instanceMethods; @property (readonly, copy) OFArray *instanceVariables; + +/** + * \brief The properties of the class. + * + * Only available if OF_HAVE_PROPERTIES is defined. + */ +@property (readonly, copy) OFArray *properties; #endif /** * \brief Creates a new introspection for the specified class. * @@ -146,7 +173,7 @@ * * \return An array of OFInstanceVariables */ - (OFArray*)instanceVariables; -/* TODO: properties, protocols */ +/* TODO: protocols */ @end Index: src/OFIntrospection.m ================================================================== --- src/OFIntrospection.m +++ src/OFIntrospection.m @@ -165,12 +165,54 @@ return [OFString stringWithFormat: @"", name, typeEncoding, offset]; } @end + +#ifdef OF_HAVE_PROPERTIES +@implementation OFProperty +@synthesize name, attributes; + +#if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) +- _initWithProperty: (objc_property_t)property +{ + self = [super init]; + + @try { + name = [[OFString alloc] + initWithCString: property_getName(property) + encoding: OF_STRING_ENCODING_ASCII]; + attributes = property_getAttributes(property); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} +#endif + +- (void)dealloc +{ + [name release]; + + [super dealloc]; +} + +- (OFString*)description +{ + return [OFString stringWithFormat: @"", + name, attributes]; +} +@end +#endif @implementation OFIntrospection +#ifdef OF_HAVE_PROPERTIES +@synthesize properties; +#endif + + introspectionWithClass: (Class)class { return [[[self alloc] initWithClass: class] autorelease]; } @@ -181,18 +223,24 @@ @try { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; #if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) Method *methodList; Ivar *ivarList; +# ifdef OF_HAVE_PROPERTIES + objc_property_t *propertyList; +# endif unsigned i, count; #elif defined(OF_OLD_GNU_RUNTIME) MethodList_t methodList; #endif classMethods = [[OFMutableArray alloc] init]; instanceMethods = [[OFMutableArray alloc] init]; instanceVariables = [[OFMutableArray alloc] init]; +#ifdef OF_HAVE_PROPERTIES + properties = [[OFMutableArray alloc] init]; +#endif #if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) methodList = class_copyMethodList(((OFObject*)class)->isa, &count); @try { @@ -227,45 +275,67 @@ [pool releaseObjects]; } } @finally { free(ivarList); } + + propertyList = class_copyPropertyList(class, &count); + @try { + for (i = 0; i < count; i++) { + [properties addObject: + [[[OFProperty alloc] + _initWithProperty: propertyList[i]] + autorelease]]; + [pool releaseObjects]; + } + } @finally { + free(propertyList); + } #elif defined(OF_OLD_GNU_RUNTIME) for (methodList = class->class_pointer->methods; methodList != NULL; methodList = methodList->method_next) { int i; - for (i = 0; i < methodList->method_count; i++) + for (i = 0; i < methodList->method_count; i++) { [classMethods addObject: [[[OFMethod alloc] _initWithMethod: &methodList->method_list[i]] autorelease]]; + [pool releaseObjects]; + } } for (methodList = class->methods; methodList != NULL; methodList = methodList->method_next) { int i; - for (i = 0; i < methodList->method_count; i++) + for (i = 0; i < methodList->method_count; i++) { [instanceMethods addObject: [[[OFMethod alloc] _initWithMethod: &methodList->method_list[i]] autorelease]]; + [pool releaseObjects]; + } } if (class->ivars != NULL) { int i; - for (i = 0; i < class->ivars->ivar_count; i++) + for (i = 0; i < class->ivars->ivar_count; i++) { [instanceVariables addObject: [[[OFInstanceVariable alloc] _initWithIvar: class->ivars->ivar_list + i] autorelease]]; + [pool releaseObjects]; + } } #endif [classMethods makeImmutable]; [instanceMethods makeImmutable]; [instanceVariables makeImmutable]; +#ifdef OF_HAVE_PROPERTIES + [properties makeImmutable]; +#endif [pool release]; } @catch (id e) { [self release]; @throw e; @@ -277,10 +347,13 @@ - (void)dealloc { [classMethods release]; [instanceMethods release]; [instanceVariables release]; +#ifdef OF_HAVE_PROPERTIES + [properties release]; +#endif [super dealloc]; } - (OFArray*)classMethods