Compare commits

...

4 Commits

Author SHA1 Message Date
ThePantsThief 4ee263a405 Fix #168 by restructuring try-catch branching 2018-11-04 04:07:15 -06:00
Tanner Bennett 02180085a6 Fix prettyArgumentComponentsForMethod: bug
#178 made methods with no arguments appear to take one argument by forcibly returning the selector name as the only argument. This is not desired behavior. Updating the test to reflect desired behavior reveals this.

This commit makes this method return an empty array when selectors consist of one component, and does some housekeeping on the tests added in #178.
2018-11-04 04:07:15 -06:00
Tanner Bennett 5716658571 Detect and unbox pointers to objects from void *
- Also unbox C strings into NSString
- Also adds return type encoding string to method calling view controller
2018-11-04 04:00:20 -06:00
Tanner Bennett bc39c8894c Add helper methods to FLEXRuntimeUtility
- Add FLEXTypeEncoding enum
- Can check whether arbitrary poiner is valid object
- Can get return type encoding for method
- Can unbox raw pointers from NSValue into actual objects, or unbox C strings into NSStrings

Code copied from the Objc runtime complies with ASPL
2018-11-04 04:00:19 -06:00
9 changed files with 888 additions and 88 deletions
@@ -17,6 +17,7 @@
@interface FLEXMethodCallingViewController ()
@property (nonatomic, assign) Method method;
@property (nonatomic, assign) FLEXTypeEncoding *returnType;
@end
@@ -27,7 +28,8 @@
self = [super initWithTarget:target];
if (self) {
self.method = method;
self.title = [self isClassMethod] ? @"Class Method" : @"Method";
self.returnType = [FLEXRuntimeUtility returnTypeForMethod:method];
self.title = [self isClassMethod] ? @"Class Method" : @"Method";;
}
return self;
}
@@ -36,7 +38,11 @@
{
[super viewDidLoad];
self.fieldEditorView.fieldDescription = [FLEXRuntimeUtility prettyNameForMethod:self.method isClassMethod:[self isClassMethod]];
NSString *returnType = @((const char *)self.returnType);
NSString *methodDescription = [FLEXRuntimeUtility prettyNameForMethod:self.method isClassMethod:[self isClassMethod]];
NSString *format = @"Signature:\n%@\n\nReturn Type:\n%@";
NSString *info = [NSString stringWithFormat:format, methodDescription, returnType];
self.fieldEditorView.fieldDescription = info;
NSArray<NSString *> *methodComponents = [FLEXRuntimeUtility prettyArgumentComponentsForMethod:self.method];
NSMutableArray<FLEXArgumentInputView *> *argumentInputViews = [NSMutableArray array];
@@ -54,6 +60,12 @@
self.fieldEditorView.argumentInputViews = argumentInputViews;
}
- (void)dealloc
{
free(self.returnType);
self.returnType = NULL;
}
- (BOOL)isClassMethod
{
return self.target && self.target == [self.target class];
@@ -88,6 +100,7 @@
[alert show];
} else if (returnedObject) {
// For non-nil (or void) return types, push an explorer view controller to display the returned object
returnedObject = [FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:returnedObject type:self.returnType];
FLEXObjectExplorerViewController *explorerViewController = [FLEXObjectExplorerFactory explorerViewControllerForObject:returnedObject];
[self.navigationController pushViewController:explorerViewController animated:YES];
} else {
@@ -367,7 +367,10 @@ typedef NS_ENUM(NSUInteger, FLEXMetadataKind) {
id value = nil;
if ([self canHaveInstanceState]) {
FLEXPropertyBox *propertyBox = self.filteredProperties[index];
NSString *typeString = [FLEXRuntimeUtility typeEncodingForProperty:propertyBox.property];
const FLEXTypeEncoding *encoding = [typeString cStringUsingEncoding:NSUTF8StringEncoding];
value = [FLEXRuntimeUtility valueForProperty:propertyBox.property onObject:self.object];
value = [FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:value type:encoding];
}
return value;
}
@@ -449,7 +452,9 @@ typedef NS_ENUM(NSUInteger, FLEXMetadataKind) {
id value = nil;
if ([self canHaveInstanceState]) {
FLEXIvarBox *ivarBox = self.filteredIvars[index];
const FLEXTypeEncoding *encoding = ivar_getTypeEncoding(ivarBox.ivar);
value = [FLEXRuntimeUtility valueForIvar:ivarBox.ivar onObject:self.object];
value = [FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:value type:encoding];
}
return value;
}
+367
View File
@@ -0,0 +1,367 @@
APPLE PUBLIC SOURCE LICENSE
Version 2.0 - August 6, 2003
Please read this License carefully before downloading this software.
By downloading or using this software, you are agreeing to be bound by
the terms of this License. If you do not or cannot agree to the terms
of this License, please do not download or use the software.
1. General; Definitions. This License applies to any program or other
work which Apple Computer, Inc. ("Apple") makes publicly available and
which contains a notice placed by Apple identifying such program or
work as "Original Code" and stating that it is subject to the terms of
this Apple Public Source License version 2.0 ("License"). As used in
this License:
1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is
the grantor of rights, (i) claims of patents that are now or hereafter
acquired, owned by or assigned to Apple and (ii) that cover subject
matter contained in the Original Code, but only to the extent
necessary to use, reproduce and/or distribute the Original Code
without infringement; and (b) in the case where You are the grantor of
rights, (i) claims of patents that are now or hereafter acquired,
owned by or assigned to You and (ii) that cover subject matter in Your
Modifications, taken alone or in combination with Original Code.
1.2 "Contributor" means any person or entity that creates or
contributes to the creation of Modifications.
1.3 "Covered Code" means the Original Code, Modifications, the
combination of Original Code and any Modifications, and/or any
respective portions thereof.
1.4 "Externally Deploy" means: (a) to sublicense, distribute or
otherwise make Covered Code available, directly or indirectly, to
anyone other than You; and/or (b) to use Covered Code, alone or as
part of a Larger Work, in any way to provide a service, including but
not limited to delivery of content, through electronic communication
with a client other than You.
1.5 "Larger Work" means a work which combines Covered Code or portions
thereof with code not governed by the terms of this License.
1.6 "Modifications" mean any addition to, deletion from, and/or change
to, the substance and/or structure of the Original Code, any previous
Modifications, the combination of Original Code and any previous
Modifications, and/or any respective portions thereof. When code is
released as a series of files, a Modification is: (a) any addition to
or deletion from the contents of a file containing Covered Code;
and/or (b) any new file or other representation of computer program
statements that contains any part of Covered Code.
1.7 "Original Code" means (a) the Source Code of a program or other
work as originally made available by Apple under this License,
including the Source Code of any updates or upgrades to such programs
or works made available by Apple under this License, and that has been
expressly identified by Apple as such in the header file(s) of such
work; and (b) the object code compiled from such Source Code and
originally made available by Apple under this License.
1.8 "Source Code" means the human readable form of a program or other
work that is suitable for making modifications to it, including all
modules it contains, plus any associated interface definition files,
scripts used to control compilation and installation of an executable
(object code).
1.9 "You" or "Your" means an individual or a legal entity exercising
rights under this License. For legal entities, "You" or "Your"
includes any entity which controls, is controlled by, or is under
common control with, You, where "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of fifty percent
(50%) or more of the outstanding shares or beneficial ownership of
such entity.
2. Permitted Uses; Conditions & Restrictions. Subject to the terms
and conditions of this License, Apple hereby grants You, effective on
the date You accept this License and download the Original Code, a
world-wide, royalty-free, non-exclusive license, to the extent of
Apple's Applicable Patent Rights and copyrights covering the Original
Code, to do the following:
2.1 Unmodified Code. You may use, reproduce, display, perform,
internally distribute within Your organization, and Externally Deploy
verbatim, unmodified copies of the Original Code, for commercial or
non-commercial purposes, provided that in each instance:
(a) You must retain and reproduce in all copies of Original Code the
copyright and other proprietary notices and disclaimers of Apple as
they appear in the Original Code, and keep intact all notices in the
Original Code that refer to this License; and
(b) You must include a copy of this License with every copy of Source
Code of Covered Code and documentation You distribute or Externally
Deploy, and You may not offer or impose any terms on such Source Code
that alter or restrict this License or the recipients' rights
hereunder, except as permitted under Section 6.
2.2 Modified Code. You may modify Covered Code and use, reproduce,
display, perform, internally distribute within Your organization, and
Externally Deploy Your Modifications and Covered Code, for commercial
or non-commercial purposes, provided that in each instance You also
meet all of these conditions:
(a) You must satisfy all the conditions of Section 2.1 with respect to
the Source Code of the Covered Code;
(b) You must duplicate, to the extent it does not already exist, the
notice in Exhibit A in each file of the Source Code of all Your
Modifications, and cause the modified files to carry prominent notices
stating that You changed the files and the date of any change; and
(c) If You Externally Deploy Your Modifications, You must make
Source Code of all Your Externally Deployed Modifications either
available to those to whom You have Externally Deployed Your
Modifications, or publicly available. Source Code of Your Externally
Deployed Modifications must be released under the terms set forth in
this License, including the license grants set forth in Section 3
below, for as long as you Externally Deploy the Covered Code or twelve
(12) months from the date of initial External Deployment, whichever is
longer. You should preferably distribute the Source Code of Your
Externally Deployed Modifications electronically (e.g. download from a
web site).
2.3 Distribution of Executable Versions. In addition, if You
Externally Deploy Covered Code (Original Code and/or Modifications) in
object code, executable form only, You must include a prominent
notice, in the code itself as well as in related documentation,
stating that Source Code of the Covered Code is available under the
terms of this License with information on how and where to obtain such
Source Code.
2.4 Third Party Rights. You expressly acknowledge and agree that
although Apple and each Contributor grants the licenses to their
respective portions of the Covered Code set forth herein, no
assurances are provided by Apple or any Contributor that the Covered
Code does not infringe the patent or other intellectual property
rights of any other entity. Apple and each Contributor disclaim any
liability to You for claims brought by any other entity based on
infringement of intellectual property rights or otherwise. As a
condition to exercising the rights and licenses granted hereunder, You
hereby assume sole responsibility to secure any other intellectual
property rights needed, if any. For example, if a third party patent
license is required to allow You to distribute the Covered Code, it is
Your responsibility to acquire that license before distributing the
Covered Code.
3. Your Grants. In consideration of, and as a condition to, the
licenses granted to You under this License, You hereby grant to any
person or entity receiving or distributing Covered Code under this
License a non-exclusive, royalty-free, perpetual, irrevocable license,
under Your Applicable Patent Rights and other intellectual property
rights (other than patent) owned or controlled by You, to use,
reproduce, display, perform, modify, sublicense, distribute and
Externally Deploy Your Modifications of the same scope and extent as
Apple's licenses under Sections 2.1 and 2.2 above.
4. Larger Works. You may create a Larger Work by combining Covered
Code with other code not governed by the terms of this License and
distribute the Larger Work as a single product. In each such instance,
You must make sure the requirements of this License are fulfilled for
the Covered Code or any portion thereof.
5. Limitations on Patent License. Except as expressly stated in
Section 2, no other patent rights, express or implied, are granted by
Apple herein. Modifications and/or Larger Works may require additional
patent licenses from Apple which Apple may grant in its sole
discretion.
6. Additional Terms. You may choose to offer, and to charge a fee for,
warranty, support, indemnity or liability obligations and/or other
rights consistent with the scope of the license granted herein
("Additional Terms") to one or more recipients of Covered Code.
However, You may do so only on Your own behalf and as Your sole
responsibility, and not on behalf of Apple or any Contributor. You
must obtain the recipient's agreement that any such Additional Terms
are offered by You alone, and You hereby agree to indemnify, defend
and hold Apple and every Contributor harmless for any liability
incurred by or claims asserted against Apple or such Contributor by
reason of any such Additional Terms.
7. Versions of the License. Apple may publish revised and/or new
versions of this License from time to time. Each version will be given
a distinguishing version number. Once Original Code has been published
under a particular version of this License, You may continue to use it
under the terms of that version. You may also choose to use such
Original Code under the terms of any subsequent version of this
License published by Apple. No one other than Apple has the right to
modify the terms applicable to Covered Code created under this
License.
8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in
part pre-release, untested, or not fully tested works. The Covered
Code may contain errors that could cause failures or loss of data, and
may be incomplete or contain inaccuracies. You expressly acknowledge
and agree that use of the Covered Code, or any portion thereof, is at
Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND
WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND
APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE
PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF
MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR
PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD
PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST
INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE
FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS,
THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO
ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE
AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.
You acknowledge that the Covered Code is not intended for use in the
operation of nuclear facilities, aircraft navigation, communication
systems, or air traffic control machines in which case the failure of
the Covered Code could lead to death, personal injury, or severe
physical or environmental damage.
9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL,
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING
TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR
ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY,
TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF
APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY
REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF
INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY
TO YOU. In no event shall Apple's total liability to You for all
damages (other than as may be required by applicable law) under this
License exceed the amount of fifty dollars ($50.00).
10. Trademarks. This License does not grant any rights to use the
trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS",
"QuickTime", "QuickTime Streaming Server" or any other trademarks,
service marks, logos or trade names belonging to Apple (collectively
"Apple Marks") or to any trademark, service mark, logo or trade name
belonging to any Contributor. You agree not to use any Apple Marks in
or as part of the name of products derived from the Original Code or
to endorse or promote products derived from the Original Code other
than as expressly permitted by and in strict compliance at all times
with Apple's third party trademark usage guidelines which are posted
at http://www.apple.com/legal/guidelinesfor3rdparties.html.
11. Ownership. Subject to the licenses granted under this License,
each Contributor retains all rights, title and interest in and to any
Modifications made by such Contributor. Apple retains all rights,
title and interest in and to the Original Code and any Modifications
made by or on behalf of Apple ("Apple Modifications"), and such Apple
Modifications will not be automatically subject to this License. Apple
may, at its sole discretion, choose to license such Apple
Modifications under this License, or on different terms from those
contained in this License or may choose not to license them at all.
12. Termination.
12.1 Termination. This License and the rights granted hereunder will
terminate:
(a) automatically without notice from Apple if You fail to comply with
any term(s) of this License and fail to cure such breach within 30
days of becoming aware of such breach;
(b) immediately in the event of the circumstances described in Section
13.5(b); or
(c) automatically without notice from Apple if You, at any time during
the term of this License, commence an action for patent infringement
against Apple; provided that Apple did not first commence
an action for patent infringement against You in that instance.
12.2 Effect of Termination. Upon termination, You agree to immediately
stop any further use, reproduction, modification, sublicensing and
distribution of the Covered Code. All sublicenses to the Covered Code
which have been properly granted prior to termination shall survive
any termination of this License. Provisions which, by their nature,
should remain in effect beyond the termination of this License shall
survive, including but not limited to Sections 3, 5, 8, 9, 10, 11,
12.2 and 13. No party will be liable to any other for compensation,
indemnity or damages of any sort solely as a result of terminating
this License in accordance with its terms, and termination of this
License will be without prejudice to any other right or remedy of
any party.
13. Miscellaneous.
13.1 Government End Users. The Covered Code is a "commercial item" as
defined in FAR 2.101. Government software and technical data rights in
the Covered Code include only those rights customarily provided to the
public as defined in this License. This customary commercial license
in technical data and software is provided in accordance with FAR
12.211 (Technical Data) and 12.212 (Computer Software) and, for
Department of Defense purchases, DFAR 252.227-7015 (Technical Data --
Commercial Items) and 227.7202-3 (Rights in Commercial Computer
Software or Computer Software Documentation). Accordingly, all U.S.
Government End Users acquire Covered Code with only those rights set
forth herein.
13.2 Relationship of Parties. This License will not be construed as
creating an agency, partnership, joint venture or any other form of
legal association between or among You, Apple or any Contributor, and
You will not represent to the contrary, whether expressly, by
implication, appearance or otherwise.
13.3 Independent Development. Nothing in this License will impair
Apple's right to acquire, license, develop, have others develop for
it, market and/or distribute technology or products that perform the
same or similar functions as, or otherwise compete with,
Modifications, Larger Works, technology or products that You may
develop, produce, market or distribute.
13.4 Waiver; Construction. Failure by Apple or any Contributor to
enforce any provision of this License will not be deemed a waiver of
future enforcement of that or any other provision. Any law or
regulation which provides that the language of a contract shall be
construed against the drafter will not apply to this License.
13.5 Severability. (a) If for any reason a court of competent
jurisdiction finds any provision of this License, or portion thereof,
to be unenforceable, that provision of the License will be enforced to
the maximum extent permissible so as to effect the economic benefits
and intent of the parties, and the remainder of this License will
continue in full force and effect. (b) Notwithstanding the foregoing,
if applicable law prohibits or restricts You from fully and/or
specifically complying with Sections 2 and/or 3 or prevents the
enforceability of either of those Sections, this License will
immediately terminate and You must immediately discontinue any use of
the Covered Code and destroy all copies of it that are in your
possession or control.
13.6 Dispute Resolution. Any litigation or other dispute resolution
between You and Apple relating to this License shall take place in the
Northern District of California, and You and Apple hereby consent to
the personal jurisdiction of, and venue in, the state and federal
courts within that District with respect to this License. The
application of the United Nations Convention on Contracts for the
International Sale of Goods is expressly excluded.
13.7 Entire Agreement; Governing Law. This License constitutes the
entire agreement between the parties with respect to the subject
matter hereof. This License shall be governed by the laws of the
United States and the State of California, except that body of
California law concerning conflicts of law.
Where You are located in the province of Quebec, Canada, the following
clause applies: The parties hereby confirm that they have requested
that this License and all related documents be drafted in English. Les
parties ont exige que le present contrat et tous les documents
connexes soient rediges en anglais.
EXHIBIT A.
"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
Reserved.
This file contains Original Code and/or Modifications of Original Code
as defined in and that are subject to the Apple Public Source License
Version 2.0 (the 'License'). You may not use this file except in
compliance with the License. Please obtain a copy of the License at
http://www.opensource.apple.com/apsl/ and read it before using this
file.
The Original Code and all software distributed under the License are
distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
Please see the License for the specific language governing rights and
limitations under the License."
+23
View File
@@ -0,0 +1,23 @@
//
// FLEXObjcInternal.h
// FLEX
//
// Created by Tanner Bennett on 11/1/18.
//
#import <Foundation/Foundation.h>
#ifdef __cplusplus
extern "C" {
#endif
/// @brief Assumes memory is valid and readable.
/// @discussion objc-internal.h, objc-private.h, and objc-config.h
/// https://blog.timac.org/2016/1124-testing-if-an-arbitrary-pointer-is-a-valid-objective-c-object/
/// http://llvm.org/svn/llvm-project/lldb/trunk/examples/summaries/cocoa/objc_runtime.py
/// https://blog.timac.org/2016/1124-testing-if-an-arbitrary-pointer-is-a-valid-objective-c-object/
BOOL FLEXPointerIsValidObjcObject(const void * ptr);
#ifdef __cplusplus
}
#endif
+309
View File
@@ -0,0 +1,309 @@
//
// FLEXObjcInternal.mm
// FLEX
//
// Created by Tanner Bennett on 11/1/18.
//
/*
* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#import "FLEXObjcInternal.h"
#import <objc/runtime.h>
#import <malloc/malloc.h>
#define ALWAYS_INLINE inline __attribute__((always_inline))
#define NEVER_INLINE inline __attribute__((noinline))
// The macros below are copied straight from
// objc-internal.h, objc-private.h, objc-object.h, and objc-config.h with
// as few modifications as possible. Changes are noted in boxed comments.
// https://opensource.apple.com/source/objc4/objc4-723/
// https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-internal.h.auto.html
// https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-private.h.auto.html
// https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-config.h.auto.html
// https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-object.h.auto.html
/////////////////////
// objc-internal.h //
/////////////////////
#if TARGET_OS_OSX && __x86_64__
// 64-bit Mac - tag bit is LSB
# define OBJC_MSB_TAGGED_POINTERS 0
#else
// Everything else - tag bit is MSB
# define OBJC_MSB_TAGGED_POINTERS 1
#endif
#define _OBJC_TAG_INDEX_MASK 0x7
// array slot includes the tag bit itself
#define _OBJC_TAG_SLOT_COUNT 16
#define _OBJC_TAG_SLOT_MASK 0xf
#define _OBJC_TAG_EXT_INDEX_MASK 0xff
// array slot has no extra bits
#define _OBJC_TAG_EXT_SLOT_COUNT 256
#define _OBJC_TAG_EXT_SLOT_MASK 0xff
#if OBJC_MSB_TAGGED_POINTERS
# define _OBJC_TAG_MASK (1UL<<63)
# define _OBJC_TAG_INDEX_SHIFT 60
# define _OBJC_TAG_SLOT_SHIFT 60
# define _OBJC_TAG_PAYLOAD_LSHIFT 4
# define _OBJC_TAG_PAYLOAD_RSHIFT 4
# define _OBJC_TAG_EXT_MASK (0xfUL<<60)
# define _OBJC_TAG_EXT_INDEX_SHIFT 52
# define _OBJC_TAG_EXT_SLOT_SHIFT 52
# define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 12
# define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
#else
# define _OBJC_TAG_MASK 1UL
# define _OBJC_TAG_INDEX_SHIFT 1
# define _OBJC_TAG_SLOT_SHIFT 0
# define _OBJC_TAG_PAYLOAD_LSHIFT 0
# define _OBJC_TAG_PAYLOAD_RSHIFT 4
# define _OBJC_TAG_EXT_MASK 0xfUL
# define _OBJC_TAG_EXT_INDEX_SHIFT 4
# define _OBJC_TAG_EXT_SLOT_SHIFT 4
# define _OBJC_TAG_EXT_PAYLOAD_LSHIFT 0
# define _OBJC_TAG_EXT_PAYLOAD_RSHIFT 12
#endif
//////////////////////////////////////
// originally _objc_isTaggedPointer //
//////////////////////////////////////
static BOOL flex_isTaggedPointer(const void *ptr)
{
return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}
///////////////////
// objc-config.h //
///////////////////
// Define SUPPORT_INDEXED_ISA=1 on platforms that store the class in the isa
// field as an index into a class table.
#if __ARM_ARCH_7K__ >= 2
# define SUPPORT_INDEXED_ISA 1
#else
# define SUPPORT_INDEXED_ISA 0
#endif
// Define SUPPORT_PACKED_ISA=1 on platforms that store the class in the isa
// field as a maskable pointer with other data around it.
#if (!__LP64__ || TARGET_OS_WIN32 || TARGET_OS_SIMULATOR)
# define SUPPORT_PACKED_ISA 0
#else
# define SUPPORT_PACKED_ISA 1
#endif
// Define SUPPORT_NONPOINTER_ISA=1 on any platform that may store something
// in the isa field that is not a raw pointer.
#if !SUPPORT_INDEXED_ISA && !SUPPORT_PACKED_ISA
# define SUPPORT_NONPOINTER_ISA 0
#else
# define SUPPORT_NONPOINTER_ISA 1
#endif
////////////////////
// objc-private.h //
////////////////////
union isa_t
{
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
Class cls;
uintptr_t bits;
#if SUPPORT_PACKED_ISA
// extra_rc must be the MSB-most field (so it matches carry/overflow flags)
// nonpointer must be the LSB (fixme or get rid of it)
// shiftcls must occupy the same bits that a real class pointer would
// bits + RC_ONE is equivalent to extra_rc + 1
// RC_HALF is the high bit of extra_rc (i.e. half of its range)
// future expansion:
// uintptr_t fast_rr : 1; // no r/r overrides
// uintptr_t lock : 2; // lock for atomic property, @synch
// uintptr_t extraBytes : 1; // allocated with extra bytes
# if __arm64__
# define ISA_MASK 0x0000000ffffffff8ULL
# define ISA_MAGIC_MASK 0x000003f000000001ULL
# define ISA_MAGIC_VALUE 0x000001a000000001ULL
struct {
uintptr_t nonpointer : 1;
uintptr_t has_assoc : 1;
uintptr_t has_cxx_dtor : 1;
uintptr_t shiftcls : 33; // MACH_VM_MAX_ADDRESS 0x1000000000
uintptr_t magic : 6;
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 19;
# define RC_ONE (1ULL<<45)
# define RC_HALF (1ULL<<18)
};
# elif __x86_64__
# define ISA_MASK 0x00007ffffffffff8ULL
# define ISA_MAGIC_MASK 0x001f800000000001ULL
# define ISA_MAGIC_VALUE 0x001d800000000001ULL
struct {
uintptr_t nonpointer : 1;
uintptr_t has_assoc : 1;
uintptr_t has_cxx_dtor : 1;
uintptr_t shiftcls : 44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000
uintptr_t magic : 6;
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 8;
# define RC_ONE (1ULL<<56)
# define RC_HALF (1ULL<<7)
};
# else
# error unknown architecture for packed isa
# endif
// SUPPORT_PACKED_ISA
#endif
#if SUPPORT_INDEXED_ISA
# if __ARM_ARCH_7K__ >= 2
# define ISA_INDEX_IS_NPI 1
# define ISA_INDEX_MASK 0x0001FFFC
# define ISA_INDEX_SHIFT 2
# define ISA_INDEX_BITS 15
# define ISA_INDEX_COUNT (1 << ISA_INDEX_BITS)
# define ISA_INDEX_MAGIC_MASK 0x001E0001
# define ISA_INDEX_MAGIC_VALUE 0x001C0001
struct {
uintptr_t nonpointer : 1;
uintptr_t has_assoc : 1;
uintptr_t indexcls : 15;
uintptr_t magic : 4;
uintptr_t has_cxx_dtor : 1;
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 7;
# define RC_ONE (1ULL<<25)
# define RC_HALF (1ULL<<6)
};
# else
# error unknown architecture for indexed isa
# endif
// SUPPORT_INDEXED_ISA
#endif
};
///////////////////
// objc-object.h //
///////////////////
////////////////////////////////////////////////
// originally objc_object::isExtTaggedPointer //
////////////////////////////////////////////////
static BOOL flex_isExtTaggedPointer(const void *ptr)
{
return ((uintptr_t)ptr & _OBJC_TAG_EXT_MASK) == _OBJC_TAG_EXT_MASK;
}
struct flex_objc_object {
isa_t isa;
};
//////////////////////////////////////////////////////////
// Returns nil on platforms without nonpointer isa. //
// Supporting those platforms would be too complicated //
// for such a niche feature anyway. - @NSExceptional //
// //
// Code modified from objc_object::ISA() on 11/04/18 //
//////////////////////////////////////////////////////////
static id flex_getIsa(const flex_objc_object *object) {
#if SUPPORT_NONPOINTER_ISA
if (object->isa.nonpointer) {
return object_getClass((__bridge id)object);
}
return (__bridge Class)(void *)object->isa.bits;
#else
return nil;
#endif
}
/////////////////////////////////////
// FLEXObjectInternal //
// No Apple code beyond this point //
/////////////////////////////////////
extern "C" {
/// Assumes memory is valid and readable.
/// https://blog.timac.org/2016/1124-testing-if-an-arbitrary-pointer-is-a-valid-objective-c-object/
BOOL FLEXPointerIsValidObjcObject(const void * ptr)
{
uintptr_t pointer = (uintptr_t)ptr;
if (!ptr) {
return NO;
}
// Tagged pointers have 0x1 set, no other valid pointers do
// objc-internal.h -> _objc_isTaggedPointer()
if (flex_isTaggedPointer(ptr) || flex_isExtTaggedPointer(ptr)) {
return YES;
}
// Check pointer alignment
if ((pointer % sizeof(uintptr_t)) != 0) {
return NO;
}
// From LLDB:
// Pointers in a class_t will only have bits 0 through 46 set,
// so if any pointer has bits 47 through 63 high, we know that this is not a valid isa
// http://llvm.org/svn/llvm-project/lldb/trunk/examples/summaries/cocoa/objc_runtime.py
if ((pointer & 0xFFFF800000000000) != 0) {
return NO;
}
// http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html :
if (flex_getIsa((const flex_objc_object *)ptr)) {
return YES;
}
return NO;
}
}
+35
View File
@@ -25,10 +25,44 @@ extern NSString *const kFLEXUtilityAttributeWeak;
extern NSString *const kFLEXUtilityAttributeGarbageCollectable;
extern NSString *const kFLEXUtilityAttributeOldStyleTypeEncoding;
typedef NS_ENUM(char, FLEXTypeEncoding)
{
FLEXTypeEncodingUnknown = '?',
FLEXTypeEncodingChar = 'c',
FLEXTypeEncodingInt = 'i',
FLEXTypeEncodingShort = 's',
FLEXTypeEncodingLong = 'l',
FLEXTypeEncodingLongLong = 'q',
FLEXTypeEncodingUnsignedChar = 'C',
FLEXTypeEncodingUnsignedInt = 'I',
FLEXTypeEncodingUnsignedShort = 'S',
FLEXTypeEncodingUnsignedLong = 'L',
FLEXTypeEncodingUnsignedLongLong = 'Q',
FLEXTypeEncodingFloat = 'f',
FLEXTypeEncodingDouble = 'd',
FLEXTypeEncodingCBool = 'B',
FLEXTypeEncodingVoid = 'v',
FLEXTypeEncodingCString = '*',
FLEXTypeEncodingObjcObject = '@',
FLEXTypeEncodingObjcClass = '#',
FLEXTypeEncodingSelector = ':',
FLEXTypeEncodingArray = '[',
FLEXTypeEncodingStruct = '{',
FLEXTypeEncodingUnion = '(',
FLEXTypeEncodingBitField = 'b',
FLEXTypeEncodingPointer = '^',
FLEXTypeEncodingConst = 'r'
};
#define FLEXEncodeClass(class) ("@\"" #class "\"")
@interface FLEXRuntimeUtility : NSObject
// General Helpers
+ (BOOL)pointerIsValidObjcObject:(const void *)pointer;
/// Unwraps raw pointers to objects stored in NSValue, and re-boxes C strings into NSStrings.
+ (id)potentiallyUnwrapBoxedPointer:(id)returnedObjectOrNil type:(const FLEXTypeEncoding *)returnType;
// Property Helpers
+ (NSString *)prettyNameForProperty:(objc_property_t)property;
+ (NSString *)typeEncodingForProperty:(objc_property_t)property;
@@ -47,6 +81,7 @@ extern NSString *const kFLEXUtilityAttributeOldStyleTypeEncoding;
// Method Helpers
+ (NSString *)prettyNameForMethod:(Method)method isClassMethod:(BOOL)isClassMethod;
+ (NSArray *)prettyArgumentComponentsForMethod:(Method)method;
+ (FLEXTypeEncoding *)returnTypeForMethod:(Method)method;
// Method Calling/Field Editing
+ (id)performSelector:(SEL)selector onObject:(id)object withArguments:(NSArray *)arguments error:(NSError * __autoreleasing *)error;
+89 -31
View File
@@ -8,6 +8,7 @@
#import <UIKit/UIKit.h>
#import "FLEXRuntimeUtility.h"
#import "FLEXObjcInternal.h"
// See https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW6
NSString *const kFLEXUtilityAttributeTypeEncoding = @"T";
@@ -36,6 +37,57 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
@implementation FLEXRuntimeUtility
#pragma mark - General Helpers (Public)
+ (BOOL)pointerIsValidObjcObject:(const void *)pointer
{
return FLEXPointerIsValidObjcObject(pointer);
}
+ (id)potentiallyUnwrapBoxedPointer:(id)returnedObjectOrNil type:(const FLEXTypeEncoding *)returnType
{
if (!returnedObjectOrNil) {
return nil;
}
NSInteger i = 0;
if (returnType[i] == FLEXTypeEncodingConst) {
i++;
}
BOOL returnsObjectOrClass = returnType[i] == FLEXTypeEncodingObjcObject ||
returnType[i] == FLEXTypeEncodingObjcClass;
BOOL returnsVoidPointer = returnType[i] == FLEXTypeEncodingPointer &&
returnType[i+1] == FLEXTypeEncodingVoid;
BOOL returnsCString = returnType[i] == FLEXTypeEncodingCString;
// If we got back an NSValue and the return type is not an object,
// we check to see if the pointer is of a valid object. If not,
// we just display the NSValue.
if (!returnsObjectOrClass) {
// Can only be NSValue since return type is not an object,
// so we bail if this doesn't add up
if (![returnedObjectOrNil isKindOfClass:[NSValue class]]) {
return returnedObjectOrNil;
}
NSValue *value = (NSValue *)returnedObjectOrNil;
if (returnsCString) {
// Wrap char * in NSString
const char *string = (const char *)value.pointerValue;
returnedObjectOrNil = [NSString stringWithCString:string encoding:NSUTF8StringEncoding];
} else if (returnsVoidPointer) {
// Cast valid objects disguised as void * to id
if ([FLEXRuntimeUtility pointerIsValidObjcObject:value.pointerValue]) {
returnedObjectOrNil = (__bridge id)value.pointerValue;
}
}
}
return returnedObjectOrNil;
}
#pragma mark - Property Helpers (Public)
+ (NSString *)prettyNameForProperty:(objc_property_t)property
@@ -285,7 +337,7 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
// this is a workaround cause method_getNumberOfArguments() returns wrong number for some methods
if (selectorComponents.count == 1) {
return [selectorComponents copy];
return @[];
}
if ([selectorComponents.lastObject isEqualToString:@""]) {
@@ -303,6 +355,11 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
return components;
}
+ (FLEXTypeEncoding *)returnTypeForMethod:(Method)method
{
return (FLEXTypeEncoding *)method_copyReturnType(method);
}
#pragma mark - Method Calling/Field Editing (Public)
@@ -353,66 +410,67 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
return nil;
}
NSUInteger bufferSize = 0;
@try {
NSUInteger bufferSize = 0;
// NSGetSizeAndAlignment barfs on type encoding for bitfields.
NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL);
if (bufferSize > 0) {
void *buffer = calloc(bufferSize, 1);
[argumentValue getValue:buffer];
[invocation setArgument:buffer atIndex:argumentIndex];
free(buffer);
}
} @catch (NSException *exception) { }
if (bufferSize > 0) {
void *buffer = calloc(bufferSize, 1);
[argumentValue getValue:buffer];
[invocation setArgument:buffer atIndex:argumentIndex];
free(buffer);
}
}
}
}
// Try to invoke the invocation but guard against an exception being thrown.
BOOL successfullyInvoked = NO;
id returnObject = nil;
@try {
// Some methods are not fit to be called...
// Looking at you -[UIResponder(UITextInputAdditions) _caretRect]
[invocation invoke];
successfullyInvoked = YES;
// Retreive the return value and box if necessary.
const char *returnType = [methodSignature methodReturnType];
if (returnType[0] == @encode(id)[0] || returnType[0] == @encode(Class)[0]) {
// Return value is an object.
__unsafe_unretained id objectReturnedFromMethod = nil;
[invocation getReturnValue:&objectReturnedFromMethod];
returnObject = objectReturnedFromMethod;
} else if (returnType[0] != @encode(void)[0]) {
// Will use arbitrary buffer for return value and box it.
void *returnValue = malloc([methodSignature methodReturnLength]);
if (returnValue) {
[invocation getReturnValue:returnValue];
returnObject = [self valueForPrimitivePointer:returnValue objCType:returnType];
free(returnValue);
}
}
} @catch (NSException *exception) {
// Bummer...
if (error) {
// "… on <class>" / "… on instance of <class>"
NSString *class = NSStringFromClass([object class]);
NSString *calledOn = object == [object class] ? class : [@"an instance of " stringByAppendingString:class];
NSString *message = [NSString stringWithFormat:@"Exception '%@' thrown while performing selector '%@' on %@.\nReason:\n\n%@",
exception.name,
NSStringFromSelector(selector),
calledOn,
exception.reason];
*error = [NSError errorWithDomain:FLEXRuntimeUtilityErrorDomain
code:FLEXRuntimeUtilityErrorCodeInvocationFailed
userInfo:@{ NSLocalizedDescriptionKey : message }];
}
}
// Retreive the return value and box if necessary.
id returnObject = nil;
if (successfullyInvoked) {
const char *returnType = [methodSignature methodReturnType];
if (returnType[0] == @encode(id)[0] || returnType[0] == @encode(Class)[0]) {
__unsafe_unretained id objectReturnedFromMethod = nil;
[invocation getReturnValue:&objectReturnedFromMethod];
returnObject = objectReturnedFromMethod;
} else if (returnType[0] != @encode(void)[0]) {
void *returnValue = malloc([methodSignature methodReturnLength]);
if (returnValue) {
[invocation getReturnValue:returnValue];
returnObject = [self valueForPrimitivePointer:returnValue objCType:returnType];
free(returnValue);
}
}
}
return returnObject;
}
+8
View File
@@ -166,6 +166,8 @@
94AAF0381BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AAF0361BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
94AAF0391BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 94AAF0371BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m */; };
94AAF03A1BAF2F0300DE8760 /* FLEXKeyboardShortcutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 942DCD821BAE0AD300DB5DC2 /* FLEXKeyboardShortcutManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
C37A0C93218BAC9600848CA7 /* FLEXObjcInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = C37A0C91218BAC9600848CA7 /* FLEXObjcInternal.h */; };
C37A0C94218BAC9600848CA7 /* FLEXObjcInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = C37A0C92218BAC9600848CA7 /* FLEXObjcInternal.mm */; };
C395D6D921789BD800BEAD4D /* FLEXColorExplorerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = C395D6D721789BD800BEAD4D /* FLEXColorExplorerViewController.h */; };
C395D6DA21789BD800BEAD4D /* FLEXColorExplorerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C395D6D821789BD800BEAD4D /* FLEXColorExplorerViewController.m */; };
C3DB9F642107FC9600B46809 /* FLEXObjectRef.h in Headers */ = {isa = PBXBuildFile; fileRef = C3DB9F622107FC9600B46809 /* FLEXObjectRef.h */; };
@@ -346,6 +348,8 @@
94A515241C4CA2080063292F /* FLEXToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FLEXToolbarItem.m; path = Classes/Toolbar/FLEXToolbarItem.m; sourceTree = SOURCE_ROOT; };
94AAF0361BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeyboardHelpViewController.h; sourceTree = "<group>"; };
94AAF0371BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeyboardHelpViewController.m; sourceTree = "<group>"; };
C37A0C91218BAC9600848CA7 /* FLEXObjcInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXObjcInternal.h; sourceTree = "<group>"; };
C37A0C92218BAC9600848CA7 /* FLEXObjcInternal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FLEXObjcInternal.mm; sourceTree = "<group>"; };
C395D6D721789BD800BEAD4D /* FLEXColorExplorerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXColorExplorerViewController.h; sourceTree = "<group>"; };
C395D6D821789BD800BEAD4D /* FLEXColorExplorerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXColorExplorerViewController.m; sourceTree = "<group>"; };
C3DB9F622107FC9600B46809 /* FLEXObjectRef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXObjectRef.h; sourceTree = "<group>"; };
@@ -471,6 +475,8 @@
3A4C94581B5B21410088C3F2 /* FLEXMultilineTableViewCell.m */,
3A4C94591B5B21410088C3F2 /* FLEXResources.h */,
3A4C945A1B5B21410088C3F2 /* FLEXResources.m */,
C37A0C91218BAC9600848CA7 /* FLEXObjcInternal.h */,
C37A0C92218BAC9600848CA7 /* FLEXObjcInternal.mm */,
3A4C945B1B5B21410088C3F2 /* FLEXRuntimeUtility.h */,
3A4C945C1B5B21410088C3F2 /* FLEXRuntimeUtility.m */,
3A4C945D1B5B21410088C3F2 /* FLEXUtility.h */,
@@ -710,6 +716,7 @@
3A4C94FD1B5B21410088C3F2 /* FLEXArgumentInputStructView.h in Headers */,
94A515141C4CA1C00063292F /* FLEXManager.h in Headers */,
3A4C95201B5B21410088C3F2 /* FLEXFileBrowserFileOperationController.h in Headers */,
C37A0C93218BAC9600848CA7 /* FLEXObjcInternal.h in Headers */,
3A4C953E1B5B21410088C3F2 /* FLEXNetworkTransactionDetailTableViewController.h in Headers */,
3A4C95301B5B21410088C3F2 /* FLEXSystemLogMessage.h in Headers */,
3A4C95361B5B21410088C3F2 /* FLEXNetworkHistoryTableViewController.h in Headers */,
@@ -939,6 +946,7 @@
3A4C95351B5B21410088C3F2 /* FLEXSystemLogTableViewController.m in Sources */,
3A4C95271B5B21410088C3F2 /* FLEXGlobalsTableViewController.m in Sources */,
779B1ED31C0C4D7C001F5E49 /* FLEXTableColumnHeader.m in Sources */,
C37A0C94218BAC9600848CA7 /* FLEXObjcInternal.mm in Sources */,
3A4C94EA1B5B21410088C3F2 /* FLEXHierarchyTableViewController.m in Sources */,
3A4C95331B5B21410088C3F2 /* FLEXSystemLogTableViewCell.m in Sources */,
C3DB9F652107FC9600B46809 /* FLEXObjectRef.m in Sources */,
+37 -55
View File
@@ -24,49 +24,43 @@
@implementation FLEXTestMethodList
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
[self testMethodListForClass:[NSObject class]];
[self testMethodListForClass:[NSArray class]];
[self testMethodListForClass:[UIApplication class]];
[self testMethodListForClass:[UIView class]];
[self testMethodListForClass:[NSThread class]];
[self testMethodListForClass:[CALayer class]];
[self testMethodListForClass:[NSDictionary class]];
[self testMethodListForClass:[NSProxy class]];
[self testMethodListForClass:[NSData class]];
[self testMethodListForClass:[FLEXManager class]];
[self testMethodListForClass:[FLEXWindow class]];
[self testMethodListForClass:[FLEXMultiColumnTableView class]];
[self testMethodListForClass:[NSString class]];
[self testMethodListForClass:[NSSet class]];
[self testMethodListForClass:[NSUndoManager class]];
[self testMethodListForClass:[NSMutableArray class]];
[self testMethodListForClass:[NSMutableDictionary class]];
[self testMethodListForClass:[NSException class]];
[self testMethodListForClass:[UIImage class]];
[self testMethodListForClass:[UIViewController class]];
[self testMethodListForClass:[UIScreen class]];
[self testMethodListForClass:[UIResponder class]];
[self testMethodListForClass:[NSNumber class]];
[self testMethodListForClass:[NSValue class]];
[self testMethodListForClass:[NSError class]];
[self testMethodListForClass:[NSNotificationCenter class]];
[self testMethodListForClass:[NSUserActivity class]];
[self testMethodListForClass:[NSUserDefaults class]];
[self testMethodListForClass:[NSExpression class]];
[self testMethodListForClass:[NSBundle class]];
NSArray<Class> *classesToTest = @[
[NSObject class],
[NSArray class],
[UIApplication class],
[UIView class],
[NSThread class],
[CALayer class],
[NSDictionary class],
[NSProxy class],
[NSData class],
[FLEXManager class],
[FLEXWindow class],
[FLEXMultiColumnTableView class],
[NSString class],
[NSSet class],
[NSUndoManager class],
[NSMutableArray class],
[NSMutableDictionary class],
[NSException class],
[UIImage class],
[UIViewController class],
[UIScreen class],
[UIResponder class],
[NSNumber class],
[NSValue class],
[NSError class],
[NSNotificationCenter class],
[NSUserActivity class],
[NSUserDefaults class],
[NSExpression class],
[NSBundle class]
];
for (Class cls in classesToTest) {
[self testMethodListForClass:cls];
}
}
- (void)testMethodListForClass:(Class)class {
@@ -75,27 +69,15 @@
Method *methods = class_copyMethodList(class, &methodCount);
for (unsigned int i = 0; i < methodCount; ++i) {
Method method = methods[i];
NSString *selectorName = NSStringFromSelector(method_getName(method));
NSArray *prevWay = [self prettyArgumentComponentsForMethod:method];
if (![prevWay count]) {
prevWay = @[ selectorName ];
}
NSArray *newWay = [FLEXRuntimeUtility prettyArgumentComponentsForMethod:method];
XCTAssert([newWay isEqual:prevWay]);
XCTAssertEqualObjects(prevWay, newWay);
}
free(methods);
}
- (void)testPerformanceExample {
// This is an example of a performance test case.
[self measureBlock:^{
// Put the code you want to measure the time of here.
}];
}
#pragma mark - Method to test with
- (NSArray *)prettyArgumentComponentsForMethod:(Method)method {