diff --git a/Objective-J/Debug.js b/Objective-J/Debug.js index 532afc6f2..d8583f634 100644 --- a/Objective-J/Debug.js +++ b/Objective-J/Debug.js @@ -185,7 +185,7 @@ GLOBAL(objj_typecheck_decorator) = function(msgSend) if (!aReceiver) return msgSend.apply(this, arguments); - var types = aReceiver.isa.method_dtable[aSelector].types; + var types = aReceiver.isa.method_dtable[aSelector].method_types; for (var i = 2; i < arguments.length; i++) { try diff --git a/Objective-J/Runtime.js b/Objective-J/Runtime.js index 2c07e2154..2229a6e82 100644 --- a/Objective-J/Runtime.js +++ b/Objective-J/Runtime.js @@ -1020,9 +1020,52 @@ GLOBAL(method_getName) = function(/*Method*/ aMethod) return aMethod.method_name; } -GLOBAL(method_getTypes) = function(/*Method*/ aMethod) +// This will not return correct values if the compiler does not have the option 'IncludeTypeSignatures' +GLOBAL(method_copyReturnType) = function(/*Method*/ aMethod) { - return aMethod.method_types; + var types = aMethod.method_types; + + if (types) + { + var argType = types[0]; + + return argType != NULL ? argType : NULL; + } + else + return NULL; +} + +// This will not return correct values for index > 1 if the compiler does not have the option 'IncludeTypeSignatures' +GLOBAL(method_copyArgumentType) = function(/*Method*/ aMethod, /*unsigned int*/ index) +{ + switch (index) { + case 0: + return "id"; + + case 1: + return "SEL"; + + default: + var types = aMethod.method_types; + + if (types) + { + var argType = types[index - 1]; + + return argType != NULL ? argType : NULL; + } + else + return NULL; + } +} + +// Returns number of arguments for a method. The first argument is 'self' and the second is the selector. +// Those are followed by the method arguments. So for example it will return 2 for a method with no arguments. +GLOBAL(method_getNumberOfArguments) = function(/*Method*/ aMethod) +{ + var types = aMethod.method_types; + + return types ? types.length + 1 : ((aMethod.method_name.match(/:/g) || []).length + 2); } GLOBAL(method_getImplementation) = function(/*Method*/ aMethod) diff --git a/Tests/Objective-J/Preprocessor/BehaviorTests/MethodTest.j b/Tests/Objective-J/Preprocessor/BehaviorTests/MethodTest.j index 99aef883b..7df299459 100644 --- a/Tests/Objective-J/Preprocessor/BehaviorTests/MethodTest.j +++ b/Tests/Objective-J/Preprocessor/BehaviorTests/MethodTest.j @@ -80,4 +80,59 @@ [self assert:-6 equals:[testClass void:10 in:4]]; } +- (void)testMethodName +{ + var method = class_getInstanceMethod(MathClass, @selector(sqrt:)); + + [self assert:method_getName(method) equals:@"sqrt:"]; +} + +- (void)testMethodNoOfArguments +{ + var method = class_getInstanceMethod(MathClass, @selector(five)); + + [self assert:method_getNumberOfArguments(method) equals:2]; + + method = class_getInstanceMethod(MathClass, @selector(multiply:)); + [self assert:method_getNumberOfArguments(method) equals:3]; + + method = class_getInstanceMethod(MathClass, @selector(multiply:with:)); + [self assert:method_getNumberOfArguments(method) equals:4]; +} + +- (void)testMethodTypes +{ + var theClass = objj_allocateClassPair(CPObject, RAND() + ""); + + objj_registerClassPair(theClass); + class_addMethod(theClass, @"myMethod:", function() { }, ["void", "CPNumber"]); + class_addMethod(theClass, @"myMethod2:", function() { }, ["int", "float"]); + class_addMethod(theClass, @"myMethod3:", function() { }); + [theClass new]; + + var method = class_getInstanceMethod(theClass, @selector(myMethod:)); + + [self assert:method_copyReturnType(method) equals:@"void" message:@"Return type of method 'myMethod:'"]; + [self assert:method_copyArgumentType(method, 0) equals:@"id"]; + [self assert:method_copyArgumentType(method, 1) equals:@"SEL"]; + [self assert:method_copyArgumentType(method, 2) equals:@"CPNumber"]; + [self assertTrue:method_copyArgumentType(method, 3) === nil]; + [self assert:method_getNumberOfArguments(method) equals:3]; + + method = class_getInstanceMethod(theClass, @selector(myMethod2:)); + [self assert:method_copyReturnType(method) equals:@"int" message:@"Return type of method 'myMethod2:'"]; + [self assert:method_copyArgumentType(method, 0) equals:@"id"]; + [self assert:method_copyArgumentType(method, 1) equals:@"SEL"]; + [self assert:method_copyArgumentType(method, 2) equals:@"float"]; + [self assertTrue:method_copyArgumentType(method, 3) === nil]; + [self assert:method_getNumberOfArguments(method) equals:3]; + + method = class_getInstanceMethod(theClass, @selector(myMethod3:)); + [self assertTrue:method_copyReturnType(method) == nil]; + [self assert:method_copyArgumentType(method, 0) equals:@"id"]; + [self assert:method_copyArgumentType(method, 1) equals:@"SEL"]; + [self assertTrue:method_copyArgumentType(method, 2) === nil]; + [self assert:method_getNumberOfArguments(method) equals:3]; +} + @end