From 734d26b430efc3bbc5fc1b2c9588939fe4b81d7e Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 4 Jan 2018 21:34:55 -0800 Subject: [PATCH 1/6] Set project indent to 2 --- Chisel/Chisel.xcodeproj/project.pbxproj | 1 + 1 file changed, 1 insertion(+) diff --git a/Chisel/Chisel.xcodeproj/project.pbxproj b/Chisel/Chisel.xcodeproj/project.pbxproj index 12510f1..f74ed9e 100644 --- a/Chisel/Chisel.xcodeproj/project.pbxproj +++ b/Chisel/Chisel.xcodeproj/project.pbxproj @@ -75,6 +75,7 @@ 7ABD17981DF7F998006118F8 /* ChiselTests */, 7ABD178C1DF7F998006118F8 /* Products */, ); + indentWidth = 2; sourceTree = ""; }; 7ABD178C1DF7F998006118F8 /* Products */ = { From 1d4d72e4c8e7177292ceae48b71fe048f7d60609 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 4 Jan 2018 21:36:30 -0800 Subject: [PATCH 2/6] Gracefully handle invalid predicates --- Chisel/Chisel/CHLObjcInstanceCommands.mm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Chisel/Chisel/CHLObjcInstanceCommands.mm b/Chisel/Chisel/CHLObjcInstanceCommands.mm index faa6c20..d473ce3 100644 --- a/Chisel/Chisel/CHLObjcInstanceCommands.mm +++ b/Chisel/Chisel/CHLObjcInstanceCommands.mm @@ -129,7 +129,12 @@ void PrintInstances(const char *type, const char *pred) { NSPredicate *predicate = nil; if (pred != nullptr && *pred != '\0') { - predicate = [NSPredicate predicateWithFormat:@(pred)]; + @try { + predicate = [NSPredicate predicateWithFormat:@(pred)]; + } @catch (NSException *e) { + printf("Error: Invalid predicate; %s\n", [e reason].UTF8String); + return; + } } const std::unordered_set objcClasses = CHLObjcClassSet(); From 5fa0eab784a78013313ff3db2f2fc5cc9d1302f8 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 4 Jan 2018 23:32:51 -0800 Subject: [PATCH 3/6] Handle class names sans swift module name --- Chisel/Chisel/CHLObjcInstanceCommands.mm | 35 ++++++++++++++++++------ 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/Chisel/Chisel/CHLObjcInstanceCommands.mm b/Chisel/Chisel/CHLObjcInstanceCommands.mm index d473ce3..fd89e7c 100644 --- a/Chisel/Chisel/CHLObjcInstanceCommands.mm +++ b/Chisel/Chisel/CHLObjcInstanceCommands.mm @@ -149,17 +149,36 @@ void PrintInstances(const char *type, const char *pred) } } + bool exactClass = false; if (type[0] == '*') { + exactClass = true; ++type; - Class cls = objc_getClass(type); - if (cls != nullptr) { + } + + auto addMatch = [&](Class cls) { + if (exactClass) { matchClasses.insert(cls); + } else { + for (auto c : objcClasses) { + if (isSubclassOf(c, cls)) { + matchClasses.insert(c); + } + } } - } else if (Class kind = objc_getClass(type)) { - // This could be optimized for type == "NSObject", but it won't be a typical search. - for (auto cls : objcClasses) { - if (isSubclassOf(cls, kind)) { - matchClasses.insert(cls); + }; + + Class cls = objc_getClass(type); + if (cls != Nil) { + addMatch(cls); + } else { + // The given class name hasn't been found, this could be a Swift class which case has + // a module name prefix. Loop over all classes to look for matching class names. + for (auto c : objcClasses) { + // SwiftModule.ClassName + // ^- dot + 1 + auto dot = strchr(class_getName(c), '.'); + if (dot && strcmp(type, dot + 1) == 0) { + addMatch(c); } } } @@ -172,7 +191,7 @@ void PrintInstances(const char *type, const char *pred) NSSet *keyPaths = CHLVariableKeyPaths(predicate); - std::vector> instances = CHLScanObjcInstances(matchClasses); + auto instances = CHLScanObjcInstances(matchClasses); unsigned int matches = 0; for (id obj : instances) { From 6d85102325a6e3ac15a40a4656ebf94234ee0edf Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Thu, 4 Jan 2018 23:47:17 -0800 Subject: [PATCH 4/6] Fix INSTALL_NAME handling in Makefile --- Chisel/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Chisel/Makefile b/Chisel/Makefile index 9aca3c7..ad8f710 100644 --- a/Chisel/Makefile +++ b/Chisel/Makefile @@ -1,7 +1,7 @@ PREFIX ?= /usr/local/lib -export INSTALL_NAME = "" -ifneq ($(LD_DYLIB_INSTALL_NAME), "") +export INSTALL_NAME = +ifneq ($(LD_DYLIB_INSTALL_NAME),) INSTALL_NAME = "LD_DYLIB_INSTALL_NAME=$(LD_DYLIB_INSTALL_NAME)" endif From c3180f4d9dc1d62c5b8f027bae7fc9789178d2a5 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Fri, 5 Jan 2018 00:05:29 -0800 Subject: [PATCH 5/6] Improve clarity/naming/consistency --- Chisel/Chisel/CHLObjcInstanceCommands.mm | 32 +++++++++++++----------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Chisel/Chisel/CHLObjcInstanceCommands.mm b/Chisel/Chisel/CHLObjcInstanceCommands.mm index fd89e7c..37c2178 100644 --- a/Chisel/Chisel/CHLObjcInstanceCommands.mm +++ b/Chisel/Chisel/CHLObjcInstanceCommands.mm @@ -103,9 +103,9 @@ static bool objectIsMatch(NSPredicate *predicate, id obj, const std::unordered_s // Function reimplementation of +[NSObject isSubclassOf:] to avoid the objc runtime side // effects that can happen when calling methods, like realizing classes, +initialize, etc. -static bool isSubclassOf(Class base, Class target) +static bool isSubclassOfClass(Class self, Class target) { - for (auto cls = base; cls != Nil; cls = class_getSuperclass(cls)) { + for (auto cls = self; cls != Nil; cls = class_getSuperclass(cls)) { if (cls == target) { return true; } @@ -115,9 +115,9 @@ static bool isSubclassOf(Class base, Class target) // Function reimplementation of +[NSObject conformsToProtocol:] to avoid the objc runtime side // effects that can happen when calling methods, like realizing classes, +initialize, etc. -static bool conformsToProtocol(Class base, Protocol *protocol) +static bool conformsToProtocol(Class self, Protocol *protocol) { - for (auto cls = base; cls != Nil; cls = class_getSuperclass(cls)) { + for (auto cls = self; cls != Nil; cls = class_getSuperclass(cls)) { if (class_conformsToProtocol(cls, protocol)) { return true; } @@ -155,30 +155,32 @@ void PrintInstances(const char *type, const char *pred) ++type; } - auto addMatch = [&](Class cls) { + // Helper lambda that only exists so that it can be called more than once, as in the + // rare case where `type` corresponds to more than one Swift class. + auto addMatch = [&](Class baseClass) { if (exactClass) { - matchClasses.insert(cls); + matchClasses.insert(baseClass); } else { - for (auto c : objcClasses) { - if (isSubclassOf(c, cls)) { - matchClasses.insert(c); + for (auto cls : objcClasses) { + if (isSubclassOfClass(cls, baseClass)) { + matchClasses.insert(cls); } } } }; - Class cls = objc_getClass(type); - if (cls != Nil) { - addMatch(cls); + Class baseClass = objc_getClass(type); + if (baseClass != Nil) { + addMatch(baseClass); } else { // The given class name hasn't been found, this could be a Swift class which case has // a module name prefix. Loop over all classes to look for matching class names. - for (auto c : objcClasses) { + for (auto cls : objcClasses) { // SwiftModule.ClassName // ^- dot + 1 - auto dot = strchr(class_getName(c), '.'); + auto dot = strchr(class_getName(cls), '.'); if (dot && strcmp(type, dot + 1) == 0) { - addMatch(c); + addMatch(cls); } } } From 97545fd5838cca25f09fea2a3299ec2c7e35e4ad Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Fri, 5 Jan 2018 00:28:56 -0800 Subject: [PATCH 6/6] Comment fix --- Chisel/Chisel/CHLObjcInstanceCommands.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chisel/Chisel/CHLObjcInstanceCommands.mm b/Chisel/Chisel/CHLObjcInstanceCommands.mm index 37c2178..3816879 100644 --- a/Chisel/Chisel/CHLObjcInstanceCommands.mm +++ b/Chisel/Chisel/CHLObjcInstanceCommands.mm @@ -173,7 +173,7 @@ void PrintInstances(const char *type, const char *pred) if (baseClass != Nil) { addMatch(baseClass); } else { - // The given class name hasn't been found, this could be a Swift class which case has + // The given class name hasn't been found, this could be a Swift class which has // a module name prefix. Loop over all classes to look for matching class names. for (auto cls : objcClasses) { // SwiftModule.ClassName