void PrintInstances()

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);
  }
}