in Chisel/Chisel/CHLObjcInstanceCommands.mm [131:212]
void PrintInstances(const char *type, const char *pred)
{
NSPredicate *predicate = nil;
if (pred != nullptr && *pred != '\0') {
@try {
predicate = [NSPredicate predicateWithFormat:@(pred)];
} @catch (NSException *e) {
printf("Error: Invalid predicate; %s\n", [e reason].UTF8String);
return;
}
}
const std::unordered_set<Class> objcClasses = CHLObjcClassSet();
std::unordered_set<Class> matchClasses;
Protocol *protocol = objc_getProtocol(type);
if (protocol != nullptr && strcmp("NSObject", type) != 0) {
for (auto cls : objcClasses) {
if (conformsToProtocol(cls, protocol)) {
matchClasses.insert(cls);
}
}
}
bool exactClass = false;
if (type[0] == '*') {
exactClass = true;
++type;
}
// 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(baseClass);
} else {
for (auto cls : objcClasses) {
if (isSubclassOfClass(cls, baseClass)) {
matchClasses.insert(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 has
// a module name prefix. Loop over all classes to look for matching class names.
for (auto cls : objcClasses) {
// SwiftModule.ClassName
// ^- dot + 1
auto dot = strchr(class_getName(cls), '.');
if (dot && strcmp(type, dot + 1) == 0) {
addMatch(cls);
}
}
}
if (matchClasses.empty()) {
// TODO: Accept name of library/module, and list instances of classes defined there.
printf("Unknown type: %s\n", type);
return;
}
NSSet *keyPaths = CHLVariableKeyPaths(predicate);
auto instances = CHLScanObjcInstances(matchClasses);
unsigned int matches = 0;
for (id obj : instances) {
if (objectIsMatch(predicate, obj, objcClasses)) {
++matches;
printObject(obj, keyPaths);
}
}
if (matches > 1) {
printf("%d matches\n", matches);
}
}