forked from pmougin/F-Script
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathFSNSProxy.m
107 lines (87 loc) · 3.78 KB
/
FSNSProxy.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/* FSNSProxy.m Copyright (c) 1998-2009 Philippe Mougin. */
/* This software is open source. See the license. */
#import "build_config.h"
#import "FSNSProxy.h"
#import "FSNSStringPrivate.h"
#import "FSBoolean.h"
#import "FSNSString.h"
#import "FScriptFunctions.h"
#import "FSNSNumber.h"
#import "FSNumber.h"
#import "NumberPrivate.h"
#import "FSArray.h"
#import "FSBooleanPrivate.h"
#import "FSNSObject.h"
#import <objc/objc-runtime.h>
#import <AppKit/AppKit.h>
/* Note: Cocoa implementation of NSProxy is completely broken at the *class* level: most methods in the
NSObject protocol are not provided at the class level, the superclass method return incorect results etc.
Some methods here (like methodSignatureForSelector:) are partial fixes for some aspects of this problem.
This fixes are needed by F-Script because it makes use of these methods at some points, when the user
want to manipulate directly classes of the NSProxy hierarchy.
*/
@interface NSMethodSignature(UndocumentedNSMethodSignature)
+ (NSMethodSignature*) signatureWithObjCTypes:(char *)types;
@end
@implementation NSProxy(FSNSProxy)
+ (NSString *)description
{
return NSStringFromClass(self);
}
+ (BOOL)isKindOfClass:(Class)theClass
{
Class cls = [self classOrMetaclass];
while (cls != theClass && cls != nil && cls != [cls superclass]) cls = [cls superclass];
// Note: Correct behavior for a root class is to return nil when asked for its superclass.
// However, it seems that some root classes (e.g. NSProxy) return themselves instead.
// The test above take the two possibilities into account.
return cls == theClass;
}
+ (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
// Limitation: this is all hard wired here, and thus will not work for methods added in new categories or new subclasses.
if (selector == @selector(class)) return [NSMethodSignature signatureWithObjCTypes:"#@:"];
else if (selector == @selector(classOrMetaclass)) return [NSMethodSignature signatureWithObjCTypes:"#@:"];
else if (selector == @selector(description)) return [NSMethodSignature signatureWithObjCTypes:"@@:"];
else if (selector == @selector(isKindOfClass:)) return [NSMethodSignature signatureWithObjCTypes:"c@:#"];
else if (selector == @selector(isProxy)) return [NSMethodSignature signatureWithObjCTypes:"c@:"];
else if (selector == @selector(methodSignatureForSelector:)) return [NSMethodSignature signatureWithObjCTypes:"@@::"];
else if (selector == @selector(operator_equal_equal:)) return [NSMethodSignature signatureWithObjCTypes:"@@:@"];
else if (selector == @selector(operator_tilde_tilde:)) return [NSMethodSignature signatureWithObjCTypes:"@@:@"];
else if (selector == @selector(printString)) return [NSMethodSignature signatureWithObjCTypes:"@@:"];
else if (selector == @selector(superclass)) return [NSMethodSignature signatureWithObjCTypes:"#@:"];
else return nil;
}
+ (NSUInteger) _ul_count
{
return 1;
}
+ (id)_ul_objectAtIndex:(NSUInteger)index
{
return self;
}
///////////////////////// USER METHODS /////////////////////
+ (id)classOrMetaclass
{
return objc_getMetaClass(object_getClassName(self));
}
+ (FSBoolean *)operator_equal_equal:(id)operand
{
return (self == operand ? (id)[FSBoolean fsTrue] : (id)[FSBoolean fsFalse]);
}
+ (FSBoolean *)operator_tilde_tilde:(id)operand
{
return (self == operand ? (id)[FSBoolean fsFalse] : (id)[FSBoolean fsTrue]);
}
- (id)classOrMetaclass
{
return [self class];
}
+ (NSString *)printString
{
if ([self classOrMetaclass] == [NSProxy classOrMetaclass] && self != (id)[NSProxy class])
return [[self description] stringByAppendingString:@" (meta)"];
else
return [self description];
}
@end