[
  {
    "path": ".gitignore",
    "content": "*.pyc\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of Conduct\nFacebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.fb.com/codeofconduct) so that you can understand what actions will and will not be tolerated."
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Chisel\nWe want to make contributing to this project as easy and transparent as\npossible.\n\n## Pull Requests\nWe actively welcome your pull requests.\n\n1. Fork the repo and create your branch from `master`. \n2. If you've added code that should be tested, add tests\n3. If you've changed APIs, update the documentation. \n4. Ensure the test suite passes. \n5. Make sure your code lints. \n6. If you haven't already, complete the Contributor License Agreement (\"CLA\").\n\n## Contributor License Agreement (\"CLA\")\nIn order to accept your pull request, we need you to submit a CLA. You only need\nto do this once to work on any of Facebook's open source projects.\n\nComplete your CLA here: <https://developers.facebook.com/opensource/cla>\n\n## Issues  \nWe use GitHub issues to track public bugs. Please ensure your description is\nclear and has sufficient instructions to be able to reproduce the issue.\n\nFacebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe\ndisclosure of security bugs. In those cases, please go through the process\noutlined on that page and do not file a public issue.\n\n## Updating Chisel in Brew (for maintainers)\nMost users have Chisel installed via Homebrew. In order to update the version they'll receive when using `brew install` or `brew update`, we have to make some manual changes.\n\n1. Create a new release in the GitHub web interface.\n2. Download the `tar.gz` for that release and run `shasum -a 256 <path>`.\n3. Copy the URL for the `.tar.gz` on the release page.\n\nRun:\n```\nbrew bump-formula-pr --strict chisel \\\n--url=<GitHub .tar.gz URL> \\\n--sha256=<output of shasum>\n```\n\nMore docs on the process are available on the [Homebrew site](https://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request).\n\nExample PRs:\n- [Bump to 2.0.1](https://github.com/Homebrew/homebrew-core/pull/59799)\n- [Bump to 2.0.0](https://github.com/Homebrew/homebrew-core/pull/50571)\n\n## License\nBy contributing to Chisel, you agree that your contributions will be licensed\nunder its MIT license.\n\n"
  },
  {
    "path": "Chisel/Chisel/CHLAllocations.c",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n#include \"CHLAllocations.h\"\n\nstatic kern_return_t reader(__unused task_t remote_task, vm_address_t remote_address, __unused vm_size_t size, void **local_memory)\n{\n  *local_memory = (void *)remote_address;\n  return KERN_SUCCESS;\n}\n\ntypedef struct {\n  CHLRangeHandler handler;\n  void *context;\n} RangeEnumeratorArgs;\n\nstatic void rangeEnumerator(__unused task_t task, void *context, __unused unsigned type, vm_range_t *ranges, unsigned int count)\n{\n  const RangeEnumeratorArgs *args = (RangeEnumeratorArgs *)context;\n  for (unsigned int i = 0; i < count; ++i) {\n    args->handler(ranges[i], args->context);\n  }\n}\n\nvoid CHLScanAllocations(CHLRangeHandler handler, void *context, const malloc_zone_t *sideZone)\n{\n  vm_address_t *zones;\n  unsigned int count;\n  malloc_get_all_zones(TASK_NULL, &reader, &zones, &count);\n\n  RangeEnumeratorArgs args = {handler, context};\n\n  for (unsigned int i = 0; i < count; ++i) {\n    malloc_zone_t *zone = (malloc_zone_t *)zones[i];\n    if (zone != sideZone) {\n      zone->introspect->enumerator(TASK_NULL, &args, MALLOC_PTR_IN_USE_RANGE_TYPE, (vm_address_t)zone, reader, rangeEnumerator);\n    }\n  }\n}\n"
  },
  {
    "path": "Chisel/Chisel/CHLAllocations.h",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n#include <malloc/malloc.h>\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\ntypedef void (*CHLRangeHandler)(vm_range_t range, void *context);\n\n// Enumerate live allocations in all malloc zones. If callers allocate memory in the handler, those\n// allocations should be within the given `sideZone`.\nvoid CHLScanAllocations(CHLRangeHandler handler, void *context, const malloc_zone_t *sideZone);\n\n#if defined(__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "Chisel/Chisel/CHLObjcInstanceCommands.h",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n@class NSPredicate;\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\n// Debugger interface for finding and printing instances of a type, with an optional predicate.\n// The predicate format is anything supported by NSPredicate.\nvoid PrintInstances(const char *type, const char *pred);\n\n#if defined(__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "Chisel/Chisel/CHLObjcInstanceCommands.mm",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n#import \"CHLObjcInstanceCommands.h\"\n\n#include <objc/runtime.h>\n#include <vector>\n\n#import <CoreFoundation/CoreFoundation.h>\n#import <Foundation/Foundation.h>\n\n#import \"CHLObjcInstances.h\"\n#import \"CHLPredicateTools.h\"\n#include \"zone_allocator.h\"\n\n#if __has_feature(objc_arc)\n#error Disable ARC for this file\n#endif\n\nstruct IsValidArgs {\n  const std::unordered_set<Class> &classSet;\n  bool isValid = true;\n};\n\nstatic void isValidObject(const void *value, void *context)\n{\n  const auto args = reinterpret_cast<IsValidArgs *>(context);\n  if (!args->isValid) {\n    return;\n  }\n\n  vm_range_t range = {(vm_address_t)value, malloc_size(value)};\n  if (CHLViableObjcInstance(range, args->classSet) == nil) {\n    args->isValid = false;\n  }\n}\n\nstatic void isValidKeyValue(const void *key, const void *value, void *context)\n{\n  const auto args = reinterpret_cast<IsValidArgs *>(context);\n  isValidObject(key, context);\n  if (args->isValid) {\n    isValidObject(value, context);\n  }\n}\n\nstatic bool predicatePrecheck(id obj, const std::unordered_set<Class> &classSet)\n{\n  IsValidArgs args{classSet};\n\n  if ([obj isKindOfClass:objc_getClass(\"__NSCFDictionary\")]) {\n    CFDictionaryApplyFunction((CFDictionaryRef)obj, &isValidKeyValue, &args);\n  } else if ([obj isKindOfClass:objc_getClass(\"__NSCFSet\")]) {\n    CFSetApplyFunction((CFSetRef)obj, &isValidObject, &args);\n  } else {\n    // Skip classes containing NSPlaceholder.\n    // TODO: Figure out better way to ignore invalid instances.\n    char *name = (char *)object_getClassName(obj);\n    while (*name == '_') ++name;\n    if (strncmp(name, \"NSPlaceholder\", sizeof(\"NSPlaceholder\") - 1) == 0) {\n      args.isValid = false;\n    }\n  }\n\n  if (!args.isValid && getenv(\"FINDINSTANCES_DEBUG\")) {\n    printf(\"%p has class %s but contains non objc data\\n\", obj, object_getClassName(obj));\n  }\n\n  return args.isValid;\n}\n\nstatic void printObject(id obj, NSSet *keyPaths) {\n  printf(\"<%s: %p\", object_getClassName(obj), obj);\n  for (NSString *keyPath in keyPaths) {\n    printf(\"; %s = %s\", keyPath.UTF8String, [[obj valueForKeyPath:keyPath] description].UTF8String);\n  }\n  printf(\">\\n\");\n}\n\nstatic bool objectIsMatch(NSPredicate *predicate, id obj, const std::unordered_set<Class> &classSet)\n{\n  if (!predicate) {\n    return true;\n  }\n\n  bool debug = getenv(\"FINDINSTANCES_DEBUG\");\n\n  if (!predicatePrecheck(obj, classSet)) {\n    if (debug) {\n      printf(\"%p has class %s but has non objc contents\\n\", obj, object_getClassName(obj));\n    }\n    return false;\n  }\n\n  @try {\n    return [predicate evaluateWithObject:obj];\n  } @catch (...) {\n    if (debug) {\n      printf(\"%p has class %s but failed predicate evaluation\\n\", obj, object_getClassName(obj));\n    }\n    return false;\n  }\n}\n\n// Function reimplementation of +[NSObject isSubclassOf:] to avoid the objc runtime side\n// effects that can happen when calling methods, like realizing classes, +initialize, etc.\nstatic bool isSubclassOfClass(Class self, Class target)\n{\n  for (auto cls = self; cls != Nil; cls = class_getSuperclass(cls)) {\n    if (cls == target) {\n      return true;\n    }\n  }\n  return false;\n}\n\n// Function reimplementation of +[NSObject conformsToProtocol:] to avoid the objc runtime side\n// effects that can happen when calling methods, like realizing classes, +initialize, etc.\nstatic bool conformsToProtocol(Class self, Protocol *protocol)\n{\n  for (auto cls = self; cls != Nil; cls = class_getSuperclass(cls)) {\n    if (class_conformsToProtocol(cls, protocol)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nvoid PrintInstances(const char *type, const char *pred)\n{\n  NSPredicate *predicate = nil;\n  if (pred != nullptr && *pred != '\\0') {\n    @try {\n      predicate = [NSPredicate predicateWithFormat:@(pred)];\n    } @catch (NSException *e) {\n      printf(\"Error: Invalid predicate; %s\\n\", [e reason].UTF8String);\n      return;\n    }\n  }\n\n  const std::unordered_set<Class> objcClasses = CHLObjcClassSet();\n  std::unordered_set<Class> matchClasses;\n\n  Protocol *protocol = objc_getProtocol(type);\n  if (protocol != nullptr && strcmp(\"NSObject\", type) != 0) {\n    for (auto cls : objcClasses) {\n      if (conformsToProtocol(cls, protocol)) {\n        matchClasses.insert(cls);\n      }\n    }\n  }\n\n  bool exactClass = false;\n  if (type[0] == '*') {\n    exactClass = true;\n    ++type;\n  }\n\n  // Helper lambda that only exists so that it can be called more than once, as in the\n  // rare case where `type` corresponds to more than one Swift class.\n  auto addMatch = [&](Class baseClass) {\n    if (exactClass) {\n      matchClasses.insert(baseClass);\n    } else {\n      for (auto cls : objcClasses) {\n        if (isSubclassOfClass(cls, baseClass)) {\n          matchClasses.insert(cls);\n        }\n      }\n    }\n  };\n\n  Class baseClass = objc_getClass(type);\n  if (baseClass != Nil) {\n    addMatch(baseClass);\n  } else {\n    // The given class name hasn't been found, this could be a Swift class which has\n    // a module name prefix. Loop over all classes to look for matching class names.\n    for (auto cls : objcClasses) {\n      // SwiftModule.ClassName\n      //             ^- dot + 1\n      auto dot = strchr(class_getName(cls), '.');\n      if (dot && strcmp(type, dot + 1) == 0) {\n        addMatch(cls);\n      }\n    }\n  }\n\n  if (matchClasses.empty()) {\n    // TODO: Accept name of library/module, and list instances of classes defined there.\n    printf(\"Unknown type: %s\\n\", type);\n    return;\n  }\n\n  NSSet *keyPaths = CHLVariableKeyPaths(predicate);\n\n  auto instances = CHLScanObjcInstances(matchClasses);\n  unsigned int matches = 0;\n\n  for (id obj : instances) {\n    if (objectIsMatch(predicate, obj, objcClasses)) {\n      ++matches;\n      printObject(obj, keyPaths);\n    }\n  }\n\n  if (matches > 1) {\n    printf(\"%d matches\\n\", matches);\n  }\n}\n"
  },
  {
    "path": "Chisel/Chisel/CHLObjcInstances.h",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n#if defined(__cplusplus)\n\n#include <malloc/malloc.h>\n#include <unordered_set>\n#include <vector>\n\n#include \"zone_allocator.h\"\n\n// Create a set containing all known Classes.\nstd::unordered_set<Class> CHLObjcClassSet();\n\n// Enumerates the heap and returns all objects that appear to be legitimate.\nstd::vector<id, zone_allocator<id>> CHLScanObjcInstances(const std::unordered_set<Class> &classSet);\n\n// Performs a number of heuristic checks on the memory range, to determine if the memory appears to\n// be a viable Objective-C object.\nid CHLViableObjcInstance(vm_range_t range, const std::unordered_set<Class> &classSet);\n\n#endif\n"
  },
  {
    "path": "Chisel/Chisel/CHLObjcInstances.mm",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n#import \"CHLObjcInstances.h\"\n\n#import <Foundation/Foundation.h>\n\n#include \"CHLAllocations.h\"\n\n#include <dlfcn.h>\n#include <objc/message.h>\n#include <objc/runtime.h>\n#include <mach-o/getsect.h>\n#if !defined(__LP64__)\nusing mach_header_t = mach_header;\n#else\nusing mach_header_t = mach_header_64;\n#endif\n\n#include <unordered_set>\n#include <vector>\n\n#if __has_feature(objc_arc)\n#error Disable ARC for this file\n#endif\n\n// Informal protocol to make it easy to call -_isDeallocating\n@interface NSObject (Private)\n- (BOOL)_isDeallocating;\n@end\n\nstatic id embeddedObjcInstance(vm_range_t range) {\n  Dl_info info;\n  bool aligned = range.address % alignof(void *) == 0;\n  uint8_t *pointer = (uint8_t *)range.address;\n  if (aligned && dladdr(pointer, &info)) {\n    unsigned long size = 0;\n    uint8_t *start = getsectiondata((mach_header_t *)info.dli_fbase, SEG_DATA, \"__cfstring\", &size);\n    uint8_t *end = start + size;\n    if (start <= pointer || pointer < end) {\n      // Found NSString/CFString constant.\n      return reinterpret_cast<id>(range.address);\n    }\n  }\n  return nil;\n}\n\n// TODO: Should this cache results instead of repeated lookups.\nbool isFixedSizeClass(Class cls) {\n  const auto meta = object_getClass(cls);\n  const auto root = objc_getMetaClass(\"NSObject\");\n\n  SEL allocs[] = { @selector(allocWithZone:), @selector(alloc) };\n  for (const auto &sel : allocs) {\n    IMP imp = class_getMethodImplementation(meta, sel);\n    if (imp != class_getMethodImplementation(root, sel)) {\n      // Class overrides NSObject alloc method, may not have fixed sizes.\n      return false;\n    }\n  }\n\n  return true;\n}\n\n// Runs a number of heuristics on the given address. Returns nil if any heuristic fails, otherwise\n// returns that address casted as an object.\n//\n// Currently the heuristics don't fully guarantee that the returned object is an actual object, but\n// when using MallocScribble=1, false positives are unlikely. Further, callers will generally do\n// higher level filtering, for example checking a value on the object, which can further eliminate\n// false positives.\n//\n// There's also one known false negative case, NSConcreteValue can store data in the malloc memory\n// beyond its instance size. Currently this false negative is allowed.\nid CHLViableObjcInstance(vm_range_t range, const std::unordered_set<Class> &classSet)\n{\n  // Check if this address points to an object embedded into Mach-O.\n  if (range.size == 0) {\n    return embeddedObjcInstance(range);\n  }\n\n  id obj = reinterpret_cast<id>(range.address);\n\n  // It's safe to call object_getClass on memory that isn't objc objects.\n  // Check that the returned Class points to an expected class.\n  Class cls = object_getClass(obj);\n  if (classSet.find(cls) == classSet.end()) {\n    return nil;\n  }\n\n  // Instance size is the byte count needed for an object's ivars, plus any padding.\n  // Allocation size is the byte count that malloc will actually allocate for instances of a Class.\n  const auto instanceSize = class_getInstanceSize(cls);\n  const auto expectedAllocationSize = malloc_good_size(instanceSize);\n  const auto extraSize = expectedAllocationSize - instanceSize;\n\n  const bool debug = getenv(\"FINDINSTANCES_DEBUG\") != NULL;\n\n  if (range.size < expectedAllocationSize) {\n    if (debug) {\n      printf(\"%p has class %s but is too small\\n\", obj, class_getName(cls));\n    }\n    return nil;\n  }\n\n  if (range.size > expectedAllocationSize && isFixedSizeClass(cls)) {\n    // Range is too big and the class has no way of allocating larger instances.\n    if (debug) {\n      printf(\"%p has fixed size class %s but is too large\\n\", obj, class_getName(cls));\n    }\n    return nil;\n  }\n\n  if (range.size == expectedAllocationSize && extraSize) {\n    // ObjC instances are allocated with calloc, memory beyond the instance size should be zeros.\n    // Some classes have been known to store data in the extra space, ex NSConcreteValue.\n    static const unsigned char ZEROS[1024] = {0};\n    auto extra = object_getIndexedIvars(obj);\n    auto compareSize = std::min(extraSize, sizeof(ZEROS));\n    if (memcmp(extra, &ZEROS, compareSize) != 0) {\n      if (debug) {\n        printf(\"%p has class %s but has non-zero memory\\n\", obj, class_getName(cls));\n      }\n      return nil;\n    }\n  }\n\n  // Ignore deallocating objects.\n  if ([obj _isDeallocating]) {\n    return nil;\n  }\n\n  return obj;\n}\n\nstruct FindViableObjcInstancesArgs {\n  const std::unordered_set<Class> &classSet;\n  std::vector<id, zone_allocator<id>> &instances;\n};\n\nstatic void findViableObjcInstances(vm_range_t range, void *context)\n{\n  const auto args = reinterpret_cast<FindViableObjcInstancesArgs *>(context);\n  id obj = CHLViableObjcInstance(range, args->classSet);\n  if (obj != nil) {\n    args->instances.push_back(obj);\n  }\n}\n\nstd::vector<id, zone_allocator<id>> CHLScanObjcInstances(const std::unordered_set<Class> &classSet)\n{\n  std::vector<id, zone_allocator<id>> instances;\n  FindViableObjcInstancesArgs args{classSet, instances};\n  CHLScanAllocations(&findViableObjcInstances, &args, instances.get_allocator().zone());\n  return instances;\n}\n\nstd::unordered_set<Class> CHLObjcClassSet()\n{\n  unsigned int count = 0;\n  auto classList = objc_copyClassList(&count);\n  std::unordered_set<Class> classSet{classList, classList + count, count};\n  free(classList);\n  return classSet;\n}\n"
  },
  {
    "path": "Chisel/Chisel/CHLPredicateTools.h",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n#import <Foundation/Foundation.h>\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\nNSSet *CHLVariableKeyPaths(NSPredicate *predicate);\n\n#if defined(__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "Chisel/Chisel/CHLPredicateTools.m",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n#import \"CHLPredicateTools.h\"\n\nstatic bool isEqualToConstantComparison(NSComparisonPredicate *predicate)\n{\n  bool equality = predicate.predicateOperatorType == NSEqualToPredicateOperatorType;\n  bool direct = predicate.comparisonPredicateModifier == NSDirectPredicateModifier;\n  bool constantLeft = predicate.leftExpression.expressionType == NSConstantValueExpressionType;\n  bool constantRight = predicate.rightExpression.expressionType == NSConstantValueExpressionType;\n  return equality && direct && (constantLeft || constantRight);\n}\n\nNSSet *CHLVariableKeyPaths(NSPredicate *predicate)\n{\n  if (predicate == nil) {\n    return nil;\n  }\n\n  NSMutableSet *keyPaths = [NSMutableSet new];\n\n  NSMutableArray *predicateStack = [NSMutableArray arrayWithObject:predicate];\n  while (predicateStack.count > 0) {\n    NSPredicate *subpredicate = [predicateStack lastObject];\n    [predicateStack removeLastObject];\n\n    if ([subpredicate isKindOfClass:[NSCompoundPredicate class]]) {\n      NSCompoundPredicate *compoundPredicate = (NSCompoundPredicate *)subpredicate;\n      [predicateStack addObjectsFromArray:compoundPredicate.subpredicates];\n      continue;\n    }\n\n    if ([subpredicate isKindOfClass:[NSComparisonPredicate class]]) {\n      NSComparisonPredicate *comparisonPredicate = (NSComparisonPredicate *)subpredicate;\n\n      if (isEqualToConstantComparison(comparisonPredicate)) {\n        // Keypaths equal to constants are not variable. Skip these to not be noisy.\n        // ex `username == \"jonalan\"` or `alpha == 0`\n        continue;\n      }\n\n      // TODO: Handle NSFunctionExpressionType\n      if (comparisonPredicate.leftExpression.expressionType == NSKeyPathExpressionType) {\n        [keyPaths addObject:comparisonPredicate.leftExpression.keyPath];\n      }\n      if (comparisonPredicate.rightExpression.expressionType == NSKeyPathExpressionType) {\n        [keyPaths addObject:comparisonPredicate.rightExpression.keyPath];\n      }\n    }\n  }\n\n  return keyPaths;\n}\n"
  },
  {
    "path": "Chisel/Chisel/Chisel.h",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n#import <UIKit/UIKit.h>\n\n//! Project version number for Chisel.\nFOUNDATION_EXPORT double ChiselVersionNumber;\n\n//! Project version string for Chisel.\nFOUNDATION_EXPORT const unsigned char ChiselVersionString[];\n\n// In this header, you should import all the public headers of your framework using statements like #import <Chisel/PublicHeader.h>\n"
  },
  {
    "path": "Chisel/Chisel/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>FMWK</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>NSPrincipalClass</key>\n\t<string></string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Chisel/Chisel/zone_allocator.h",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n#pragma once\n\n#include <memory>\n\n#include <malloc/malloc.h>\n\ntemplate <typename T>\nstruct zone_allocator {\n  using value_type = T;\n\n  T *allocate(std::size_t n)\n  {\n    auto allocation = malloc_zone_malloc(_zone.get(), n * sizeof(T));\n    return reinterpret_cast<T *>(allocation);\n  }\n\n  void deallocate(T *p, __unused std::size_t n)\n  {\n    malloc_zone_free(_zone.get(), p);\n  }\n\n  const malloc_zone_t *zone() const\n  {\n    return _zone.get();\n  }\n\nprivate:\n  std::shared_ptr<malloc_zone_t> _zone{malloc_create_zone(0x200, 0), &malloc_destroy_zone};\n};\n\ntemplate <typename T, typename U>\nbool operator==(const zone_allocator<T> &a, const zone_allocator<T> &b) noexcept\n{\n  return a.zone() == b.zone();\n}\n\ntemplate <typename T, typename U>\nbool operator!=(const zone_allocator<T> &a, const zone_allocator<T> &b) noexcept\n{\n  return !(a == b);\n}\n"
  },
  {
    "path": "Chisel/Chisel-macOS/Chisel_macOS.h",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n#import <Cocoa/Cocoa.h>\n\n//! Project version number for Chisel_macOS.\nFOUNDATION_EXPORT double Chisel_macOSVersionNumber;\n\n//! Project version string for Chisel_macOS.\nFOUNDATION_EXPORT const unsigned char Chisel_macOSVersionString[];\n\n// In this header, you should import all the public headers of your framework using statements like #import <Chisel_macOS/PublicHeader.h>\n\n\n"
  },
  {
    "path": "Chisel/Chisel-macOS/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>FMWK</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>NSPrincipalClass</key>\n\t<string></string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Chisel/Chisel.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t70D1EACB20FD9D4A004CDB3D /* Chisel_macOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 70D1EAC920FD9D4A004CDB3D /* Chisel_macOS.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t70D1EACF20FD9D82004CDB3D /* CHLPredicateTools.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A20C4B21DFDB8D200C89959 /* CHLPredicateTools.m */; };\n\t\t70D1EAD020FD9D85004CDB3D /* CHLObjcInstanceCommands.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A04088B1DF9A2C7009C5BFA /* CHLObjcInstanceCommands.mm */; };\n\t\t70D1EAD120FD9D88004CDB3D /* CHLObjcInstances.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7ABD17AA1DF7FCF9006118F8 /* CHLObjcInstances.mm */; };\n\t\t70D1EAD220FD9D8C004CDB3D /* CHLAllocations.c in Sources */ = {isa = PBXBuildFile; fileRef = 7ABD17A61DF7F9FD006118F8 /* CHLAllocations.c */; };\n\t\t7A04088C1DF9A2C7009C5BFA /* CHLObjcInstanceCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A04088A1DF9A2C7009C5BFA /* CHLObjcInstanceCommands.h */; };\n\t\t7A04088D1DF9A2C7009C5BFA /* CHLObjcInstanceCommands.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A04088B1DF9A2C7009C5BFA /* CHLObjcInstanceCommands.mm */; };\n\t\t7A20C4B31DFDB8D200C89959 /* CHLPredicateTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A20C4B11DFDB8D200C89959 /* CHLPredicateTools.h */; };\n\t\t7A20C4B41DFDB8D200C89959 /* CHLPredicateTools.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A20C4B21DFDB8D200C89959 /* CHLPredicateTools.m */; };\n\t\t7ABD17951DF7F998006118F8 /* Chisel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7ABD178B1DF7F998006118F8 /* Chisel.framework */; };\n\t\t7ABD179A1DF7F998006118F8 /* ChiselTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7ABD17991DF7F998006118F8 /* ChiselTests.m */; };\n\t\t7ABD179C1DF7F998006118F8 /* Chisel.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ABD178E1DF7F998006118F8 /* Chisel.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t7ABD17A71DF7F9FD006118F8 /* CHLAllocations.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ABD17A51DF7F9FD006118F8 /* CHLAllocations.h */; };\n\t\t7ABD17A81DF7F9FD006118F8 /* CHLAllocations.c in Sources */ = {isa = PBXBuildFile; fileRef = 7ABD17A61DF7F9FD006118F8 /* CHLAllocations.c */; };\n\t\t7ABD17AB1DF7FCF9006118F8 /* CHLObjcInstances.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ABD17A91DF7FCF9006118F8 /* CHLObjcInstances.h */; };\n\t\t7ABD17AC1DF7FCF9006118F8 /* CHLObjcInstances.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7ABD17AA1DF7FCF9006118F8 /* CHLObjcInstances.mm */; };\n\t\t7ABD17AF1DF88520006118F8 /* zone_allocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ABD17AD1DF88520006118F8 /* zone_allocator.h */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t7ABD17961DF7F998006118F8 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7ABD17821DF7F998006118F8 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 7ABD178A1DF7F998006118F8;\n\t\t\tremoteInfo = Chisel;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t70D1EAC720FD9D4A004CDB3D /* Chisel_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Chisel_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t70D1EAC920FD9D4A004CDB3D /* Chisel_macOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Chisel_macOS.h; sourceTree = \"<group>\"; };\n\t\t70D1EACA20FD9D4A004CDB3D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t7A04088A1DF9A2C7009C5BFA /* CHLObjcInstanceCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHLObjcInstanceCommands.h; sourceTree = \"<group>\"; };\n\t\t7A04088B1DF9A2C7009C5BFA /* CHLObjcInstanceCommands.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHLObjcInstanceCommands.mm; sourceTree = \"<group>\"; };\n\t\t7A20C4B11DFDB8D200C89959 /* CHLPredicateTools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHLPredicateTools.h; sourceTree = \"<group>\"; };\n\t\t7A20C4B21DFDB8D200C89959 /* CHLPredicateTools.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CHLPredicateTools.m; sourceTree = \"<group>\"; };\n\t\t7ABD178B1DF7F998006118F8 /* Chisel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Chisel.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t7ABD178E1DF7F998006118F8 /* Chisel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Chisel.h; sourceTree = \"<group>\"; };\n\t\t7ABD178F1DF7F998006118F8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t7ABD17941DF7F998006118F8 /* ChiselTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ChiselTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t7ABD17991DF7F998006118F8 /* ChiselTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChiselTests.m; sourceTree = \"<group>\"; };\n\t\t7ABD179B1DF7F998006118F8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t7ABD17A51DF7F9FD006118F8 /* CHLAllocations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHLAllocations.h; sourceTree = \"<group>\"; };\n\t\t7ABD17A61DF7F9FD006118F8 /* CHLAllocations.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CHLAllocations.c; sourceTree = \"<group>\"; };\n\t\t7ABD17A91DF7FCF9006118F8 /* CHLObjcInstances.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CHLObjcInstances.h; sourceTree = \"<group>\"; };\n\t\t7ABD17AA1DF7FCF9006118F8 /* CHLObjcInstances.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CHLObjcInstances.mm; sourceTree = \"<group>\"; };\n\t\t7ABD17AD1DF88520006118F8 /* zone_allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zone_allocator.h; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t70D1EAC320FD9D4A004CDB3D /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t7ABD17871DF7F998006118F8 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t7ABD17911DF7F998006118F8 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t7ABD17951DF7F998006118F8 /* Chisel.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t70D1EAC820FD9D4A004CDB3D /* Chisel-macOS */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t70D1EAC920FD9D4A004CDB3D /* Chisel_macOS.h */,\n\t\t\t\t70D1EACA20FD9D4A004CDB3D /* Info.plist */,\n\t\t\t);\n\t\t\tpath = \"Chisel-macOS\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7ABD17811DF7F998006118F8 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7ABD178D1DF7F998006118F8 /* Chisel */,\n\t\t\t\t7ABD17981DF7F998006118F8 /* ChiselTests */,\n\t\t\t\t70D1EAC820FD9D4A004CDB3D /* Chisel-macOS */,\n\t\t\t\t7ABD178C1DF7F998006118F8 /* Products */,\n\t\t\t);\n\t\t\tindentWidth = 2;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7ABD178C1DF7F998006118F8 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7ABD178B1DF7F998006118F8 /* Chisel.framework */,\n\t\t\t\t7ABD17941DF7F998006118F8 /* ChiselTests.xctest */,\n\t\t\t\t70D1EAC720FD9D4A004CDB3D /* Chisel_macOS.framework */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7ABD178D1DF7F998006118F8 /* Chisel */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7ABD178E1DF7F998006118F8 /* Chisel.h */,\n\t\t\t\t7ABD178F1DF7F998006118F8 /* Info.plist */,\n\t\t\t\t7ABD17AD1DF88520006118F8 /* zone_allocator.h */,\n\t\t\t\t7ABD17A51DF7F9FD006118F8 /* CHLAllocations.h */,\n\t\t\t\t7ABD17A61DF7F9FD006118F8 /* CHLAllocations.c */,\n\t\t\t\t7ABD17A91DF7FCF9006118F8 /* CHLObjcInstances.h */,\n\t\t\t\t7ABD17AA1DF7FCF9006118F8 /* CHLObjcInstances.mm */,\n\t\t\t\t7A04088A1DF9A2C7009C5BFA /* CHLObjcInstanceCommands.h */,\n\t\t\t\t7A04088B1DF9A2C7009C5BFA /* CHLObjcInstanceCommands.mm */,\n\t\t\t\t7A20C4B11DFDB8D200C89959 /* CHLPredicateTools.h */,\n\t\t\t\t7A20C4B21DFDB8D200C89959 /* CHLPredicateTools.m */,\n\t\t\t);\n\t\t\tpath = Chisel;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7ABD17981DF7F998006118F8 /* ChiselTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7ABD17991DF7F998006118F8 /* ChiselTests.m */,\n\t\t\t\t7ABD179B1DF7F998006118F8 /* Info.plist */,\n\t\t\t);\n\t\t\tpath = ChiselTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXHeadersBuildPhase section */\n\t\t70D1EAC420FD9D4A004CDB3D /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t70D1EACB20FD9D4A004CDB3D /* Chisel_macOS.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t7ABD17881DF7F998006118F8 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t7ABD17A71DF7F9FD006118F8 /* CHLAllocations.h in Headers */,\n\t\t\t\t7ABD179C1DF7F998006118F8 /* Chisel.h in Headers */,\n\t\t\t\t7A20C4B31DFDB8D200C89959 /* CHLPredicateTools.h in Headers */,\n\t\t\t\t7A04088C1DF9A2C7009C5BFA /* CHLObjcInstanceCommands.h in Headers */,\n\t\t\t\t7ABD17AF1DF88520006118F8 /* zone_allocator.h in Headers */,\n\t\t\t\t7ABD17AB1DF7FCF9006118F8 /* CHLObjcInstances.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXHeadersBuildPhase section */\n\n/* Begin PBXNativeTarget section */\n\t\t70D1EAC620FD9D4A004CDB3D /* Chisel-macOS */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 70D1EACE20FD9D4A004CDB3D /* Build configuration list for PBXNativeTarget \"Chisel-macOS\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t70D1EAC220FD9D4A004CDB3D /* Sources */,\n\t\t\t\t70D1EAC320FD9D4A004CDB3D /* Frameworks */,\n\t\t\t\t70D1EAC420FD9D4A004CDB3D /* Headers */,\n\t\t\t\t70D1EAC520FD9D4A004CDB3D /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = \"Chisel-macOS\";\n\t\t\tproductName = \"Chisel-macOS\";\n\t\t\tproductReference = 70D1EAC720FD9D4A004CDB3D /* Chisel_macOS.framework */;\n\t\t\tproductType = \"com.apple.product-type.framework\";\n\t\t};\n\t\t7ABD178A1DF7F998006118F8 /* Chisel */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 7ABD179F1DF7F998006118F8 /* Build configuration list for PBXNativeTarget \"Chisel\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t7ABD17861DF7F998006118F8 /* Sources */,\n\t\t\t\t7ABD17871DF7F998006118F8 /* Frameworks */,\n\t\t\t\t7ABD17881DF7F998006118F8 /* Headers */,\n\t\t\t\t7ABD17891DF7F998006118F8 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = Chisel;\n\t\t\tproductName = Chisel;\n\t\t\tproductReference = 7ABD178B1DF7F998006118F8 /* Chisel.framework */;\n\t\t\tproductType = \"com.apple.product-type.framework\";\n\t\t};\n\t\t7ABD17931DF7F998006118F8 /* ChiselTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 7ABD17A21DF7F998006118F8 /* Build configuration list for PBXNativeTarget \"ChiselTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t7ABD17901DF7F998006118F8 /* Sources */,\n\t\t\t\t7ABD17911DF7F998006118F8 /* Frameworks */,\n\t\t\t\t7ABD17921DF7F998006118F8 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t7ABD17971DF7F998006118F8 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = ChiselTests;\n\t\t\tproductName = ChiselTests;\n\t\t\tproductReference = 7ABD17941DF7F998006118F8 /* ChiselTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t7ABD17821DF7F998006118F8 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0810;\n\t\t\t\tORGANIZATIONNAME = Facebook;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t70D1EAC620FD9D4A004CDB3D = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 9.4.1;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t\t7ABD178A1DF7F998006118F8 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 8.1;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t\t7ABD17931DF7F998006118F8 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 8.1;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 7ABD17851DF7F998006118F8 /* Build configuration list for PBXProject \"Chisel\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = 7ABD17811DF7F998006118F8;\n\t\t\tproductRefGroup = 7ABD178C1DF7F998006118F8 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t7ABD178A1DF7F998006118F8 /* Chisel */,\n\t\t\t\t7ABD17931DF7F998006118F8 /* ChiselTests */,\n\t\t\t\t70D1EAC620FD9D4A004CDB3D /* Chisel-macOS */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t70D1EAC520FD9D4A004CDB3D /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t7ABD17891DF7F998006118F8 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t7ABD17921DF7F998006118F8 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t70D1EAC220FD9D4A004CDB3D /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t70D1EAD120FD9D88004CDB3D /* CHLObjcInstances.mm in Sources */,\n\t\t\t\t70D1EAD220FD9D8C004CDB3D /* CHLAllocations.c in Sources */,\n\t\t\t\t70D1EAD020FD9D85004CDB3D /* CHLObjcInstanceCommands.mm in Sources */,\n\t\t\t\t70D1EACF20FD9D82004CDB3D /* CHLPredicateTools.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t7ABD17861DF7F998006118F8 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t7ABD17A81DF7F9FD006118F8 /* CHLAllocations.c in Sources */,\n\t\t\t\t7ABD17AC1DF7FCF9006118F8 /* CHLObjcInstances.mm in Sources */,\n\t\t\t\t7A04088D1DF9A2C7009C5BFA /* CHLObjcInstanceCommands.mm in Sources */,\n\t\t\t\t7A20C4B41DFDB8D200C89959 /* CHLPredicateTools.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t7ABD17901DF7F998006118F8 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t7ABD179A1DF7F998006118F8 /* ChiselTests.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t7ABD17971DF7F998006118F8 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 7ABD178A1DF7F998006118F8 /* Chisel */;\n\t\t\ttargetProxy = 7ABD17961DF7F998006118F8 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin XCBuildConfiguration section */\n\t\t70D1EACC20FD9D4A004CDB3D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++14\";\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_VERSION = A;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tINFOPLIST_FILE = \"Chisel-macOS/Info.plist\";\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.13;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.facebook.Chisel-macOS\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME:c99extidentifier)\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 4.0;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t70D1EACD20FD9D4A004CDB3D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++14\";\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_VERSION = A;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tINFOPLIST_FILE = \"Chisel-macOS/Info.plist\";\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.13;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.facebook.Chisel-macOS\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME:c99extidentifier)\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Owholemodule\";\n\t\t\t\tSWIFT_VERSION = 4.0;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t7ABD179D1DF7F998006118F8 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++14\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = NO;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVES = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = c11;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 10.1;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t7ABD179E1DF7F998006118F8 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++14\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = NO;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVES = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = c11;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 10.1;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t7ABD17A01DF7F998006118F8 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tINFOPLIST_FILE = Chisel/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.facebook.Chisel;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = NO;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t7ABD17A11DF7F998006118F8 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tINFOPLIST_FILE = Chisel/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.facebook.Chisel;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = NO;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t7ABD17A31DF7F998006118F8 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = ChiselTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.facebook.ChiselTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t7ABD17A41DF7F998006118F8 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = ChiselTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.facebook.ChiselTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t70D1EACE20FD9D4A004CDB3D /* Build configuration list for PBXNativeTarget \"Chisel-macOS\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t70D1EACC20FD9D4A004CDB3D /* Debug */,\n\t\t\t\t70D1EACD20FD9D4A004CDB3D /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t7ABD17851DF7F998006118F8 /* Build configuration list for PBXProject \"Chisel\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t7ABD179D1DF7F998006118F8 /* Debug */,\n\t\t\t\t7ABD179E1DF7F998006118F8 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t7ABD179F1DF7F998006118F8 /* Build configuration list for PBXNativeTarget \"Chisel\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t7ABD17A01DF7F998006118F8 /* Debug */,\n\t\t\t\t7ABD17A11DF7F998006118F8 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t7ABD17A21DF7F998006118F8 /* Build configuration list for PBXNativeTarget \"ChiselTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t7ABD17A31DF7F998006118F8 /* Debug */,\n\t\t\t\t7ABD17A41DF7F998006118F8 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 7ABD17821DF7F998006118F8 /* Project object */;\n}\n"
  },
  {
    "path": "Chisel/Chisel.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:Chisel.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Chisel/Chisel.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Chisel/Chisel.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>BuildSystemType</key>\n\t<string>Original</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Chisel/Chisel.xcodeproj/xcshareddata/xcschemes/Chisel.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0920\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"7ABD178A1DF7F998006118F8\"\n               BuildableName = \"Chisel.framework\"\n               BlueprintName = \"Chisel\"\n               ReferencedContainer = \"container:Chisel.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"7ABD17931DF7F998006118F8\"\n               BuildableName = \"ChiselTests.xctest\"\n               BlueprintName = \"ChiselTests\"\n               ReferencedContainer = \"container:Chisel.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"7ABD178A1DF7F998006118F8\"\n            BuildableName = \"Chisel.framework\"\n            BlueprintName = \"Chisel\"\n            ReferencedContainer = \"container:Chisel.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"7ABD178A1DF7F998006118F8\"\n            BuildableName = \"Chisel.framework\"\n            BlueprintName = \"Chisel\"\n            ReferencedContainer = \"container:Chisel.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"7ABD178A1DF7F998006118F8\"\n            BuildableName = \"Chisel.framework\"\n            BlueprintName = \"Chisel\"\n            ReferencedContainer = \"container:Chisel.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "Chisel/ChiselTests/ChiselTests.m",
    "content": "// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n//\n// This source code is licensed under the MIT license found in the\n// LICENSE file in the root directory of this source tree.\n\n#import <XCTest/XCTest.h>\n\n@interface ChiselTests : XCTestCase\n\n@end\n\n@implementation ChiselTests\n\n- (void)setUp {\n    [super setUp];\n    // Put setup code here. This method is called before the invocation of each test method in the class.\n}\n\n- (void)tearDown {\n    // Put teardown code here. This method is called after the invocation of each test method in the class.\n    [super tearDown];\n}\n\n- (void)testExample {\n    // This is an example of a functional test case.\n    // Use XCTAssert and related functions to verify your tests produce the correct results.\n}\n\n- (void)testPerformanceExample {\n    // This is an example of a performance test case.\n    [self measureBlock:^{\n        // Put the code you want to measure the time of here.\n    }];\n}\n\n@end\n"
  },
  {
    "path": "Chisel/ChiselTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Chisel/Makefile",
    "content": "PREFIX ?= /usr/local/lib\n\nexport INSTALL_NAME =\nifneq ($(LD_DYLIB_INSTALL_NAME),)\n\tINSTALL_NAME = \"LD_DYLIB_INSTALL_NAME=$(LD_DYLIB_INSTALL_NAME)\"\nendif\n\ninstall:\n\txcodebuild \\\n\t\t-scheme Chisel \\\n\t\t-configuration Release \\\n\t\t-sdk iphonesimulator \\\n\t\tinstall \\\n\t\t$(INSTALL_NAME) \\\n\t\tDSTROOT=/ \\\n\t\tINSTALL_PATH=\"$(PREFIX)\"\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) Facebook, Inc. and its affiliates.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# Chisel\n`Chisel` is a collection of `LLDB` commands to assist in the debugging of iOS apps.\n\n[[Installation](#installation) &bull; [Commands](#commands) &bull; [Custom Commands](#custom-commands) &bull; [Development Workflow](#development-workflow) [Contributing](#contributing) &bull; [License](#license)]\n\nFor a comprehensive overview of LLDB, and how Chisel complements it, read Ari Grant's [Dancing in the Debugger — A Waltz with LLDB](http://www.objc.io/issue-19/lldb-debugging.html) in issue 19 of [objc.io](http://www.objc.io/).\n\n## Installation\n\n```shell\nbrew update\nbrew install chisel\n```\n\nif `.lldbinit` file doesn't exist you can create it & open it by tapping on the terminal\n\n ```shell\n touch .lldbinit\n open .lldbinit\n```\n\nThen add the following line to your `~/.lldbinit` file.\n\n```Python\n# ~/.lldbinit\n...\ncommand script import /usr/local/opt/chisel/libexec/fbchisellldb.py\n```\n\n* Note that if you are installing on an M1 Mac, the path above should be `/opt/homebrew/opt/chisel/libexec/fbchisellldb.py` instead.\n\nAlternatively, download chisel and add the following line to your _~/.lldbinit_ file.\n\n```Python\n# ~/.lldbinit\n...\ncommand script import /path/to/fbchisellldb.py\n\n```\n\nThe commands will be available the next time `Xcode` starts.\n\n## Commands\nThere are many commands; here's a few:\n*(Compatibility with iOS/Mac indicated at right)*\n\n|Command          |Description     |iOS    |OS X   |\n|-----------------|----------------|-------|-------|\n|pviews           |Print the recursive view description for the key window.|Yes|Yes|\n|pvc              |Print the recursive view controller description for the key window.|Yes|No|\n|visualize        |Open a `UIImage`, `CGImageRef`, `UIView`, `CALayer`, `NSData` (of an image), `UIColor`, `CIColor`, `CIImage`, `CGColorRef` or `CVPixelBuffer` in Preview.app on your Mac.|Yes|No|\n|fv               |Find a view in the hierarchy whose class name matches the provided regex.|Yes|No|\n|fvc              |Find a view controller in the hierarchy whose class name matches the provided regex.|Yes|No|\n|show/hide        |Show or hide the given view or layer. You don't even have to continue the process to see the changes!|Yes|Yes|\n|mask/unmask      |Overlay a view or layer with a transparent rectangle to visualize where it is.|Yes|No|\n|border/unborder  |Add a border to a view or layer to visualize where it is.|Yes|Yes|\n|caflush          |Flush the render server (equivalent to a \"repaint\" if no animations are in-flight).|Yes|Yes|\n|bmessage         |Set a symbolic breakpoint on the method of a class or the method of an instance without worrying which class in the hierarchy actually implements the method.|Yes|Yes|\n|wivar            |Set a watchpoint on an instance variable of an object.|Yes|Yes|\n|presponder       |Print the responder chain starting from the given object.|Yes|Yes|\n|...              |... and many more!|\n\nTo see the list of **all** of the commands execute the help command in `LLDB` or go to the [Wiki](https://github.com/facebook/chisel/wiki).\n\n```Python\n(lldb) help\nThe following is a list of built-in, permanent debugger commands:\n...\n\nThe following is a list of your current user-defined commands:\n...\n```\n\nThe bottom list contains all the commands sourced from `Chisel`.\n\nYou can also inspect a specific command by passing its name as an argument to the help command (as with all other `LLDB` commands).\n\n```\n(lldb) help border\nDraws a border around <viewOrLayer>. Color and width can be optionally provided.\n\nArguments:\n  <viewOrLayer>; Type: UIView*; The view to border.\n\nOptions:\n  --color/-c <color>; Type: string; A color name such as 'red', 'green', 'magenta', etc.\n  --width/-w <width>; Type: CGFloat; Desired width of border.\n\nSyntax: border [--color=color] [--width=width] <viewOrLayer>\n```\n\nAll of the commands provided by `Chisel` come with verbose help. Be sure to read it when in doubt!\n\n## Custom Commands\nYou can add local, custom commands. Here's a contrived example.\n\n```python\n#!/usr/bin/python\n# Example file with custom commands, located at /magical/commands/example.py\n\nimport lldb\nimport fbchisellldbbase as fb\n\ndef lldbcommands():\n  return [ PrintKeyWindowLevel() ]\n\nclass PrintKeyWindowLevel(fb.FBCommand):\n  def name(self):\n    return 'pkeywinlevel'\n\n  def description(self):\n    return 'An incredibly contrived command that prints the window level of the key window.'\n\n  def run(self, arguments, options):\n    # It's a good habit to explicitly cast the type of all return\n    # values and arguments. LLDB can't always find them on its own.\n    lldb.debugger.HandleCommand('p (CGFloat)[(id)[(id)[UIApplication sharedApplication] keyWindow] windowLevel]')\n```\n\nThen all that's left is to source the commands in lldbinit. `Chisel` has a python function just for this, _loadCommandsInDirectory_ in the _fbobjclldb.py_ module.\n\n```Python\n# ~/.lldbinit\n...\ncommand script import /path/to/fbobjclldb.py\nscript fbobjclldb.loadCommandsInDirectory('/magical/commands/')\n\n```\n\nThere's also builtin support to make it super easy to specify the arguments and options that a command takes. See the _border_ and _pinvocation_ commands for example use.\n\n## Development Workflow\nDeveloping commands, whether for local use or contributing to `Chisel` directly, both follow the same workflow. Create a command as described in the [Custom Commands](#custom-commands) section and then\n\n1. Start `LLDB`\n2. Reach a breakpoint (or simply pause execution via the pause button in `Xcode`'s debug bar or `process interrupt` if attached directly)\n3. Execute `command source ~/.lldbinit` in LLDB to source the commands\n4. Run the command you are working on\n5. Modify the command\n6. Optionally run `script reload(modulename)`\n7. Repeat steps 3-6 until the command becomes a source of happiness\n\n## Contributing\nPlease contribute any generic commands that you make. If it helps you then it will likely help many others! :D See `CONTRIBUTING.md` to learn how to contribute.\n\n## License\n`Chisel` is MIT-licensed. See `LICENSE`.\n"
  },
  {
    "path": "commands/FBAccessibilityCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport os\nimport re\n\nimport fbchisellldbbase as fb\nimport fbchisellldbobjecthelpers as objHelpers\n\n\n# This is the key corresponding to accessibility label in\n# _accessibilityElementsInContainer:\nACCESSIBILITY_LABEL_KEY = 2001\n\n\ndef lldbcommands():\n    return [\n        FBPrintAccessibilityLabels(),\n        FBPrintAccessibilityIdentifiers(),\n        FBFindViewByAccessibilityLabelCommand(),\n    ]\n\n\nclass FBPrintAccessibilityLabels(fb.FBCommand):\n    def name(self):\n        return \"pa11y\"\n\n    def description(self):\n        return \"Print accessibility labels of all views in hierarchy of <aView>\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"aView\",\n                type=\"UIView*\",\n                help=\"The view to print the hierarchy of.\",\n                default=\"(id)[[UIApplication sharedApplication] keyWindow]\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        forceStartAccessibilityServer()\n        printAccessibilityHierarchy(arguments[0])\n\n\nclass FBPrintAccessibilityIdentifiers(fb.FBCommand):\n    def name(self):\n        return \"pa11yi\"\n\n    def description(self):\n        return \"Print accessibility identifiers of all views in hierarchy of <aView>\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"aView\",\n                type=\"UIView*\",\n                help=\"The view to print the hierarchy of.\",\n                default=\"(id)[[UIApplication sharedApplication] keyWindow]\",\n            )\n        ]\n\n    def run(self, arguments, option):\n        forceStartAccessibilityServer()\n        printAccessibilityIdentifiersHierarchy(arguments[0])\n\n\nclass FBFindViewByAccessibilityLabelCommand(fb.FBCommand):\n    def name(self):\n        return \"fa11y\"\n\n    def description(self):\n        return (\n            \"Find the views whose accessibility labels match labelRegex \"\n            \"and puts the address of the first result on the clipboard.\"\n        )\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"labelRegex\",\n                type=\"string\",\n                help=\"The accessibility label regex to search the view hierarchy for.\",\n            )\n        ]\n\n    def accessibilityGrepHierarchy(self, view, needle):\n        a11yLabel = accessibilityLabel(view)\n        # if we don't have any accessibility string - we should have some children\n        if int(a11yLabel.GetValue(), 16) == 0:\n            # We call private method that gives back all visible accessibility children\n            # for view iOS 10 and higher\n            if fb.evaluateBooleanExpression(\n                \"[UIView respondsToSelector:@selector(_accessibilityElementsAndContainersDescendingFromViews:options:sorted:)]\"\n            ):\n                accessibilityElements = fb.evaluateObjectExpression(\n                    \"[UIView _accessibilityElementsAndContainersDescendingFromViews:@[(id)%s] options:0 sorted:NO]\"\n                    % view\n                )\n            else:\n                accessibilityElements = fb.evaluateObjectExpression(\n                    \"[[[UIApplication sharedApplication] keyWindow] _accessibilityElementsInContainer:0 topLevel:%s includeKB:0]\"\n                    % view\n                )\n            accessibilityElementsCount = fb.evaluateIntegerExpression(\n                \"[%s count]\" % accessibilityElements\n            )\n            for index in range(0, accessibilityElementsCount):\n                subview = fb.evaluateObjectExpression(\n                    \"[%s objectAtIndex:%i]\" % (accessibilityElements, index)\n                )\n                self.accessibilityGrepHierarchy(subview, needle)\n        elif re.match(\n            r\".*\" + needle + \".*\", a11yLabel.GetObjectDescription(), re.IGNORECASE\n        ):\n            classDesc = objHelpers.className(view)\n            print(\n                \"({} {}) {}\".format(classDesc, view, a11yLabel.GetObjectDescription())\n            )\n\n            # First element that is found is copied to clipboard\n            if not self.foundElement:\n                self.foundElement = True\n                cmd = 'echo %s | tr -d \"\\n\" | pbcopy' % view\n                os.system(cmd)\n\n    def run(self, arguments, options):\n        forceStartAccessibilityServer()\n        rootView = fb.evaluateObjectExpression(\n            \"[[UIApplication sharedApplication] keyWindow]\"\n        )\n        self.foundElement = False\n        self.accessibilityGrepHierarchy(rootView, arguments[0])\n\n\ndef isRunningInSimulator():\n    return (\n        fb.evaluateExpressionValue(\"(id)[[UIDevice currentDevice] model]\")\n        .GetObjectDescription()\n        .lower()\n        .find(\"simulator\")\n        >= 0\n    ) or (\n        fb.evaluateExpressionValue(\"(id)[[UIDevice currentDevice] name]\")\n        .GetObjectDescription()\n        .lower()\n        .find(\"simulator\")\n        >= 0\n    )\n\n\ndef forceStartAccessibilityServer():\n    # We try to start accessibility server only if we don't have needed method active\n    if not fb.evaluateBooleanExpression(\n        \"[UIView instancesRespondToSelector:@selector(_accessibilityElementsInContainer:)]\"\n    ):\n        # Starting accessibility server is different for simulator and device\n        if isRunningInSimulator():\n            fb.evaluateEffect(\n                \"[[UIApplication sharedApplication] accessibilityActivate]\"\n            )\n        else:\n            fb.evaluateEffect(\n                \"[[[UIApplication sharedApplication] _accessibilityBundlePrincipalClass] _accessibilityStartServer]\"\n            )\n\n\ndef accessibilityLabel(view):\n    # using Apple private API to get real value of accessibility string for element.\n    return fb.evaluateExpressionValue(\n        \"(id)[%s accessibilityAttributeValue:%i]\" % (view, ACCESSIBILITY_LABEL_KEY),\n        False,\n    )\n\n\ndef accessibilityIdentifier(view):\n    return fb.evaluateExpressionValue(\n        \"(id)[{} accessibilityIdentifier]\".format(view), False\n    )\n\n\ndef accessibilityElements(view):\n    if fb.evaluateBooleanExpression(\n        \"[UIView instancesRespondToSelector:@selector(accessibilityElements)]\"\n    ):\n        a11yElements = fb.evaluateExpression(\n            \"(id)[%s accessibilityElements]\" % view, False\n        )\n        if int(a11yElements, 16) != 0:\n            return a11yElements\n    if fb.evaluateBooleanExpression(\n        \"[%s respondsToSelector:@selector(_accessibleSubviews)]\" % view\n    ):\n        return fb.evaluateExpression(\"(id)[%s _accessibleSubviews]\" % (view), False)\n    else:\n        return fb.evaluateObjectExpression(\n            \"[[[UIApplication sharedApplication] keyWindow] _accessibilityElementsInContainer:0 topLevel:%s includeKB:0]\"\n            % view\n        )\n\n\ndef printAccessibilityHierarchy(view, indent=0):\n    a11yLabel = accessibilityLabel(view)\n    classDesc = objHelpers.className(view)\n    indentString = \"   | \" * indent\n\n    # if we don't have any accessibility string - we should have some children\n    if int(a11yLabel.GetValue(), 16) == 0:\n        print(indentString + (\"{} {}\".format(classDesc, view)))\n        # We call private method that gives back all visible accessibility children\n        # for view\n        a11yElements = accessibilityElements(view)\n        accessibilityElementsCount = int(\n            fb.evaluateExpression(\"(int)[%s count]\" % a11yElements)\n        )\n        for index in range(0, accessibilityElementsCount):\n            subview = fb.evaluateObjectExpression(\n                \"[%s objectAtIndex:%i]\" % (a11yElements, index)\n            )\n            printAccessibilityHierarchy(subview, indent + 1)\n    else:\n        print(\n            indentString\n            + (\"({} {}) {}\".format(classDesc, view, a11yLabel.GetObjectDescription()))\n        )\n\n\ndef printAccessibilityIdentifiersHierarchy(view, indent=0):\n    a11yIdentifier = accessibilityIdentifier(view)\n    classDesc = objHelpers.className(view)\n    indentString = \"   | \" * indent\n\n    # if we don't have any accessibility identifier - we should have some children\n    if int(a11yIdentifier.GetValue(), 16) == 0:\n        print(indentString + (\"{} {}\".format(classDesc, view)))\n        # We call private method that gives back all visible accessibility children\n        # for view\n        a11yElements = accessibilityElements(view)\n        accessibilityElementsCount = int(\n            fb.evaluateExpression(\"(int)[%s count]\" % a11yElements)\n        )\n        for index in range(0, accessibilityElementsCount):\n            subview = fb.evaluateObjectExpression(\n                \"[%s objectAtIndex:%i]\" % (a11yElements, index)\n            )\n            printAccessibilityIdentifiersHierarchy(subview, indent + 1)\n    else:\n        print(\n            indentString\n            + (\n                \"({} {}) {}\".format(\n                    classDesc, view, a11yIdentifier.GetObjectDescription()\n                )\n            )\n        )\n"
  },
  {
    "path": "commands/FBAutoLayoutCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n\nimport fbchisellldbbase as fb\nimport fbchisellldbviewhelpers as viewHelpers\nimport lldb\n\n\ndef lldbcommands():\n    return [\n        FBPrintAutolayoutTrace(),\n        FBAutolayoutBorderAmbiguous(),\n        FBAutolayoutUnborderAmbiguous(),\n    ]\n\n\nclass FBPrintAutolayoutTrace(fb.FBCommand):\n    def name(self):\n        return \"paltrace\"\n\n    def description(self):\n        return (\n            \"Print the Auto Layout trace for the given view. \"\n            \"Defaults to the key window.\"\n        )\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"view\",\n                type=\"UIView *\",\n                help=\"The view to print the Auto Layout trace for.\",\n                default=\"(id)[[UIApplication sharedApplication] keyWindow]\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        view = fb.evaluateInputExpression(arguments[0])\n        opt = fb.evaluateBooleanExpression(\n            \"[UIView instancesRespondToSelector:@selector(_autolayoutTraceRecursively:)]\"\n        )\n        traceCall = \"_autolayoutTraceRecursively:1\" if opt else \"_autolayoutTrace\"\n        print(fb.describeObject(\"[{} {}]\".format(view, traceCall)))\n\n\ndef setBorderOnAmbiguousViewRecursive(view, width, color):\n    if not fb.evaluateBooleanExpression(\n        \"[(id)%s isKindOfClass:(Class)[UIView class]]\" % view\n    ):\n        return\n\n    isAmbiguous = fb.evaluateBooleanExpression(\"(BOOL)[%s hasAmbiguousLayout]\" % view)\n    if isAmbiguous:\n        layer = viewHelpers.convertToLayer(view)\n        fb.evaluateEffect(\"[%s setBorderWidth:(CGFloat)%s]\" % (layer, width))\n        fb.evaluateEffect(\n            \"[%s setBorderColor:(CGColorRef)[(id)[UIColor %sColor] CGColor]]\"\n            % (layer, color)\n        )\n\n    subviews = fb.evaluateExpression(\"(id)[%s subviews]\" % view)\n    subviewsCount = int(fb.evaluateExpression(\"(int)[(id)%s count]\" % subviews))\n    if subviewsCount > 0:\n        for i in range(0, subviewsCount):\n            subview = fb.evaluateExpression(\"(id)[%s objectAtIndex:%i]\" % (subviews, i))\n            setBorderOnAmbiguousViewRecursive(subview, width, color)\n\n\nclass FBAutolayoutBorderAmbiguous(fb.FBCommand):\n    def name(self):\n        return \"alamborder\"\n\n    def description(self):\n        return \"Put a border around views with an ambiguous layout\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-c\",\n                long=\"--color\",\n                arg=\"color\",\n                type=\"string\",\n                default=\"red\",\n                help=\"A color name such as 'red', 'green', 'magenta', etc.\",\n            ),\n            fb.FBCommandArgument(\n                short=\"-w\",\n                long=\"--width\",\n                arg=\"width\",\n                type=\"CGFloat\",\n                default=2.0,\n                help=\"Desired width of border.\",\n            ),\n        ]\n\n    def run(self, arguments, options):\n        keyWindow = fb.evaluateExpression(\n            \"(id)[[UIApplication sharedApplication] keyWindow]\"\n        )\n        setBorderOnAmbiguousViewRecursive(keyWindow, options.width, options.color)\n        lldb.debugger.HandleCommand(\"caflush\")\n\n\nclass FBAutolayoutUnborderAmbiguous(fb.FBCommand):\n    def name(self):\n        return \"alamunborder\"\n\n    def description(self):\n        return \"Removes the border around views with an ambiguous layout\"\n\n    def run(self, arguments, options):\n        keyWindow = fb.evaluateExpression(\n            \"(id)[[UIApplication sharedApplication] keyWindow]\"\n        )\n        setBorderOnAmbiguousViewRecursive(keyWindow, 0, \"red\")\n        lldb.debugger.HandleCommand(\"caflush\")\n"
  },
  {
    "path": "commands/FBClassDump.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport string\n\nimport fbchisellldbbase as fb\nimport fbchisellldbobjcruntimehelpers as runtimeHelpers\n\n\ndef lldbcommands():\n    return [FBPrintMethods(), FBPrintProperties(), FBPrintBlock()]\n\n\nclass FBPrintMethods(fb.FBCommand):\n    def name(self):\n        return \"pmethods\"\n\n    def description(self):\n        return \"Print the class and instance methods of a class.\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-a\",\n                long=\"--address\",\n                arg=\"showaddr\",\n                help=\"Print the implementation address of the method\",\n                default=False,\n                boolean=True,\n            ),\n            fb.FBCommandArgument(\n                short=\"-i\",\n                long=\"--instance\",\n                arg=\"insmethod\",\n                help=\"Print the instance methods\",\n                default=False,\n                boolean=True,\n            ),\n            fb.FBCommandArgument(\n                short=\"-c\",\n                long=\"--class\",\n                arg=\"clsmethod\",\n                help=\"Print the class methods\",\n                default=False,\n                boolean=True,\n            ),\n            fb.FBCommandArgument(\n                short=\"-n\",\n                long=\"--name\",\n                arg=\"clsname\",\n                help=\"Take the argument as class name\",\n                default=False,\n                boolean=True,\n            ),\n        ]\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"instance or class\",\n                type=\"instance or Class\",\n                help=\"an Objective-C Class.\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        cls = getClassFromArgument(arguments[0], options.clsname)\n\n        if options.clsmethod:\n            print(\"Class Methods:\")\n            printClassMethods(cls, options.showaddr)\n\n        if options.insmethod:\n            print(\"\\nInstance Methods:\")\n            printInstanceMethods(cls, options.showaddr)\n\n        if not options.clsmethod and not options.insmethod:\n            print(\"Class Methods:\")\n            printClassMethods(cls, options.showaddr)\n            print(\"\\nInstance Methods:\")\n            printInstanceMethods(cls, options.showaddr)\n\n\nclass FBPrintProperties(fb.FBCommand):\n    def name(self):\n        return \"pproperties\"\n\n    def description(self):\n        return \"Print the properties of an instance or Class\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-n\",\n                long=\"--name\",\n                arg=\"clsname\",\n                help=\"Take the argument as class name\",\n                default=False,\n                boolean=True,\n            )\n        ]\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"instance or class\",\n                type=\"instance or Class\",\n                help=\"an Objective-C Class.\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        cls = getClassFromArgument(arguments[0], options.clsname)\n\n        printProperties(cls)\n\n\nclass FBPrintBlock(fb.FBCommand):\n    def name(self):\n        return \"pblock\"\n\n    def description(self):\n        return \"Print the block`s implementation address and signature\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(arg=\"block\", help=\"The block object you want to print\")\n        ]\n\n    def run(self, arguments, options):\n        block = arguments[0]\n\n        # http://clang.llvm.org/docs/Block-ABI-Apple.html\n        tmpString = \"\"\"\n        enum {\n          BLOCK_HAS_COPY_DISPOSE =  (1 << 25),\n          BLOCK_HAS_CTOR =          (1 << 26), // helpers have C++ code\n          BLOCK_IS_GLOBAL =         (1 << 28),\n          BLOCK_HAS_STRET =         (1 << 29), // IFF BLOCK_HAS_SIGNATURE\n          BLOCK_HAS_SIGNATURE =     (1 << 30),\n        };\n        struct Block_literal_1 {\n          void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock\n          int flags;\n          int reserved;\n          void (*invoke)(void *, ...);\n          struct Block_descriptor_1 {\n              unsigned long int reserved; // NULL\n              unsigned long int size;         // sizeof(struct Block_literal_1)\n              // optional helper functions\n              void (*copy_helper)(void *dst, void *src);     // IFF (1<<25)\n              void (*dispose_helper)(void *src);             // IFF (1<<25)\n              // required ABI.2010.3.16\n              const char *signature;                         // IFF (1<<30)\n          } *descriptor;\n          // imported variables\n        };\n        struct Block_literal_1 real = *((__bridge struct Block_literal_1 *)$block);\n        NSMutableDictionary *dict = (id)[NSMutableDictionary dictionary];\n        \n        [dict setObject:(id)[NSNumber numberWithLong:(long)real.invoke] forKey:@\"invoke\"];\n        \n        if (real.flags & BLOCK_HAS_SIGNATURE) {\n          char *signature;\n          if (real.flags & BLOCK_HAS_COPY_DISPOSE) {\n              signature = (char *)(real.descriptor)->signature;\n          } else {\n              signature = (char *)(real.descriptor)->copy_helper;\n          }\n\n          NSMethodSignature *sig = [NSMethodSignature signatureWithObjCTypes:signature];\n          NSMutableArray *types = [NSMutableArray array];\n\n          [types addObject:(id)[NSString stringWithUTF8String:(char *)[sig methodReturnType]]];\n\n          for (NSUInteger i = 0; i < sig.numberOfArguments; i++) {\n              char *type = (char *)[sig getArgumentTypeAtIndex:i];\n              [types addObject:(id)[NSString stringWithUTF8String:type]];\n          }\n          \n          [dict setObject:types forKey:@\"signature\"];\n        }\n        \n        RETURN(dict);\n        \"\"\"\n        command = string.Template(tmpString).substitute(block=block)\n        json = fb.evaluate(command)\n\n        signature = json[\"signature\"]\n        if not signature:\n            print(\"Imp: \" + hex(json[\"invoke\"]))\n            return\n\n        sigStr = \"{} ^(\".format(decode(signature[0]))\n        # the block`s implementation always take the block as it`s first argument, so we ignore it\n        sigStr += \", \".join([decode(m) for m in signature[2:]])\n        sigStr += \");\"\n\n        print(\"Imp: \" + hex(json[\"invoke\"]) + \"    Signature: \" + sigStr)\n\n\n# helpers\ndef isClassObject(arg):\n    return runtimeHelpers.class_isMetaClass(runtimeHelpers.object_getClass(arg))\n\n\ndef getClassFromArgument(arg, is_classname):\n    cls = arg\n    if is_classname:\n        cls = runtimeHelpers.objc_getClass(cls)\n        if not int(cls, 16):\n            raise Exception('Class \"{}\" not found'.format(arg))\n    else:\n        if not isClassObject(cls):\n            cls = runtimeHelpers.object_getClass(cls)\n            if not isClassObject(cls):\n                raise Exception(\n                    \"Invalid argument. Please specify an instance or a Class.\"\n                )\n\n    return cls\n\n\ndef printInstanceMethods(cls, showaddr=False, prefix=\"-\"):\n    methods = getMethods(cls)\n    if not methods:\n        print(\"No methods were found\")\n\n    for m in methods:\n        if showaddr:\n            print(prefix + \" \" + m.prettyPrintString() + \" \" + str(m.imp))\n        else:\n            print(prefix + \" \" + m.prettyPrintString())\n\n\ndef printClassMethods(cls, showaddr=False):\n    printInstanceMethods(runtimeHelpers.object_getClass(cls), showaddr, \"+\")\n\n\ndef printProperties(cls, showvalue=False):\n    props = getProperties(cls)\n    for p in props:\n        print(p.prettyPrintString())\n\n\ndef decode(code):\n    encodeMap = {\n        \"c\": \"char\",\n        \"i\": \"int\",\n        \"s\": \"short\",\n        \"l\": \"long\",\n        \"q\": \"long long\",\n        \"C\": \"unsigned char\",\n        \"I\": \"unsigned int\",\n        \"S\": \"unsigned short\",\n        \"L\": \"unsigned long\",\n        \"Q\": \"unsigned long long\",\n        \"f\": \"float\",\n        \"d\": \"double\",\n        \"B\": \"bool\",\n        \"v\": \"void\",\n        \"*\": \"char *\",\n        \"@\": \"id\",\n        \"#\": \"Class\",\n        \":\": \"SEL\",\n    }\n\n    ret = code\n    if code in encodeMap:\n        ret = encodeMap[code]\n    elif ret[0:1] == \"@\":\n        if ret[1:2] == \"?\":  # @? represent a block\n            ret = code\n        elif ret[2:3] == \"<\":  # @\"<aDelegate><bDelegate>\"\n            ret = \"id\" + ret[2:-1].replace(\"><\", \", \")\n        else:\n            ret = ret[2:-1] + \" *\"\n    elif ret[0:1] == \"^\":\n        ret = decode(ret[1:]) + \" *\"\n\n    return ret\n\n\n# Notice that evaluateExpression doesn't work with variable arguments. such as -[NSString stringWithFormat:]\n# I remove the \"free(methods)\" because it would cause evaluateExpressionValue to raise exception some time.\ndef getMethods(klass):\n    tmpString = \"\"\"\n    unsigned int outCount;\n    Method *methods = (Method *)class_copyMethodList((Class)$cls, &outCount);\n    NSMutableArray *result = (id)[NSMutableArray array];\n    \n    for (int i = 0; i < outCount; i++) {\n      NSMutableDictionary *m = (id)[NSMutableDictionary dictionary];\n\n      SEL name = (SEL)method_getName(methods[i]);\n      [m setObject:(id)NSStringFromSelector(name) forKey:@\"name\"];\n      \n      char * encoding = (char *)method_getTypeEncoding(methods[i]);\n      [m setObject:(id)[NSString stringWithUTF8String:encoding] forKey:@\"type_encoding\"];\n      \n      NSMutableArray *types = (id)[NSMutableArray array];\n      NSInteger args = (NSInteger)method_getNumberOfArguments(methods[i]);\n      for (int idx = 0; idx < args; idx++) {\n          char *type = (char *)method_copyArgumentType(methods[i], idx);\n          [types addObject:(id)[NSString stringWithUTF8String:type]];\n      }\n      [m setObject:types forKey:@\"parameters_type\"];\n      \n      char *ret_type = (char *)method_copyReturnType(methods[i]);\n      [m setObject:(id)[NSString stringWithUTF8String:ret_type] forKey:@\"return_type\"];\n      \n      long imp = (long)method_getImplementation(methods[i]);\n      [m setObject:[NSNumber numberWithLongLong:imp] forKey:@\"implementation\"];\n      \n      [result addObject:m];\n    }\n    RETURN(result);\n  \"\"\"\n    command = string.Template(tmpString).substitute(cls=klass)\n    methods = fb.evaluate(command)\n    return [Method(m) for m in methods]\n\n\nclass Method:\n    def __init__(self, json):\n        self.name = json[\"name\"]\n        self.type_encoding = json[\"type_encoding\"]\n        self.parameters_type = json[\"parameters_type\"]\n        self.return_type = json[\"return_type\"]\n        self.imp = self.toHex(json[\"implementation\"])\n\n    def prettyPrintString(self):\n        argnum = len(self.parameters_type)\n        names = self.name.split(\":\")\n\n        # the argnum count must be bigger then 2, index 0 for self, index 1 for SEL\n        for i in range(2, argnum):\n            arg_type = self.parameters_type[i]\n            names[i - 2] = names[i - 2] + \":(\" + decode(arg_type) + \")arg\" + str(i - 2)\n\n        string = \" \".join(names)\n        return \"({}){}\".format(decode(self.return_type), string)\n\n    def toHex(self, addr):\n        return hex(addr)\n\n    def __str__(self):\n        return (\n            \"<Method:\"\n            + self.oc_method\n            + \"> \"\n            + self.name\n            + \" --- \"\n            + self.type\n            + \" --- \"\n            + self.imp\n        )\n\n\ndef getProperties(klass):\n    tmpString = \"\"\"\n      NSMutableArray *result = (id)[NSMutableArray array];\n      unsigned int count;\n      objc_property_t *props = (objc_property_t *)class_copyPropertyList((Class)$cls, &count);\n      for (int i = 0; i < count; i++) {\n          NSMutableDictionary *dict = (id)[NSMutableDictionary dictionary];\n          \n          char *name = (char *)property_getName(props[i]);\n          [dict setObject:(id)[NSString stringWithUTF8String:name] forKey:@\"name\"];\n          \n          char *attrstr = (char *)property_getAttributes(props[i]);\n          [dict setObject:(id)[NSString stringWithUTF8String:attrstr] forKey:@\"attributes_string\"];\n          \n          NSMutableDictionary *attrsDict = (id)[NSMutableDictionary dictionary];\n          unsigned int pcount;\n          objc_property_attribute_t *attrs = (objc_property_attribute_t *)property_copyAttributeList(props[i], &pcount);\n          for (int i = 0; i < pcount; i++) {\n              NSString *name = (id)[NSString stringWithUTF8String:(char *)attrs[i].name];\n              NSString *value = (id)[NSString stringWithUTF8String:(char *)attrs[i].value];\n              [attrsDict setObject:value forKey:name];\n          }\n          [dict setObject:attrsDict forKey:@\"attributes\"];\n          \n          [result addObject:dict];\n      }\n      RETURN(result);\n    \"\"\"\n    command = string.Template(tmpString).substitute(cls=klass)\n    propsJson = fb.evaluate(command)\n    return [Property(m) for m in propsJson]\n\n\nclass Property:\n    def __init__(self, json):\n        self.name = json[\"name\"]\n        self.attributes_string = json[\"attributes_string\"]\n        self.attributes = json[\"attributes\"]\n\n    # https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW1\n    def prettyPrintString(self):\n        attrs = []\n        if \"N\" in self.attributes:\n            attrs.append(\"nonatomic\")\n        else:\n            attrs.append(\"atomic\")\n\n        if \"&\" in self.attributes:\n            attrs.append(\"strong\")\n        elif \"C\" in self.attributes:\n            attrs.append(\"copy\")\n        elif \"W\" in self.attributes:\n            attrs.append(\"weak\")\n        else:\n            attrs.append(\"assign\")\n\n        if \"R\" in self.attributes:\n            attrs.append(\"readonly\")\n\n        if \"G\" in self.attributes:\n            attrs.append(\"getter={}\".format(self.attributes[\"G\"]))\n        if \"S\" in self.attributes:\n            attrs.append(\"setter={}\".format(self.attributes[\"S\"]))\n\n        return \"@property ({}) {} {};\".format(\n            \", \".join(attrs), decode(self.attributes[\"T\"]), self.name\n        )\n"
  },
  {
    "path": "commands/FBComponentCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport fbchisellldbbase as fb\nimport fbchisellldbviewhelpers as viewHelpers\n\n\ndef lldbcommands():\n    return [\n        FBComponentsDebugCommand(),\n        FBComponentsPrintCommand(),\n        FBComponentsReflowCommand(),\n    ]\n\n\nclass FBComponentsDebugCommand(fb.FBCommand):\n    def name(self):\n        return \"dcomponents\"\n\n    def description(self):\n        return \"Set debugging options for components.\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-s\",\n                long=\"--set\",\n                arg=\"set\",\n                help=\"Set debug mode for components\",\n                boolean=True,\n            ),\n            fb.FBCommandArgument(\n                short=\"-u\",\n                long=\"--unset\",\n                arg=\"unset\",\n                help=\"Unset debug mode for components\",\n                boolean=True,\n            ),\n        ]\n\n    def run(self, arguments, options):\n        print(\"Debug mode for ComponentKit is deprecated; use Flipper instead.\")\n\n\nclass FBComponentsPrintCommand(fb.FBCommand):\n    def name(self):\n        return \"pcomponents\"\n\n    def description(self):\n        return (\n            \"Print a recursive description of components found starting from <aView>.\"\n        )\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"aView\",\n                type=\"UIView* or CKComponent*\",\n                help=\"The view or component from which the search for components begins.\",\n                default=\"(id)[[UIApplication sharedApplication] keyWindow]\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        view = fb.evaluateInputExpression(arguments[0])\n        if not viewHelpers.isView(view):\n            # assume it's a CKComponent\n            view = fb.evaluateExpression(\"((CKComponent *)%s).viewContext.view\" % view)\n        print(\n            fb.describeObject(\n                \"[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)\"\n                + view\n                + \"]\"\n            )\n        )\n\n\nclass FBComponentsReflowCommand(fb.FBCommand):\n    def name(self):\n        return \"rcomponents\"\n\n    def description(self):\n        return \"Synchronously reflow and update all components.\"\n\n    def run(self, arguments, options):\n        fb.evaluateEffect(\"[CKComponentDebugController reflowComponents]\")\n"
  },
  {
    "path": "commands/FBCopyCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nfrom __future__ import print_function\n\nimport errno\nimport os\nimport time\n\nimport fbchisellldbbase as fb\nimport fbchisellldbobjecthelpers as objectHelpers\nimport lldb\n\n\ndef lldbcommands():\n    return [FBCopyCommand()]\n\n\ndef _copyFromURL(url, preferredFilename, noOpen):\n    data = fb.evaluateObjectExpression(\n        \"(id)[NSData dataWithContentsOfURL:(id){}]\".format(url)\n    )\n    defaultFilename = fb.describeObject(\n        \"(id)[[{} pathComponents] lastObject]\".format(url)\n    )\n    _copyFromData(data, defaultFilename, preferredFilename, noOpen)\n\n\ndef _copyFromData(data, defaultFilename, preferredFilename, noOpen):\n    directory = \"/tmp/chisel_copy/\"\n\n    path = directory + (preferredFilename or defaultFilename)\n\n    try:\n        os.makedirs(directory)\n    except OSError as e:\n        if e.errno == errno.EEXIST and os.path.isdir(directory):\n            pass\n        else:\n            raise\n\n    startAddress = fb.evaluateExpression(\"(void *)[(id)\" + data + \" bytes]\")\n    length = fb.evaluateExpression(\"(NSUInteger)[(id)\" + data + \" length]\")\n\n    address = int(startAddress, 16)\n    length = int(length)\n\n    if not (address or length):\n        print(\"Could not get data.\")\n        return\n\n    process = lldb.debugger.GetSelectedTarget().GetProcess()\n    error = lldb.SBError()\n    mem = process.ReadMemory(address, length, error)\n\n    if error is not None and str(error) != \"success\":\n        print(error)\n    else:\n        with open(path, \"wb\") as file:\n            file.write(mem)\n            file.close()\n        print(path)\n        if not noOpen:\n            os.system(\"open \" + path)\n\n\ndef _copy(target, preferredFilename, noOpen):\n    target = \"(\" + target + \")\"\n\n    if objectHelpers.isKindOfClass(target, \"NSURL\"):\n        _copyFromURL(target, preferredFilename, noOpen)\n    elif objectHelpers.isKindOfClass(target, \"NSData\"):\n        _copyFromData(\n            target,\n            time.strftime(\"%Y-%m-%d-%H-%M-%S\", time.gmtime()) + \".data\",\n            preferredFilename,\n            noOpen,\n        )\n    else:\n        print(\n            \"{} isn't supported. You can copy an NSURL or NSData.\".format(\n                objectHelpers.className(target)\n            )\n        )\n\n\nclass FBCopyCommand(fb.FBCommand):\n    def name(self):\n        return \"copy\"\n\n    def description(self):\n        return \"Copy data to your Mac.\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-f\",\n                long=\"--filename\",\n                arg=\"filename\",\n                help=\"The output filename.\",\n            ),\n            fb.FBCommandArgument(\n                short=\"-n\",\n                long=\"--no-open\",\n                arg=\"noOpen\",\n                boolean=True,\n                default=False,\n                help=\"Do not open the file.\",\n            ),\n        ]\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(arg=\"target\", type=\"(id)\", help=\"The object to copy.\")\n        ]\n\n    def run(self, arguments, options):\n        _copy(arguments[0], options.filename, options.noOpen)\n"
  },
  {
    "path": "commands/FBCounterCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n# These set of commands provide a way to use counters in debug time. By using these counters,\n# you can track how many times your program takes a specific path.\n#\n# Sample Use Case:\n# Let's say you have a function that logs some messages from various parts of your code.\n# And you want to learn how many times logMessage is called on startup.\n#\n# 1. Add a breakpoint to the entry point of your program (e.g. main).\n#   a. Add `zzz 10 printcounter` as an action.\n#   b. Check \"Automatically continue after evaluating actions\"\n# 2. Add a breakpoint to the logMessage function.\n#   a. Add `incrementcounter log` as an action.\n#   b. Add `incrementcounter log_{} message` as an action.\n#   c. Check \"Automatically continue after evaluating actions\"\n# 3. Run the program\n#\n# Format String:\n# It uses Python's string.Formatter to format strings. You can use placeholders here as you can in Python:\n# https://docs.python.org/3.4/library/string.html#string.Formatter.format\n#\n# Sample key_format_string:\n# \"key_{}\" (int)5 -> Will build the key string as \"key_5\"\n\n# Can be removed when Python 2 support is removed.\nfrom __future__ import print_function\n\nimport fbchisellldbbase as fb\n\n\ncounters = {}\n\n\ndef lldbcommands():\n    return [\n        FBIncrementCounterCommand(),\n        FBPrintCounterCommand(),\n        FBPrintCountersCommand(),\n        FBResetCounterCommand(),\n        FBResetCountersCommand(),\n    ]\n\n\ndef generateKey(arguments):\n    keyFormatString = arguments[1]\n    keyArgs = []\n\n    for argument in arguments[2:]:\n        if argument.startswith(\"(\"):\n            value = fb.evaluateExpression(argument)\n        else:\n            value = fb.evaluateExpressionValue(argument).GetObjectDescription()\n\n            if not value:\n                value = fb.evaluateExpression(argument)\n\n        keyArgs.append(value)\n\n    return keyFormatString.format(*keyArgs).strip()\n\n\n# Increments the counter for the key.\n# (lldb) incrementcounter key_format_string key_args\nclass FBIncrementCounterCommand(fb.FBCommand):\n    def name(self):\n        return \"incrementcounter\"\n\n    def description(self):\n        return \"Increments the counter for the key.\"\n\n    def run(self, arguments, options):\n        key = generateKey(arguments)\n        counters[key] = counters.get(key, 0) + 1\n\n\n# Prints the counter for the key.\n# (lldb) printcounter key_format_string key_args\n# 0\nclass FBPrintCounterCommand(fb.FBCommand):\n    def name(self):\n        return \"printcounter\"\n\n    def description(self):\n        return \"Prints the counter for the key.\"\n\n    def run(self, arguments, options):\n        key = generateKey(arguments)\n        print(str(counters[key]))\n\n\n# Prints all the counters sorted by the keys.\n# (lldb) printcounters\n# key_1: 0\nclass FBPrintCountersCommand(fb.FBCommand):\n    def name(self):\n        return \"printcounters\"\n\n    def description(self):\n        return \"Prints all the counters sorted by the keys.\"\n\n    def run(self, arguments, options):\n        keys = sorted(counters.keys())\n        for key in keys:\n            print(key + \": \" + str(counters[key]))\n\n\n# Resets the counter for the key.\n# (lldb) resetcounter key_format_string key_args\nclass FBResetCounterCommand(fb.FBCommand):\n    def name(self):\n        return \"resetcounter\"\n\n    def description(self):\n        return \"Resets the counter for the key.\"\n\n    def run(self, arguments, options):\n        key = generateKey(arguments)\n        counters[key] = 0\n\n\n# Resets all the counters.\n# (lldb) resetcounters\nclass FBResetCountersCommand(fb.FBCommand):\n    def name(self):\n        return \"resetcounters\"\n\n    def description(self):\n        return \"Resets all the counters.\"\n\n    def run(self, arguments, options):\n        counters.clear()\n"
  },
  {
    "path": "commands/FBDebugCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n# Can be removed when Python 2 support is removed.\nfrom __future__ import print_function\n\nimport os\nimport re\nimport sys\n\nimport fbchisellldbbase as fb\nimport fbchisellldbobjcruntimehelpers as objc\nimport lldb\n\n\ndef lldbcommands():\n    return [\n        FBWatchInstanceVariableCommand(),\n        FBFrameworkAddressBreakpointCommand(),\n        FBMethodBreakpointCommand(),\n        FBMemoryWarningCommand(),\n        FBFindInstancesCommand(),\n        FBMethodBreakpointEnableCommand(),\n        FBMethodBreakpointDisableCommand(),\n        FBHeapFromCommand(),\n        FBSequenceCommand(),\n    ]\n\n\nclass FBWatchInstanceVariableCommand(fb.FBCommand):\n    def name(self):\n        return \"wivar\"\n\n    def description(self):\n        return \"Set a watchpoint for an object's instance variable.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"object\", type=\"id\", help=\"Object expression to be evaluated.\"\n            ),\n            fb.FBCommandArgument(\n                arg=\"ivarName\", help=\"Name of the instance variable to watch.\"\n            ),\n        ]\n\n    def run(self, arguments, options):\n        commandForObject, ivarName = arguments\n\n        objectAddress = int(fb.evaluateObjectExpression(commandForObject), 0)\n\n        ivarOffsetCommand = '(ptrdiff_t)ivar_getOffset((void*)object_getInstanceVariable((id){}, \"{}\", 0))'.format(\n            objectAddress, ivarName\n        )\n        ivarOffset = int(fb.evaluateExpression(ivarOffsetCommand), 0)\n\n        # A multi-statement command allows for variables scoped to the command,\n        # not permanent in the session like $variables.\n        ivarSizeCommand = (\n            \"unsigned int size = 0;\"\n            'char *typeEncoding = (char *)ivar_getTypeEncoding((void*)class_getInstanceVariable((Class)object_getClass((id){}), \"{}\"));'\n            \"(char *)NSGetSizeAndAlignment(typeEncoding, &size, 0);\"\n            \"size\"\n        ).format(objectAddress, ivarName)\n        ivarSize = int(fb.evaluateExpression(ivarSizeCommand), 0)\n\n        error = lldb.SBError()\n        watchpoint = lldb.debugger.GetSelectedTarget().WatchAddress(\n            objectAddress + ivarOffset, ivarSize, False, True, error\n        )\n\n        if error.Success():\n            print(\n                \"Remember to delete the watchpoint using: watchpoint delete {}\".format(\n                    watchpoint.GetID()\n                )\n            )\n        else:\n            print(\"Could not create the watchpoint: {}\".format(error.GetCString()))\n\n\nclass FBFrameworkAddressBreakpointCommand(fb.FBCommand):\n    def name(self):\n        return \"binside\"\n\n    def description(self):\n        return \"Set a breakpoint for a relative address within the framework/library that's currently running. This does the work of finding the offset for the framework/library and sliding your address accordingly.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"address\",\n                type=\"string\",\n                help=\"Address within the currently running framework to set a breakpoint on.\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        library_address = int(arguments[0], 0)\n        address = int(\n            lldb.debugger.GetSelectedTarget()\n            .GetProcess()\n            .GetSelectedThread()\n            .GetSelectedFrame()\n            .GetModule()\n            .ResolveFileAddress(library_address)\n        )\n\n        lldb.debugger.HandleCommand(\"breakpoint set --address {}\".format(address))\n\n\nclass FBMethodBreakpointCommand(fb.FBCommand):\n    def name(self):\n        return \"bmessage\"\n\n    def description(self):\n        return \"Set a breakpoint for a selector on a class, even if the class itself doesn't override that selector. It walks the hierarchy until it finds a class that does implement the selector and sets a conditional breakpoint there.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"expression\",\n                type=\"string\",\n                help='Expression to set a breakpoint on, e.g. \"-[MyView setFrame:]\", \"+[MyView awesomeClassMethod]\" or \"-[0xabcd1234 setFrame:]\"',\n            )\n        ]\n\n    def run(self, arguments, options):\n        expression = arguments[0]\n\n        methodPattern = re.compile(\n            r\"\"\"\n      (?P<scope>[-+])?\n      \\[\n        (?P<target>.*?)\n        (?P<category>\\(.+\\))?\n        \\s+\n        (?P<selector>.*)\n      \\]\n\"\"\",\n            re.VERBOSE,\n        )\n\n        match = methodPattern.match(expression)\n\n        if not match:\n            print(\"Failed to parse expression. Do you even Objective-C?!\")\n            return\n\n        expressionForSelf = objc.functionPreambleExpressionForSelf()\n        if not expressionForSelf:\n            arch = objc.currentArch()\n            print(\n                \"Your architecture, {}, is truly fantastic. However, I don't currently support it.\".format(\n                    arch\n                )\n            )\n            return\n\n        methodTypeCharacter = match.group(\"scope\")\n        classNameOrExpression = match.group(\"target\")\n        category = match.group(\"category\")\n        selector = match.group(\"selector\")\n\n        methodIsClassMethod = methodTypeCharacter == \"+\"\n\n        if methodIsClassMethod:\n            methodTypeCharacter = \"\\+\"\n        else:\n            # The default is instance method, and methodTypeCharacter\n            # may not actually be '-'.\n            methodTypeCharacter = \"-\"\n\n        targetIsClass = False\n        targetObject = fb.evaluateObjectExpression(\n            \"({})\".format(classNameOrExpression), False\n        )\n\n        if not targetObject:\n            # If the expression didn't yield anything then it's likely a class.\n            # Assume it is. We will check again that the class does actually\n            # exist anyway.\n            targetIsClass = True\n            targetObject = fb.evaluateObjectExpression(\n                \"[{} class]\".format(classNameOrExpression), False\n            )\n\n        targetClass = fb.evaluateObjectExpression(\n            \"[{} class]\".format(targetObject), False\n        )\n\n        if not targetClass or int(targetClass, 0) == 0:\n            print(\n                'Couldn\\'t find a class from the expression \"{}\". Did you typo?'.format(\n                    classNameOrExpression\n                )\n            )\n            return\n\n        if methodIsClassMethod:\n            targetClass = objc.object_getClass(targetClass)\n\n        found = False\n        nextClass = targetClass\n\n        while not found and int(nextClass, 0) > 0:\n            if classItselfImplementsSelector(nextClass, selector):\n                found = True\n            else:\n                nextClass = objc.class_getSuperclass(nextClass)\n\n        if not found:\n            print(\n                \"There doesn't seem to be an implementation of {} in the class hierarchy. Made a boo boo with the selector name?\".format(\n                    selector\n                )\n            )\n            return\n\n        breakpointClassName = objc.class_getName(nextClass)\n        formattedCategory = category if category else \"\"\n        breakpointFullName = \"{}[{}{} {}]\".format(\n            methodTypeCharacter, breakpointClassName, formattedCategory, selector\n        )\n\n        if targetIsClass:\n            breakpointCondition = \"(void*)object_getClass({}) == {}\".format(\n                expressionForSelf, targetClass\n            )\n        else:\n            breakpointCondition = \"(void*){} == {}\".format(\n                expressionForSelf, targetObject\n            )\n\n        print(\n            \"Setting a breakpoint at {} with condition {}\".format(\n                breakpointFullName, breakpointCondition\n            )\n        )\n\n        if category:\n            lldb.debugger.HandleCommand(\n                'breakpoint set --skip-prologue false --fullname \"{}\" --condition \"{}\"'.format(\n                    breakpointFullName, breakpointCondition\n                )\n            )\n        else:\n            breakpointPattern = r\"{}\\[{}(\\(.+\\))? {}\\]\".format(\n                methodTypeCharacter, breakpointClassName, selector\n            )\n            lldb.debugger.HandleCommand(\n                'breakpoint set --skip-prologue false --func-regex \"{}\" --condition \"{}\"'.format(\n                    breakpointPattern, breakpointCondition\n                )\n            )\n\n\ndef classItselfImplementsSelector(klass, selector):\n    thisMethod = objc.class_getInstanceMethod(klass, selector)\n    if thisMethod == 0:\n        return False\n\n    superklass = objc.class_getSuperclass(klass)\n    superMethod = objc.class_getInstanceMethod(superklass, selector)\n    if thisMethod == superMethod:\n        return False\n    else:\n        return True\n\n\nclass FBMemoryWarningCommand(fb.FBCommand):\n    def name(self):\n        return \"mwarning\"\n\n    def description(self):\n        return \"simulate a memory warning\"\n\n    def run(self, arguments, options):\n        fb.evaluateEffect(\n            \"[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)]\"\n        )\n\n\ndef switchBreakpointState(expression, on):\n    expression_pattern = re.compile(r\"{}\".format(expression), re.I)\n\n    target = lldb.debugger.GetSelectedTarget()\n    for breakpoint in target.breakpoint_iter():\n        if breakpoint.IsEnabled() != on and (\n            expression_pattern.search(str(breakpoint))\n        ):\n            print(str(breakpoint))\n            breakpoint.SetEnabled(on)\n        for location in breakpoint:\n            if location.IsEnabled() != on and (\n                expression_pattern.search(str(location))\n                or expression == hex(location.GetLoadAddress())\n            ):\n                print(str(location))\n                location.SetEnabled(on)\n\n\nclass FBMethodBreakpointEnableCommand(fb.FBCommand):\n    def name(self):\n        return \"benable\"\n\n    def description(self):\n        return \"\"\"\n    Enable a set of breakpoints for a regular expression\n\n    Examples:\n\n          * benable ***address***\n          benable 0x0000000104514dfc\n          benable 0x183e23564\n\n          #use `benable *filename*` to switch all breakpoints in this file to `enable`\n          benable SUNNetService.m \n\n          #use `benable ***module(AppName)***` to switch all breakpoints in this module to `enable`\n          benable UIKit\n          benable Foundation \n\n    \"\"\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"expression\", type=\"string\", help=\"Expression to enable breakpoint\"\n            )\n        ]\n\n    def run(self, arguments, options):\n        expression = arguments[0]\n        switchBreakpointState(expression, True)\n\n\nclass FBMethodBreakpointDisableCommand(fb.FBCommand):\n    def name(self):\n        return \"bdisable\"\n\n    def description(self):\n        return \"\"\"\n    Disable a set of breakpoints for a regular expression\n\n    Examples:\n\n          * bdisable ***address***\n          bdisable 0x0000000104514dfc\n          bdisable 0x183e23564\n\n          #use `bdisable *filename*` to switch all breakpoints in this file to `disable`\n          bdisable SUNNetService.m \n\n          #use `bdisable ***module(AppName)***` to switch all breakpoints in this module to `disable`\n          bdisable UIKit\n          bdisable Foundation \n\n    \"\"\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"expression\", type=\"string\", help=\"Expression to disable breakpoint\"\n            )\n        ]\n\n    def run(self, arguments, options):\n        expression = arguments[0]\n        switchBreakpointState(expression, False)\n\n\nclass FBFindInstancesCommand(fb.FBCommand):\n    def name(self):\n        return \"findinstances\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(arg=\"type\", help=\"Class or protocol name\"),\n            fb.FBCommandArgument(\n                arg=\"query\",\n                default=\" \",  # space is a hack to mark optional\n                help=\"Query expression, uses NSPredicate syntax\",\n            ),\n        ]\n\n    def description(self):\n        return \"\"\"\n    Find instances of specified ObjC classes.\n\n    This command scans memory and uses heuristics to identify instances of\n    Objective-C classes. This includes Swift classes that descend from NSObject.\n\n    Basic examples:\n\n        findinstances UIScrollView\n        findinstances *UIScrollView\n        findinstances UIScrollViewDelegate\n\n    These basic searches find instances of the given class or protocol. By\n    default, subclasses of the class or protocol are included in the results. To\n    find exact class instances, add a `*` prefix, for example: *UIScrollView.\n\n    Advanced examples:\n\n        # Find views that are either: hidden, invisible, or not in a window\n        findinstances UIView hidden == true || alpha == 0 || window == nil\n        # Find views that have either a zero width or zero height\n        findinstances UIView layer.bounds.#size.width == 0 || layer.bounds.#size.height == 0\n        # Find leaf views that have no subviews\n        findinstances UIView subviews.@count == 0\n        # Find dictionaries that have keys that might be passwords or passphrases\n        findinstances NSDictionary any @allKeys beginswith 'pass'\n\n    These examples make use of a filter. The filter is implemented with\n    NSPredicate, see its documentaiton for more details. Basic NSPredicate\n    expressions have relatively predicatable syntax. There are some exceptions\n    as seen above, see https://github.com/facebook/chisel/wiki/findinstances.\n    \"\"\"\n\n    def lex(self, commandLine):\n        # Can't use default shlex splitting because it strips quotes, which results\n        # in invalid NSPredicate syntax. Split the input into type and rest (query).\n        return commandLine.split(\" \", 1)\n\n    def run(self, arguments, options):\n        if not self.loadChiselIfNecessary():\n            return\n\n        if len(arguments) == 0 or not arguments[0].strip():\n            print(\n                \"Usage: findinstances <classOrProtocol> [<predicate>]; Run `help findinstances`\"\n            )\n            return\n\n        query = arguments[0]\n        predicate = arguments[1].strip()\n        # Escape double quotes and backslashes.\n        predicate = re.sub('([\\\\\"])', r\"\\\\\\1\", predicate)\n        call = '(void)PrintInstances(\"{}\", \"{}\")'.format(query, predicate)\n        fb.evaluateExpressionValue(call)\n\n    def loadChiselIfNecessary(self):\n        target = lldb.debugger.GetSelectedTarget()\n        symbol_contexts = target.FindSymbols(\"PrintInstances\", lldb.eSymbolTypeCode)\n        if any(ctx.symbol.IsValid() for ctx in symbol_contexts):\n            return True\n\n        path = self.chiselLibraryPath()\n        if not os.path.exists(path):\n            print(\"Chisel library missing: \" + path)\n            return False\n\n        module = fb.evaluateExpressionValue('(void*)dlopen(\"{}\", 2)'.format(path))\n        if module.unsigned != 0 or target.module[\"Chisel\"]:\n            return True\n\n        # `errno` is a macro that expands to a call to __error(). In development,\n        # lldb was not getting a correct value for `errno`, so `__error()` is used.\n        errno = fb.evaluateExpressionValue(\"*(int*)__error()\").value\n        error = fb.evaluateExpressionValue(\"(char*)dlerror()\")\n        if errno == 50:\n            # KERN_CODESIGN_ERROR from <mach/kern_return.h>\n            print(\"Error loading Chisel: Code signing failure; Must re-run codesign\")\n        elif error.unsigned != 0:\n            print(\"Error loading Chisel: \" + error.summary)\n        elif errno != 0:\n            error = fb.evaluateExpressionValue(\"(char*)strerror({})\".format(errno))\n            if error.unsigned != 0:\n                print(\"Error loading Chisel: \" + error.summary)\n            else:\n                print(\"Error loading Chisel (errno {})\".format(errno))\n        else:\n            print(\"Unknown error loading Chisel\")\n\n        return False\n\n    def chiselLibraryPath(self):\n        # script os.environ['CHISEL_LIBRARY_PATH'] = '/path/to/custom/Chisel'\n        path = os.getenv(\"CHISEL_LIBRARY_PATH\")\n        if path and os.path.exists(path):\n            return path\n\n        source_path = sys.modules[__name__].__file__\n        source_dir = os.path.dirname(source_path)\n        # ugh: ../.. is to back out of commands/, then back out of libexec/\n        return os.path.join(source_dir, \"..\", \"..\", \"lib\", \"Chisel.framework\", \"Chisel\")\n\n\nclass FBHeapFromCommand(fb.FBCommand):\n    def name(self):\n        return \"heapfrom\"\n\n    def description(self):\n        return \"Show all nested heap pointers contained within a given variable.\"\n\n    def run(self, arguments, options):\n        # This command is like `expression --synthetic-type false`,\n        # except only showing nested heap references.\n        var = self.context.frame.var(arguments[0])\n        if not var or not var.IsValid():\n            self.result.SetError('No variable named \"{}\"'.format(arguments[0]))\n            return\n\n        # Use the actual underlying structure of the variable,\n        # not the human friendly (synthetic) one.\n        root = var.GetNonSyntheticValue()\n\n        # Traversal of SBValue tree to get leaf nodes, which is where heap\n        # pointers will be.\n        leafs = []\n        queue = [root]\n        while queue:\n            node = queue.pop(0)\n            if node.num_children == 0:\n                leafs.append(node)\n            else:\n                queue += [node.GetChildAtIndex(i) for i in range(node.num_children)]\n\n        pointers = {}\n        for node in leafs:\n            # Assumption: an addr that has no value means a pointer.\n            if node.addr and not node.value:\n                pointers[node.load_addr] = node.path\n\n        options = lldb.SBExpressionOptions()\n        options.SetLanguage(lldb.eLanguageTypeC)\n\n        def isHeap(addr):\n            lookup = \"(int)malloc_size({})\".format(addr)\n            return self.context.frame.EvaluateExpression(lookup, options).unsigned != 0\n\n        allocations = (addr for addr in pointers if isHeap(addr))\n        for addr in allocations:\n            print(\n                \"0x{addr:x} {path}\".format(addr=addr, path=pointers[addr]),\n                file=self.result,\n            )\n        if not allocations:\n            print(\"No heap addresses found\", file=self.result)\n\n\nclass FBSequenceCommand(fb.FBCommand):\n    def name(self):\n        return \"sequence\"\n\n    def description(self):\n        return \"Run commands in sequence, stopping on any error.\"\n\n    def lex(self, commandLine):\n        return [command.strip() for command in commandLine.split(\";\")]\n\n    def run(self, arguments, options):\n        # arguments contains the raw command first, followed by the split commands.\n        if len(arguments) == 1:\n            return\n        commands = filter(None, arguments[1:])\n\n        interpreter = lldb.debugger.GetCommandInterpreter()\n\n        # Complete one command before running the next one in the sequence. Disable\n        # async to do this. Also, save the current async value to restore it later.\n        asyncFlag = lldb.debugger.GetAsync()\n        lldb.debugger.SetAsync(False)\n\n        for command in commands[:-1]:\n            success = self.run_command(interpreter, command)\n            if not success:\n                lldb.debugger.SetAsync(asyncFlag)\n                return\n\n        # Restore original async value.\n        lldb.debugger.SetAsync(asyncFlag)\n\n        # If the last command is `continue`, call Continue() on the process\n        # instead. This is done because HandleCommand('continue') has strange\n        # behavior, while calling Continue() works as expected.\n        last = commands[-1]\n        if self.is_continue(interpreter, last):\n            self.context.process.Continue()\n        else:\n            self.run_command(interpreter, last)\n\n    def run_command(self, interpreter, command):\n        ret = lldb.SBCommandReturnObject()\n        interpreter.HandleCommand(command, ret)\n        if ret.GetOutput():\n            print(ret.GetOutput().strip(), file=self.result)\n\n        if ret.Succeeded():\n            return True\n\n        self.result.SetError(ret.GetError())\n        self.result.SetStatus(ret.GetStatus())\n        return False\n\n    def is_continue(self, interpreter, command):\n        ret = lldb.SBCommandReturnObject()\n        interpreter.ResolveCommand(command, ret)\n        return ret.GetOutput() == \"process continue\"\n"
  },
  {
    "path": "commands/FBDelay.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nfrom threading import Timer\n\nimport fbchisellldbbase as fb\nimport lldb\n\n\ndef lldbcommands():\n    return [FBDelay()]\n\n\nclass FBDelay(fb.FBCommand):\n    def name(self):\n        return \"zzz\"\n\n    def description(self):\n        return \"Executes specified lldb command after delay.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"delay in seconds\",\n                type=\"float\",\n                help=\"time to wait before executing specified command\",\n            ),\n            fb.FBCommandArgument(\n                arg=\"lldb command\",\n                type=\"string\",\n                help=\"another lldb command to execute after specified delay\",\n                default=\"process interrupt\",\n            ),\n        ]\n\n    def run(self, arguments, options):\n        lldb.debugger.SetAsync(True)\n        lldb.debugger.HandleCommand(\"process continue\")\n        delay = float(arguments[0])\n        command = str(arguments[1])\n        t = Timer(delay, lambda: self.runDelayed(command))\n        t.start()\n\n    def runDelayed(self, command):\n        lldb.debugger.HandleCommand(\"process interrupt\")\n        lldb.debugger.HandleCommand(command)\n"
  },
  {
    "path": "commands/FBDisplayCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport fbchisellldbbase as fb\nimport fbchisellldbobjcruntimehelpers as runtimeHelpers\nimport fbchisellldbviewcontrollerhelpers as viewControllerHelpers\nimport fbchisellldbviewhelpers as viewHelpers\nimport lldb\n\n\ndef lldbcommands():\n    return [\n        FBCoreAnimationFlushCommand(),\n        FBDrawBorderCommand(),\n        FBRemoveBorderCommand(),\n        FBMaskViewCommand(),\n        FBUnmaskViewCommand(),\n        FBShowViewCommand(),\n        FBHideViewCommand(),\n        FBPresentViewControllerCommand(),\n        FBDismissViewControllerCommand(),\n        FBSlowAnimationCommand(),\n        FBUnslowAnimationCommand(),\n    ]\n\n\nclass FBDrawBorderCommand(fb.FBCommand):\n    colors = [\n        \"black\",\n        \"gray\",\n        \"red\",\n        \"green\",\n        \"blue\",\n        \"cyan\",\n        \"yellow\",\n        \"magenta\",\n        \"orange\",\n        \"purple\",\n        \"brown\",\n    ]\n\n    def name(self):\n        return \"border\"\n\n    def description(self):\n        return \"Draws a border around <viewOrLayer>. Color and width can be optionally provided. Additionally depth can be provided in order to recursively border subviews.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"viewOrLayer\",\n                type=\"UIView/NSView/CALayer *\",\n                help=\"The view/layer to border. NSViews must be layer-backed.\",\n            )\n        ]\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-c\",\n                long=\"--color\",\n                arg=\"color\",\n                type=\"string\",\n                default=\"red\",\n                help=\"A color name such as 'red', 'green', 'magenta', etc.\",\n            ),\n            fb.FBCommandArgument(\n                short=\"-w\",\n                long=\"--width\",\n                arg=\"width\",\n                type=\"CGFloat\",\n                default=2.0,\n                help=\"Desired width of border.\",\n            ),\n            fb.FBCommandArgument(\n                short=\"-d\",\n                long=\"--depth\",\n                arg=\"depth\",\n                type=\"int\",\n                default=0,\n                help=\"Number of levels of subviews to border. Each level gets a different color beginning with the provided or default color\",\n            ),\n        ]\n\n    def run(self, args, options):\n        def setBorder(layer, width, color, colorClass):\n            fb.evaluateEffect(\"[%s setBorderWidth:(CGFloat)%s]\" % (layer, width))\n            fb.evaluateEffect(\n                \"[%s setBorderColor:(CGColorRef)[(id)[%s %sColor] CGColor]]\"\n                % (layer, colorClass, color)\n            )\n\n        obj = fb.evaluateInputExpression(args[0])\n        depth = int(options.depth)\n        isMac = runtimeHelpers.isMacintoshArch()\n        color = options.color\n        assert color in self.colors, \"Color must be one of the following: {}\".format(\n            \" \".join(self.colors)\n        )\n        colorClassName = \"UIColor\"\n        if isMac:\n            colorClassName = \"NSColor\"\n\n        if viewHelpers.isView(obj):\n            prevLevel = 0\n            for view, level in viewHelpers.subviewsOfView(obj):\n                if level > depth:\n                    break\n                if prevLevel != level:\n                    color = self.nextColorAfterColor(color)\n                    prevLevel = level\n                layer = viewHelpers.convertToLayer(view)\n                setBorder(layer, options.width, color, colorClassName)\n        else:\n            # `obj` is not a view, make sure recursive bordering is not requested\n            assert depth <= 0, (\n                \"Recursive bordering is only supported for UIViews or NSViews\"\n            )\n            layer = viewHelpers.convertToLayer(obj)\n            setBorder(layer, options.width, color, colorClassName)\n\n        lldb.debugger.HandleCommand(\"caflush\")\n\n    def nextColorAfterColor(self, color):\n        assert color in self.colors, \"{} is not a supported color\".format(color)\n        return self.colors[(self.colors.index(color) + 1) % len(self.colors)]\n\n\nclass FBRemoveBorderCommand(fb.FBCommand):\n    def name(self):\n        return \"unborder\"\n\n    def description(self):\n        return \"Removes border around <viewOrLayer>.\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-d\",\n                long=\"--depth\",\n                arg=\"depth\",\n                type=\"int\",\n                default=0,\n                help=\"Number of levels of subviews to unborder.\",\n            )\n        ]\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"viewOrLayer\",\n                type=\"UIView/NSView/CALayer *\",\n                help=\"The view/layer to unborder.\",\n            )\n        ]\n\n    def run(self, args, options):\n        def setUnborder(layer):\n            fb.evaluateEffect(\"[%s setBorderWidth:(CGFloat)%s]\" % (layer, 0))\n\n        obj = args[0]\n        depth = int(options.depth)\n        if viewHelpers.isView(obj):\n            for view, level in viewHelpers.subviewsOfView(obj):\n                if level > depth:\n                    break\n                layer = viewHelpers.convertToLayer(view)\n                setUnborder(layer)\n        else:\n            # `obj` is not a view, make sure recursive unbordering is not requested\n            assert depth <= 0, (\n                \"Recursive unbordering is only supported for UIViews or NSViews\"\n            )\n            layer = viewHelpers.convertToLayer(obj)\n            setUnborder(layer)\n\n        lldb.debugger.HandleCommand(\"caflush\")\n\n\nclass FBMaskViewCommand(fb.FBCommand):\n    def name(self):\n        return \"mask\"\n\n    def description(self):\n        return \"Add a transparent rectangle to the window to reveal a possibly obscured or hidden view or layer's bounds\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"viewOrLayer\",\n                type=\"UIView/NSView/CALayer *\",\n                help=\"The view/layer to mask.\",\n            )\n        ]\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-c\",\n                long=\"--color\",\n                arg=\"color\",\n                type=\"string\",\n                default=\"red\",\n                help=\"A color name such as 'red', 'green', 'magenta', etc.\",\n            ),\n            fb.FBCommandArgument(\n                short=\"-a\",\n                long=\"--alpha\",\n                arg=\"alpha\",\n                type=\"CGFloat\",\n                default=0.5,\n                help=\"Desired alpha of mask.\",\n            ),\n        ]\n\n    def run(self, args, options):\n        viewOrLayer = fb.evaluateObjectExpression(args[0])\n        viewHelpers.maskView(viewOrLayer, options.color, options.alpha)\n\n\nclass FBUnmaskViewCommand(fb.FBCommand):\n    def name(self):\n        return \"unmask\"\n\n    def description(self):\n        return \"Remove mask from a view or layer\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"viewOrLayer\",\n                type=\"UIView/CALayer *\",\n                help=\"The view/layer to mask.\",\n            )\n        ]\n\n    def run(self, args, options):\n        viewOrLayer = fb.evaluateObjectExpression(args[0])\n        viewHelpers.unmaskView(viewOrLayer)\n\n\nclass FBCoreAnimationFlushCommand(fb.FBCommand):\n    def name(self):\n        return \"caflush\"\n\n    def description(self):\n        return \"Force Core Animation to flush. This will 'repaint' the UI but also may mess with ongoing animations.\"\n\n    def run(self, arguments, options):\n        viewHelpers.flushCoreAnimationTransaction()\n\n\nclass FBShowViewCommand(fb.FBCommand):\n    def name(self):\n        return \"show\"\n\n    def description(self):\n        return \"Show a view or layer.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"viewOrLayer\",\n                type=\"UIView/NSView/CALayer *\",\n                help=\"The view/layer to show.\",\n            )\n        ]\n\n    def run(self, args, options):\n        viewHelpers.setViewHidden(args[0], False)\n\n\nclass FBHideViewCommand(fb.FBCommand):\n    def name(self):\n        return \"hide\"\n\n    def description(self):\n        return \"Hide a view or layer.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"viewOrLayer\",\n                type=\"UIView/NSView/CALayer *\",\n                help=\"The view/layer to hide.\",\n            )\n        ]\n\n    def run(self, args, options):\n        viewHelpers.setViewHidden(args[0], True)\n\n\nclass FBPresentViewControllerCommand(fb.FBCommand):\n    def name(self):\n        return \"present\"\n\n    def description(self):\n        return \"Present a view controller.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"viewController\",\n                type=\"UIViewController *\",\n                help=\"The view controller to present.\",\n            )\n        ]\n\n    def run(self, args, option):\n        viewControllerHelpers.presentViewController(args[0])\n\n\nclass FBDismissViewControllerCommand(fb.FBCommand):\n    def name(self):\n        return \"dismiss\"\n\n    def description(self):\n        return \"Dismiss a presented view controller.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"viewController\",\n                type=\"UIViewController *\",\n                help=\"The view controller to dismiss.\",\n            )\n        ]\n\n    def run(self, args, option):\n        viewControllerHelpers.dismissViewController(args[0])\n\n\nclass FBSlowAnimationCommand(fb.FBCommand):\n    def name(self):\n        return \"slowanim\"\n\n    def description(self):\n        return \"Slows down animations. Works on the iOS Simulator and a device.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"speed\",\n                type=\"float\",\n                default=0.1,\n                help=\"Animation speed (default 0.1).\",\n            )\n        ]\n\n    def run(self, args, option):\n        viewHelpers.slowAnimation(args[0])\n\n\nclass FBUnslowAnimationCommand(fb.FBCommand):\n    def name(self):\n        return \"unslowanim\"\n\n    def description(self):\n        return \"Turn off slow animations.\"\n\n    def run(self, args, option):\n        viewHelpers.slowAnimation()\n"
  },
  {
    "path": "commands/FBFindCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport os\nimport re\n\nimport fbchisellldbbase as fb\nimport fbchisellldbobjcruntimehelpers as objc\nimport fbchisellldbviewcontrollerhelpers as vcHelpers\nimport lldb\n\n\ndef lldbcommands():\n    return [FBFindViewControllerCommand(), FBFindViewCommand(), FBTapLoggerCommand()]\n\n\nclass FBFindViewControllerCommand(fb.FBCommand):\n    def name(self):\n        return \"fvc\"\n\n    def description(self):\n        return \"Find the view controllers whose class names match classNameRegex and puts the address of first on the clipboard.\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-n\",\n                long=\"--name\",\n                arg=\"classNameRegex\",\n                type=\"string\",\n                help=\"The view-controller-class regex to search the view controller hierarchy for.\",\n            ),\n            fb.FBCommandArgument(\n                short=\"-v\",\n                long=\"--view\",\n                arg=\"view\",\n                type=\"UIView\",\n                help=\"This function will print the View Controller that owns this view.\",\n            ),\n        ]\n\n    def run(self, arguments, options):\n        if options.classNameRegex and options.view:\n            print(\"Do not set both the --name and --view flags\")\n        elif options.view:\n            self.findOwningViewController(options.view)\n        else:\n            output = vcHelpers.viewControllerRecursiveDescription(\n                \"(id)[[[UIApplication sharedApplication] keyWindow] rootViewController]\"\n            )\n            searchString = (\n                options.classNameRegex if options.classNameRegex else arguments[0]\n            )\n            printMatchesInViewOutputStringAndCopyFirstToClipboard(searchString, output)\n\n    def findOwningViewController(self, object):\n        while object:\n            if self.isViewController(object):\n                description = fb.evaluateExpressionValue(object).GetObjectDescription()\n                print(\"Found the owning view controller.\\n{}\".format(description))\n                cmd = 'echo {} | tr -d \"\\n\" | pbcopy'.format(object)\n                os.system(cmd)\n                return\n            else:\n                object = self.nextResponder(object)\n        print(\"Could not find an owning view controller\")\n\n    @staticmethod\n    def isViewController(object):\n        command = \"[(id){} isKindOfClass:[UIViewController class]]\".format(object)\n        isVC = fb.evaluateBooleanExpression(command)\n        return isVC\n\n    @staticmethod\n    def nextResponder(object):\n        command = \"[((id){}) nextResponder]\".format(object)\n        nextResponder = fb.evaluateObjectExpression(command)\n        try:\n            if int(nextResponder, 0):\n                return nextResponder\n            else:\n                return None\n        except Exception:\n            return None\n\n\nclass FBFindViewCommand(fb.FBCommand):\n    def name(self):\n        return \"fv\"\n\n    def description(self):\n        return \"Find the views whose class names match classNameRegex and puts the address of first on the clipboard.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"classNameRegex\",\n                type=\"string\",\n                help=\"The view-class regex to search the view hierarchy for.\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        output = fb.evaluateExpressionValue(\n            \"(id)[[[UIApplication sharedApplication] keyWindow] recursiveDescription]\"\n        ).GetObjectDescription()\n        printMatchesInViewOutputStringAndCopyFirstToClipboard(arguments[0], output)\n\n\ndef printMatchesInViewOutputStringAndCopyFirstToClipboard(needle, haystack):\n    first = None\n    for match in re.finditer(\n        \".*<.*(\" + needle + \")\\\\S*: (0x[0-9a-fA-F]*);.*\", haystack, re.IGNORECASE\n    ):\n        view = match.groups()[-1]\n        className = fb.evaluateExpressionValue(\n            \"(id)[(\" + view + \") class]\"\n        ).GetObjectDescription()\n        print(\"{} {}\".format(view, className))\n        if first is None:\n            first = view\n            cmd = 'echo %s | tr -d \"\\n\" | pbcopy' % view\n            os.system(cmd)\n\n\nclass FBTapLoggerCommand(fb.FBCommand):\n    def name(self):\n        return \"taplog\"\n\n    def description(self):\n        return \"Log tapped view to the console.\"\n\n    def run(self, arguments, options):\n        parameterExpr = objc.functionPreambleExpressionForObjectParameterAtIndex(0)\n        breakpoint = lldb.debugger.GetSelectedTarget().BreakpointCreateByName(\n            \"-[UIApplication sendEvent:]\"\n        )\n        breakpoint.SetCondition(\n            \"(int)[\"\n            + parameterExpr\n            + \" type] == 0 && (int)[[[\"\n            + parameterExpr\n            + \" allTouches] anyObject] phase] == 0\"\n        )\n        breakpoint.SetOneShot(True)\n\n        callback_name = taplog_callback.__qualname__\n        # Import the callback so LLDB can see it\n        lldb.debugger.HandleCommand(\n            \"script from %s import %s\" % (__name__, callback_name)\n        )\n        breakpoint.SetScriptCallbackFunction(callback_name)\n\n        lldb.debugger.SetAsync(True)\n        lldb.debugger.HandleCommand(\"continue\")\n\n\ndef taplog_callback(frame, bp_loc, internal_dict):\n    parameterExpr = objc.functionPreambleExpressionForObjectParameterAtIndex(0)\n    print(\n        \"Gesture Recognizers:\\n{}\".format(\n            fb.describeObject(\n                \"[[[%s allTouches] anyObject] gestureRecognizers]\" % (parameterExpr)\n            )\n        )\n    )\n    print(\n        \"View:\\n{}\".format(\n            fb.describeObject(\"[[[%s allTouches] anyObject] view]\" % (parameterExpr))\n        )\n    )\n    # We don't want to proceed event (click on button for example), so we just skip it\n    lldb.debugger.HandleCommand(\"thread return\")\n"
  },
  {
    "path": "commands/FBFlickerCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport os\nimport sys\n\nimport fbchisellldbbase as fb\nimport fbchisellldbobjcruntimehelpers as runtimeHelpers\nimport fbchisellldbviewhelpers as viewHelpers\nimport lldb\n\n\ndef lldbcommands():\n    return [FBFlickerViewCommand(), FBViewSearchCommand()]\n\n\nclass FBFlickerViewCommand(fb.FBCommand):\n    def name(self):\n        return \"flicker\"\n\n    def description(self):\n        return \"Quickly show and hide a view to quickly help visualize where it is.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"viewOrLayer\", type=\"UIView/NSView*\", help=\"The view to flicker.\"\n            )\n        ]\n\n    def run(self, arguments, options):\n        object = fb.evaluateObjectExpression(arguments[0])\n\n        isHidden = fb.evaluateBooleanExpression(\"[\" + object + \" isHidden]\")\n        shouldHide = not isHidden\n        for _ in range(0, 2):\n            viewHelpers.setViewHidden(object, shouldHide)\n            viewHelpers.setViewHidden(object, isHidden)\n\n\nclass FBViewSearchCommand(fb.FBCommand):\n    def name(self):\n        return \"vs\"\n\n    def description(self):\n        return \"Interactively search for a view by walking the hierarchy.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(arg=\"view\", type=\"UIView*\", help=\"The view to border.\")\n        ]\n\n    def run(self, arguments, options):\n        print(\n            \"\\nUse the following and (q) to quit.\\n(w) move to superview\\n(s) move to first subview\\n(a) move to previous sibling\\n(d) move to next sibling\\n(p) print the hierarchy\\n\"\n        )\n\n        object = fb.evaluateInputExpression(arguments[0])\n        walker = FlickerWalker(object)\n        walker.run()\n\n\nclass FlickerWalker:\n    def __init__(self, startView):\n        self.setCurrentView(startView)\n\n    def run(self):\n        self.keepRunning = True\n        initialAsync = lldb.debugger.GetAsync()\n        # Needed so XCode doesn't hang if tap on Continue while lldb\n        # is waiting for user input in 'vs' mode\n        lldb.debugger.SetAsync(True)\n        while self.keepRunning:\n            charRead = sys.stdin.readline().rstrip(\"\\n\")\n            self.inputCallback(charRead)\n        else:\n            lldb.debugger.SetAsync(initialAsync)\n\n    def inputCallback(self, input):\n        oldView = self.currentView\n\n        if input == \"q\":\n            cmd = 'echo %s | tr -d \"\\n\" | pbcopy' % oldView\n            os.system(cmd)\n\n            print(\n                \"\\nI hope \"\n                + oldView\n                + \" was what you were looking for. I put it on your clipboard.\"\n            )\n            viewHelpers.unmaskView(oldView)\n            self.keepRunning = False\n\n        elif input == \"w\":\n            v = superviewOfView(self.currentView)\n            if not v:\n                print(\"There is no superview. Where are you trying to go?!\")\n            self.setCurrentView(v, oldView)\n        elif input == \"s\":\n            v = firstSubviewOfView(self.currentView)\n            if not v:\n                print(\"\\nThe view has no subviews.\\n\")\n            self.setCurrentView(v, oldView)\n        elif input == \"d\":\n            v = nthSiblingOfView(self.currentView, -1)\n            if v == oldView:\n                print(\"\\nThere are no sibling views to this view.\\n\")\n            self.setCurrentView(v, oldView)\n        elif input == \"a\":\n            v = nthSiblingOfView(self.currentView, 1)\n            if v == oldView:\n                print(\"\\nThere are no sibling views to this view.\\n\")\n            self.setCurrentView(v, oldView)\n        elif input == \"p\":\n            recursionName = \"recursiveDescription\"\n            isMac = runtimeHelpers.isMacintoshArch()\n\n            if isMac:\n                recursionName = \"_subtreeDescription\"\n\n            print(fb.describeObject(\"[(id){} {}]\".format(oldView, recursionName)))\n        else:\n            print(\"\\nI really have no idea what you meant by '\" + input + \"'... =\\\\\\n\")\n\n    def setCurrentView(self, view, oldView=None):\n        if view:\n            self.currentView = view\n            if oldView:\n                viewHelpers.unmaskView(oldView)\n            viewHelpers.maskView(self.currentView, \"red\", \"0.4\")\n            print(fb.describeObject(view))\n\n\ndef superviewOfView(view):\n    superview = fb.evaluateObjectExpression(\"[\" + view + \" superview]\")\n    if int(superview, 16) == 0:\n        return None\n\n    return superview\n\n\ndef subviewsOfView(view):\n    return fb.evaluateObjectExpression(\"[\" + view + \" subviews]\")\n\n\ndef firstSubviewOfView(view):\n    subviews = subviewsOfView(view)\n    numViews = fb.evaluateIntegerExpression(\"[(id)\" + subviews + \" count]\")\n\n    if numViews == 0:\n        return None\n    else:\n        return fb.evaluateObjectExpression(\"[\" + subviews + \" objectAtIndex:0]\")\n\n\ndef nthSiblingOfView(view, n):\n    subviews = subviewsOfView(superviewOfView(view))\n    numViews = fb.evaluateIntegerExpression(\"[(id)\" + subviews + \" count]\")\n\n    idx = fb.evaluateIntegerExpression(\n        \"[(id)\" + subviews + \" indexOfObject:\" + view + \"]\"\n    )\n\n    newIdx = idx + n\n    while newIdx < 0:\n        newIdx += numViews\n    newIdx = newIdx % numViews\n\n    return fb.evaluateObjectExpression(\n        \"[(id)\" + subviews + \" objectAtIndex:\" + str(newIdx) + \"]\"\n    )\n"
  },
  {
    "path": "commands/FBImportCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport fbchisellldbbase as fb\nimport lldb\n\n\ndef lldbcommands():\n    return [ImportUIKitModule()]\n\n\nclass ImportUIKitModule(fb.FBCommand):\n    def name(self):\n        return \"uikit\"\n\n    def description(self):\n        return \"Imports the UIKit module to get access to the types while in lldb.\"\n\n    def run(self, arguments, options):\n        frame = (\n            lldb.debugger.GetSelectedTarget()\n            .GetProcess()\n            .GetSelectedThread()\n            .GetSelectedFrame()\n        )\n        fb.importModule(frame, \"UIKit\")\n"
  },
  {
    "path": "commands/FBInvocationCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport re\n\nimport fbchisellldbbase as fb\nimport lldb\n\n\ndef lldbcommands():\n    return [FBPrintInvocation()]\n\n\nclass FBPrintInvocation(fb.FBCommand):\n    def name(self):\n        return \"pinvocation\"\n\n    def description(self):\n        return \"Print the stack frame, receiver, and arguments of the current invocation. It will fail to print all arguments if any arguments are variadic (varargs).\\n\\nNOTE: Sadly this is currently only implemented on x86.\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-a\",\n                long=\"--all\",\n                arg=\"all\",\n                default=False,\n                boolean=True,\n                help=\"Specify to print the entire stack instead of just the current frame.\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        target = lldb.debugger.GetSelectedTarget()\n\n        if not re.match(r\".*i386.*\", target.GetTriple()):\n            print(\"Only x86 is currently supported (32-bit iOS Simulator or Mac OS X).\")\n            return\n\n        thread = target.GetProcess().GetSelectedThread()\n\n        if options.all:\n            for frame in thread:\n                printInvocationForFrame(frame)\n                print(\"---------------------------------\")\n        else:\n            frame = thread.GetSelectedFrame()\n            printInvocationForFrame(frame)\n\n\ndef printInvocationForFrame(frame):\n    print(frame)\n\n    symbolName = frame.GetSymbol().GetName()\n    if not re.match(r\"[-+]\\s*\\[.*\\]\", symbolName):\n        return\n\n    self = findArgAtIndexFromStackFrame(frame, 0)\n    cmd = findArgAtIndexFromStackFrame(frame, 1)\n\n    commandForSignature = (\n        \"[(id)\"\n        + self\n        + \" methodSignatureForSelector:(char *)sel_getName((SEL)\"\n        + cmd\n        + \")]\"\n    )\n    signatureValue = fb.evaluateExpressionValue(\"(id)\" + commandForSignature)\n\n    if (\n        signatureValue.GetError() is not None\n        and str(signatureValue.GetError()) != \"success\"\n    ):\n        print(\n            \"My sincerest apologies. I couldn't find a method signature for the selector.\"\n        )\n        return\n\n    signature = signatureValue.GetValue()\n\n    arg0 = stackStartAddressInSelectedFrame(frame)\n    commandForInvocation = (\n        \"[NSInvocation _invocationWithMethodSignature:(id)\"\n        + signature\n        + \" frame:((void *)\"\n        + str(arg0)\n        + \")]\"\n    )\n    invocation = fb.evaluateExpression(\"(id)\" + commandForInvocation)\n\n    if invocation:\n        prettyPrintInvocation(frame, invocation)\n    else:\n        print(frame)\n\n\ndef stackStartAddressInSelectedFrame(frame):\n    # Determine if the %ebp register has already had the\n    # stack register pushed into it (always the first instruction)\n    frameSymbol = frame.GetSymbolContext(0).GetSymbol()\n    frameStartAddress = frameSymbol.GetStartAddress().GetLoadAddress(\n        lldb.debugger.GetSelectedTarget()\n    )\n\n    currentPC = frame.GetPC()\n\n    offset = currentPC - frameStartAddress\n\n    if offset == 0:\n        return int(frame.EvaluateExpression(\"($esp + 4)\").GetValue())\n    elif offset == 1:\n        return int(frame.EvaluateExpression(\"($esp + 8)\").GetValue())\n    else:\n        return int(frame.EvaluateExpression(\"($ebp + 8)\").GetValue())\n\n\ndef findArgAtIndexFromStackFrame(frame, index):\n    return fb.evaluateExpression(\n        \"*(int *)\" + str(findArgAdressAtIndexFromStackFrame(frame, index))\n    )\n\n\ndef findArgAdressAtIndexFromStackFrame(frame, index):\n    arg0 = stackStartAddressInSelectedFrame(frame)\n    arg = arg0 + 4 * index\n    return arg\n\n\ndef prettyPrintInvocation(frame, invocation):\n    object = fb.evaluateExpression(\"(id)[(id)\" + invocation + \" target]\")\n    description = fb.evaluateExpressionValue(\"(id)\" + invocation).GetObjectDescription()\n    argDescriptions = description.splitlines(True)[4:]\n\n    print(\"NSInvocation: \" + invocation)\n    print(\"self: \" + fb.evaluateExpression(\"(id)\" + object))\n\n    if len(argDescriptions) > 0:\n        print(\n            \"\\n\" + str(len(argDescriptions)) + \" Arguments:\"\n            if len(argDescriptions) > 1\n            else \"\\nArgument:\"\n        )\n\n        index = 2\n        for argDescription in argDescriptions:\n            s = re.sub(r\"argument [0-9]+: \", \"\", argDescription)\n\n            address = findArgAdressAtIndexFromStackFrame(frame, index)\n\n            encoding = s.split(\" \")[0]\n            description = \" \".join(s.split(\" \")[1:])\n\n            readableString = argumentAsString(frame, address, encoding)\n\n            if readableString:\n                print(readableString)\n            else:\n                if encoding[0] == \"{\":\n                    encoding = encoding[1:]\n                print(\n                    (\n                        hex(address) + \", address of \" + encoding + \" \" + description\n                    ).strip()\n                )\n\n            index += 1\n\n\ndef argumentAsString(frame, address, encoding):  # noqa C901\n    if encoding[0] == \"{\":\n        encoding = encoding[1:]\n\n    encodingMap = {\n        \"c\": \"char\",\n        \"i\": \"int\",\n        \"s\": \"short\",\n        \"l\": \"long\",\n        \"q\": \"long long\",\n        \"C\": \"unsigned char\",\n        \"I\": \"unsigned int\",\n        \"S\": \"unsigned short\",\n        \"L\": \"unsigned long\",\n        \"Q\": \"unsigned long long\",\n        \"f\": \"float\",\n        \"d\": \"double\",\n        \"B\": \"bool\",\n        \"v\": \"void\",\n        \"*\": \"char *\",\n        \"@\": \"id\",\n        \"#\": \"Class\",\n        \":\": \"SEL\",\n    }\n\n    pointers = \"\"\n    while encoding[0] == \"^\":\n        pointers += \"*\"\n        encoding = encoding[1:]\n\n    type = None\n    if encoding in encodingMap:\n        type = encodingMap[encoding]\n\n    if type and pointers:\n        type = type + \" \" + pointers\n\n    if not type:\n        # Handle simple structs: {CGPoint=ff}, {CGSize=ff},\n        # {CGRect={CGPoint=ff}{CGSize=ff}}\n        if encoding[0] == \"{\":\n            encoding = encoding[1:]\n\n        type = re.sub(r\"=.*\", \"\", encoding)\n        if pointers:\n            type += \" \" + pointers\n\n    if type:\n        value = frame.EvaluateExpression(\"*(\" + type + \" *)\" + str(address))\n\n        if value.GetError() is None or str(value.GetError()) == \"success\":\n            description = None\n\n            if encoding == \"@\":\n                description = value.GetObjectDescription()\n\n            if not description:\n                description = value.GetValue()\n            if not description:\n                description = value.GetSummary()\n            if description:\n                return type + \": \" + description\n\n    return None\n"
  },
  {
    "path": "commands/FBPrintCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport os\nimport re\nimport subprocess\n\nimport fbchisellldbbase as fb\nimport fbchisellldbobjcruntimehelpers as runtimeHelpers\nimport fbchisellldbviewcontrollerhelpers as vcHelpers\nimport fbchisellldbviewhelpers as viewHelpers\nimport lldb\n\n\ndef lldbcommands():\n    return [\n        FBPrintViewHierarchyCommand(),\n        FBPrintViewControllerHierarchyCommand(),\n        FBPrintIsExecutingInAnimationBlockCommand(),\n        FBPrintInheritanceHierarchy(),\n        FBPrintUpwardResponderChain(),\n        FBPrintOnscreenTableView(),\n        FBPrintOnscreenTableViewCells(),\n        FBPrintInternals(),\n        FBPrintInstanceVariable(),\n        FBPrintKeyPath(),\n        FBPrintApplicationDocumentsPath(),\n        FBPrintApplicationBundlePath(),\n        FBPrintData(),\n        FBPrintTargetActions(),\n        FBPrintJSON(),\n        FBPrintSwiftJSON(),\n        FBPrintAsCurl(),\n        FBPrintToClipboard(),\n        FBPrintObjectInObjc(),\n    ]\n\n\nclass FBPrintViewHierarchyCommand(fb.FBCommand):\n    def name(self):\n        return \"pviews\"\n\n    def description(self):\n        return \"Print the recursion description of <aView>.\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-u\",\n                long=\"--up\",\n                arg=\"upwards\",\n                boolean=True,\n                default=False,\n                help=\"Print only the hierarchy directly above the view, up to its window.\",\n            ),\n            fb.FBCommandArgument(\n                short=\"-d\",\n                long=\"--depth\",\n                arg=\"depth\",\n                type=\"int\",\n                default=\"0\",\n                help=\"Print only to a given depth. 0 indicates infinite depth.\",\n            ),\n            fb.FBCommandArgument(\n                short=\"-w\",\n                long=\"--window\",\n                arg=\"window\",\n                type=\"int\",\n                default=\"0\",\n                help='Specify the window to print a description of. Check which windows exist with \"po (id)[[UIApplication sharedApplication] windows]\".',\n            ),\n            fb.FBCommandArgument(\n                short=\"-s\",\n                long=\"--short\",\n                arg=\"short\",\n                boolean=True,\n                default=False,\n                help=\"Print a short description of the view\",\n            ),\n            fb.FBCommandArgument(\n                short=\"-m\",\n                long=\"--medium\",\n                arg=\"medium\",\n                boolean=True,\n                default=False,\n                help=\"Print a medium description of the view\",\n            ),\n        ]\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"aView\",\n                type=\"UIView*/NSView*\",\n                help=\"The view to print the description of.\",\n                default=\"__keyWindow_dynamic__\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        maxDepth = int(options.depth)\n        window = int(options.window)\n        isMac = runtimeHelpers.isMacintoshArch()\n\n        if window > 0:\n            if isMac:\n                arguments[0] = (\n                    \"(id)[[[[NSApplication sharedApplication] windows] objectAtIndex:\"\n                    + str(window)\n                    + \"] contentView]\"\n                )\n            else:\n                arguments[0] = (\n                    \"(id)[[[UIApplication sharedApplication] windows] objectAtIndex:\"\n                    + str(window)\n                    + \"]\"\n                )\n        elif arguments[0] == \"__keyWindow_dynamic__\":\n            if isMac:\n                arguments[0] = (\n                    \"(id)[[[[NSApplication sharedApplication] windows] objectAtIndex:0] contentView]\"\n                )\n            else:\n                arguments[0] = \"(id)[[UIApplication sharedApplication] keyWindow]\"\n\n        if options.upwards:\n            view = arguments[0]\n            description = viewHelpers.upwardsRecursiveDescription(view, maxDepth)\n            if description:\n                print(description)\n            else:\n                print(\n                    \"Failed to walk view hierarchy. Make sure you pass a view, not any other kind of object or expression.\"\n                )\n        else:\n            printingMethod = \"recursiveDescription\"\n            if isMac:\n                printingMethod = \"_subtreeDescription\"\n\n            description = fb.evaluateExpressionValue(\n                \"(id)[\" + arguments[0] + \" \" + printingMethod + \"]\"\n            ).GetObjectDescription()\n            if maxDepth > 0:\n                separator = re.escape(\"   | \")\n                prefixToRemove = separator * maxDepth + \" \"\n                description += \"\\n\"\n                description = re.sub(r\"%s.*\\n\" % (prefixToRemove), r\"\", description)\n\n            if options.short:\n                toRemove = \":.*(?:\\n|$)\"\n                description = re.sub(toRemove, r\">\\n\", description)\n            elif options.medium:\n                toRemove = \";.*(?:\\n|$)\"\n                description = re.sub(toRemove, r\">\\n\", description)\n\n            print(description)\n\n\nclass FBPrintViewControllerHierarchyCommand(fb.FBCommand):\n    def name(self):\n        return \"pvc\"\n\n    def description(self):\n        return \"Print the recursion description of <aViewController>.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"aViewController\",\n                type=\"UIViewController*\",\n                help=\"The view controller to print the description of.\",\n                default=\"__keyWindow_rootVC_dynamic__\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        isMac = runtimeHelpers.isMacintoshArch()\n\n        if arguments[0] == \"__keyWindow_rootVC_dynamic__\":\n            if fb.evaluateBooleanExpression(\n                \"[UIViewController respondsToSelector:@selector(_printHierarchy)]\"\n            ):\n                print(fb.describeObject(\"[UIViewController _printHierarchy]\"))\n                return\n\n            arguments[0] = (\n                \"(id)[(id)[[UIApplication sharedApplication] keyWindow] rootViewController]\"\n            )\n            if isMac:\n                arguments[0] = (\n                    \"(id)[[[[NSApplication sharedApplication] windows] objectAtIndex:0] contentViewController]\"\n                )\n\n        print(vcHelpers.viewControllerRecursiveDescription(arguments[0]))\n\n\nclass FBPrintIsExecutingInAnimationBlockCommand(fb.FBCommand):\n    def name(self):\n        return \"panim\"\n\n    def description(self):\n        return (\n            \"Prints if the code is currently execution with a UIView animation block.\"\n        )\n\n    def run(self, arguments, options):\n        lldb.debugger.HandleCommand(\"p (BOOL)[UIView _isInAnimationBlock]\")\n\n\ndef _printIterative(initialValue, generator):\n    indent = 0\n    for currentValue in generator(initialValue):\n        print(\"   | \" * indent + currentValue)\n        indent += 1\n\n\nclass FBPrintInheritanceHierarchy(fb.FBCommand):\n    def name(self):\n        return \"pclass\"\n\n    def description(self):\n        return \"Print the inheritance starting from an instance of any class.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"object\", type=\"id\", help=\"The instance to examine.\"\n            )\n        ]\n\n    def run(self, arguments, options):\n        _printIterative(arguments[0], _inheritanceHierarchy)\n\n\ndef _inheritanceHierarchy(instanceOfAClass):\n    instanceAddress = fb.evaluateExpression(instanceOfAClass)\n    instanceClass = fb.evaluateExpression(\"(id)[(id)\" + instanceAddress + \" class]\")\n    while int(instanceClass, 16):\n        yield fb.evaluateExpressionValue(instanceClass).GetObjectDescription()\n        instanceClass = fb.evaluateExpression(\n            \"(id)[(id)\" + instanceClass + \" superclass]\"\n        )\n\n\nclass FBPrintUpwardResponderChain(fb.FBCommand):\n    def name(self):\n        return \"presponder\"\n\n    def description(self):\n        return \"Print the responder chain starting from a specific responder.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"startResponder\",\n                type=\"UIResponder *\",\n                help=\"The responder to use to start walking the chain.\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        startResponder = fb.evaluateInputExpression(arguments[0])\n\n        isMac = runtimeHelpers.isMacintoshArch()\n        responderClass = \"UIResponder\"\n        if isMac:\n            responderClass = \"NSResponder\"\n\n        if not fb.evaluateBooleanExpression(\n            \"(BOOL)[(id)\"\n            + startResponder\n            + \" isKindOfClass:[\"\n            + responderClass\n            + \" class]]\"\n        ):\n            print(\"Whoa, \" + startResponder + \" is not a \" + responderClass + \". =(\")\n            return\n\n        _printIterative(startResponder, _responderChain)\n\n\ndef _responderChain(startResponder):\n    responderAddress = fb.evaluateExpression(startResponder)\n    while int(responderAddress, 16):\n        yield fb.evaluateExpressionValue(responderAddress).GetObjectDescription()\n        responderAddress = fb.evaluateExpression(\n            \"(id)[(id)\" + responderAddress + \" nextResponder]\"\n        )\n\n\ndef tableViewInHierarchy():\n    viewDescription = fb.evaluateExpressionValue(\n        \"(id)[(id)[[UIApplication sharedApplication] keyWindow] recursiveDescription]\"\n    ).GetObjectDescription()\n\n    searchView = None\n\n    # Try to find an instance of\n    classPattern = re.compile(r\"UITableView: (0x[0-9a-fA-F]+);\")\n    for match in re.finditer(classPattern, viewDescription):\n        searchView = match.group(1)\n        break\n\n    # Try to find a direct subclass\n    if not searchView:\n        subclassPattern = re.compile(r\"(0x[0-9a-fA-F]+); baseClass = UITableView;\")\n        for match in re.finditer(subclassPattern, viewDescription):\n            searchView = match.group(1)\n            break\n\n    # SLOW: check every pointer in town\n    if not searchView:\n        pattern = re.compile(r\"(0x[0-9a-fA-F]+)[;>]\")\n        for view in re.findall(pattern, viewDescription):\n            if fb.evaluateBooleanExpression(\n                \"[\" + view + \" isKindOfClass:(id)[UITableView class]]\"\n            ):\n                searchView = view\n                break\n\n    return searchView\n\n\nclass FBPrintOnscreenTableView(fb.FBCommand):\n    def name(self):\n        return \"ptv\"\n\n    def description(self):\n        return \"Print the highest table view in the hierarchy.\"\n\n    def run(self, arguments, options):\n        tableView = tableViewInHierarchy()\n        if tableView:\n            viewValue = fb.evaluateExpressionValue(tableView)\n            print(viewValue.GetObjectDescription())\n            cmd = 'echo %s | tr -d \"\\n\" | pbcopy' % tableView\n            os.system(cmd)\n        else:\n            print(\"Sorry, chump. I couldn't find a table-view. :'(\")\n\n\nclass FBPrintOnscreenTableViewCells(fb.FBCommand):\n    def name(self):\n        return \"pcells\"\n\n    def description(self):\n        return \"Print the visible cells of the highest table view in the hierarchy.\"\n\n    def run(self, arguments, options):\n        tableView = tableViewInHierarchy()\n        print(\n            fb.evaluateExpressionValue(\n                \"(id)[(id)\" + tableView + \" visibleCells]\"\n            ).GetObjectDescription()\n        )\n\n\nclass FBPrintInternals(fb.FBCommand):\n    def name(self):\n        return \"pinternals\"\n\n    def description(self):\n        return \"Show the internals of an object by dereferencing it as a pointer.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"object\", type=\"id\", help=\"Object expression to be evaluated.\"\n            )\n        ]\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"appleWay\",\n                short=\"-a\",\n                long=\"--apple\",\n                boolean=True,\n                default=False,\n                help=\"Print ivars the apple way\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        object = fb.evaluateObjectExpression(arguments[0])\n        if options.appleWay:\n            if fb.evaluateBooleanExpression(\n                \"[{} respondsToSelector:@selector(_ivarDescription)]\".format(object)\n            ):\n                command = \"po [{} _ivarDescription]\".format(object)\n            else:\n                print(\"Sorry, but it seems Apple dumped the _ivarDescription method\")\n                return\n        else:\n            objectClass = fb.evaluateExpressionValue(\n                \"(id)[(id)(\" + object + \") class]\"\n            ).GetObjectDescription()\n            command = \"p *(({} *)((id){}))\".format(objectClass, object)\n        lldb.debugger.HandleCommand(command)\n\n\nclass FBPrintInstanceVariable(fb.FBCommand):\n    def name(self):\n        return \"pivar\"\n\n    def description(self):\n        return \"Print the value of an object's named instance variable.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"object\", type=\"id\", help=\"Object expression to be evaluated.\"\n            ),\n            fb.FBCommandArgument(\n                arg=\"ivarName\", help=\"Name of instance variable to print.\"\n            ),\n        ]\n\n    def run(self, arguments, options):\n        object = fb.evaluateInputExpression(arguments[0])\n        ivarName = arguments[1]\n\n        objectClass = fb.evaluateExpressionValue(\n            \"(id)[(\" + object + \") class]\"\n        ).GetObjectDescription()\n\n        ivarTypeCommand = '((char *)ivar_getTypeEncoding((void*)object_getInstanceVariable((id){}, \"{}\", 0)))[0]'.format(\n            object, ivarName\n        )\n        ivarTypeEncodingFirstChar = fb.evaluateExpression(ivarTypeCommand)\n\n        result = fb.evaluateExpressionValue(\n            \"(({} *)({}))->{}\".format(objectClass, object, ivarName)\n        )\n        print(\n            result.GetObjectDescription()\n            if \"@\" in ivarTypeEncodingFirstChar\n            else result\n        )\n\n\nclass FBPrintKeyPath(fb.FBCommand):\n    def name(self):\n        return \"pkp\"\n\n    def description(self):\n        return \"Print out the value of the key path expression using -valueForKeyPath:\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"keypath\", type=\"NSString *\", help=\"The keypath to print\"\n            )\n        ]\n\n    def run(self, arguments, options):\n        command = arguments[0]\n        if len(command.split(\".\")) == 1:\n            lldb.debugger.HandleCommand(\"po \" + command)\n        else:\n            objectToMessage, keypath = command.split(\".\", 1)\n            object = fb.evaluateObjectExpression(objectToMessage)\n            print(\n                fb.describeObject('[{} valueForKeyPath:@\"{}\"]'.format(object, keypath))\n            )\n\n\nclass FBPrintApplicationDocumentsPath(fb.FBCommand):\n    def name(self):\n        return \"pdocspath\"\n\n    def description(self):\n        return \"Print application's 'Documents' directory path.\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-o\",\n                long=\"--open\",\n                arg=\"open\",\n                boolean=True,\n                default=False,\n                help=\"open in Finder\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        # in iOS SDK NSDocumentDirectory == 9  NSUserDomainMask == 1\n        NSDocumentDirectory = \"9\"\n        NSUserDomainMask = \"1\"\n        path = fb.evaluateExpressionValue(\n            \"(NSString*)[NSSearchPathForDirectoriesInDomains(\"\n            + NSDocumentDirectory\n            + \", \"\n            + NSUserDomainMask\n            + \", YES) lastObject]\"\n        )\n        pathString = \"{}\".format(path).split('\"')[1]\n        cmd = 'echo {} | tr -d \"\\n\" | pbcopy'.format(pathString)\n        os.system(cmd)\n        print(pathString)\n        if options.open:\n            os.system(\"open \" + pathString)\n\n\nclass FBPrintApplicationBundlePath(fb.FBCommand):\n    def name(self):\n        return \"pbundlepath\"\n\n    def description(self):\n        return \"Print application's bundle directory path.\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-o\",\n                long=\"--open\",\n                arg=\"open\",\n                boolean=True,\n                default=False,\n                help=\"open in Finder\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        path = fb.evaluateExpressionValue(\n            \"(NSString*)[[NSBundle mainBundle] bundlePath]\"\n        )\n        pathString = \"{}\".format(path).split('\"')[1]\n        cmd = 'echo {} | tr -d \"\\n\" | pbcopy'.format(pathString)\n        os.system(cmd)\n        print(pathString)\n        if options.open:\n            os.system(\"open \" + pathString)\n\n\nclass FBPrintData(fb.FBCommand):\n    def name(self):\n        return \"pdata\"\n\n    def description(self):\n        return (\n            \"Print the contents of NSData object as string.\\n\"\n            \"Supported encodings:\\n\"\n            \"- ascii,\\n\"\n            \"- utf8,\\n\"\n            \"- utf16, unicode,\\n\"\n            \"- utf16l (Little endian),\\n\"\n            \"- utf16b (Big endian),\\n\"\n            \"- utf32,\\n\"\n            \"- utf32l (Little endian),\\n\"\n            \"- utf32b (Big endian),\\n\"\n            \"- latin1, iso88591 (88591),\\n\"\n            \"- latin2, iso88592 (88592),\\n\"\n            \"- cp1251 (1251),\\n\"\n            \"- cp1252 (1252),\\n\"\n            \"- cp1253 (1253),\\n\"\n            \"- cp1254 (1254),\\n\"\n            \"- cp1250 (1250),\"\n        )\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"encoding\",\n                short=\"-e\",\n                long=\"--encoding\",\n                type=\"string\",\n                help=\"Used encoding (default utf-8).\",\n                default=\"utf-8\",\n            )\n        ]\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(arg=\"data\", type=\"NSData *\", help=\"NSData object.\")\n        ]\n\n    def run(self, arguments, option):  # noqa C901\n        # Normalize encoding.\n        encoding_text = option.encoding.lower().replace(\" -\", \"\")\n        enc = 4  # Default encoding UTF-8.\n        if encoding_text == \"ascii\":\n            enc = 1\n        elif encoding_text == \"utf8\":\n            enc = 4\n        elif (\n            encoding_text == \"latin1\"\n            or encoding_text == \"88591\"\n            or encoding_text == \"iso88591\"\n        ):\n            enc = 5\n        elif (\n            encoding_text == \"latin2\"\n            or encoding_text == \"88592\"\n            or encoding_text == \"iso88592\"\n        ):\n            enc = 9\n        elif encoding_text == \"unicode\" or encoding_text == \"utf16\":\n            enc = 10\n        elif encoding_text == \"1251\" or encoding_text == \"cp1251\":\n            enc = 11\n        elif encoding_text == \"1252\" or encoding_text == \"cp1252\":\n            enc = 12\n        elif encoding_text == \"1253\" or encoding_text == \"cp1253\":\n            enc = 13\n        elif encoding_text == \"1254\" or encoding_text == \"cp1254\":\n            enc = 14\n        elif encoding_text == \"1250\" or encoding_text == \"cp1250\":\n            enc = 15\n        elif encoding_text == \"utf16b\":\n            enc = 0x90000100\n        elif encoding_text == \"utf16l\":\n            enc = 0x94000100\n        elif encoding_text == \"utf32\":\n            enc = 0x8C000100\n        elif encoding_text == \"utf32b\":\n            enc = 0x98000100\n        elif encoding_text == \"utf32l\":\n            enc = 0x9C000100\n\n        print(\n            fb.describeObject(\n                \"[[NSString alloc] initWithData:{} encoding:{}]\".format(\n                    arguments[0], enc\n                )\n            )\n        )\n\n\nclass FBPrintTargetActions(fb.FBCommand):\n    def name(self):\n        return \"pactions\"\n\n    def description(self):\n        return \"Print the actions and targets of a control.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"control\",\n                type=\"UIControl *\",\n                help=\"The control to inspect the actions of.\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        control = fb.evaluateInputExpression(arguments[0])\n        targets = fb.evaluateObjectExpression(\n            \"[[{control} allTargets] allObjects]\".format(control=control)\n        )\n        targetCount = fb.evaluateIntegerExpression(\n            \"[{targets} count]\".format(targets=targets)\n        )\n\n        for index in range(0, targetCount):\n            target = fb.evaluateObjectExpression(\n                \"[{targets} objectAtIndex:{index}]\".format(targets=targets, index=index)\n            )\n            actions = fb.evaluateObjectExpression(\n                \"[{control} actionsForTarget:{target} forControlEvent:0]\".format(\n                    control=control, target=target\n                )\n            )\n\n            targetDescription = fb.evaluateExpressionValue(\n                \"(id){target}\".format(target=target)\n            ).GetObjectDescription()\n            actionsDescription = fb.evaluateExpressionValue(\n                '(id)[{actions} componentsJoinedByString:@\", \"]'.format(actions=actions)\n            ).GetObjectDescription()\n\n            print(\n                \"{target}: {actions}\".format(\n                    target=targetDescription, actions=actionsDescription\n                )\n            )\n\n\nclass FBPrintJSON(fb.FBCommand):\n    def name(self):\n        return \"pjson\"\n\n    def description(self):\n        return \"Print JSON representation of NSDictionary or NSArray object\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"plain\",\n                short=\"-p\",\n                long=\"--plain\",\n                boolean=True,\n                default=False,\n                help=\"Plain JSON\",\n            )\n        ]\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"object\",\n                type=\"id\",\n                help=\"The NSDictionary or NSArray object to print\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        objectToPrint = fb.evaluateInputExpression(arguments[0])\n        pretty = 1 if options.plain is None else 0\n        jsonData = fb.evaluateObjectExpression(\n            \"[NSJSONSerialization dataWithJSONObject:(id){} options:{} error:nil]\".format(\n                objectToPrint, pretty\n            )\n        )\n        jsonString = fb.evaluateExpressionValue(\n            \"(NSString*)[[NSString alloc] initWithData:(id){} encoding:4]\".format(\n                jsonData\n            )\n        ).GetObjectDescription()\n\n        print(jsonString)\n\n\nclass FBPrintSwiftJSON(fb.FBCommand):\n    def name(self):\n        return \"psjson\"\n\n    def description(self):\n        return \"Print JSON representation of Swift Dictionary or Swift Array object\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"plain\",\n                short=\"-p\",\n                long=\"--plain\",\n                boolean=True,\n                default=False,\n                help=\"Plain JSON\",\n            )\n        ]\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"object\",\n                type=\"NSObject *\",\n                help=\"The Swift Dictionary or Swift Array to print\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        # Convert to NSObject first to allow for objc runtime to process it\n        objectToPrint = fb.evaluateInputExpression(\n            \"{obj} as NSObject\".format(obj=arguments[0])\n        )\n        pretty = 1 if options.plain is None else 0\n        jsonData = fb.evaluateObjectExpression(\n            \"[NSJSONSerialization dataWithJSONObject:(NSObject*){} options:{} error:nil]\".format(\n                objectToPrint, pretty\n            )\n        )\n        jsonString = fb.evaluateExpressionValue(\n            \"(NSString*)[[NSString alloc] initWithData:(NSObject*){} encoding:4]\".format(\n                jsonData\n            )\n        ).GetObjectDescription()\n\n        print(jsonString)\n\n\nclass FBPrintAsCurl(fb.FBCommand):\n    def name(self):\n        return \"pcurl\"\n\n    def description(self):\n        return \"Print the NSURLRequest (HTTP) as curl command.\"\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                short=\"-e\",\n                long=\"--embed-data\",\n                arg=\"embed\",\n                boolean=True,\n                default=False,\n                help=\"Embed request data as base64.\",\n            )\n        ]\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"request\",\n                type=\"NSURLRequest*/NSMutableURLRequest*\",\n                help=\"The request to convert to the curl command.\",\n            )\n        ]\n\n    def generateTmpFilePath(self):\n        return \"/tmp/curl_data_{}\".format(\n            fb.evaluateExpression(\n                \"(NSTimeInterval)[NSDate timeIntervalSinceReferenceDate]\"\n            )\n        )\n\n    def run(self, arguments, options):\n        request = fb.evaluateInputExpression(arguments[0])\n        HTTPHeaderSring = \"\"\n        HTTPMethod = fb.evaluateExpressionValue(\n            \"(id)[{} HTTPMethod]\".format(request)\n        ).GetObjectDescription()\n        URL = fb.evaluateExpressionValue(\n            \"(id)[{} URL]\".format(request)\n        ).GetObjectDescription()\n        timeout = fb.evaluateExpression(\n            \"(NSTimeInterval)[{} timeoutInterval]\".format(request)\n        )\n        HTTPHeaders = fb.evaluateObjectExpression(\n            \"(id)[{} allHTTPHeaderFields]\".format(request)\n        )\n        HTTPHeadersCount = fb.evaluateIntegerExpression(\n            \"[{} count]\".format(HTTPHeaders)\n        )\n        allHTTPKeys = fb.evaluateObjectExpression(\"[{} allKeys]\".format(HTTPHeaders))\n        for index in range(0, HTTPHeadersCount):\n            key = fb.evaluateObjectExpression(\n                \"[{} objectAtIndex:{}]\".format(allHTTPKeys, index)\n            )\n            keyDescription = fb.evaluateExpressionValue(\n                \"(id){}\".format(key)\n            ).GetObjectDescription()\n            value = fb.evaluateExpressionValue(\n                \"(id)[(id){} objectForKey:{}]\".format(HTTPHeaders, key)\n            ).GetObjectDescription()\n            if len(HTTPHeaderSring) > 0:\n                HTTPHeaderSring += \" \"\n            HTTPHeaderSring += '-H \"{}: {}\"'.format(keyDescription, value)\n        HTTPData = fb.evaluateObjectExpression(\"[{} HTTPBody]\".format(request))\n        dataFile = None\n        dataAsString = None\n        if fb.evaluateIntegerExpression(\"[{} length]\".format(HTTPData)) > 0:\n            if options.embed:\n                if fb.evaluateIntegerExpression(\n                    \"[{} respondsToSelector:@selector(base64EncodedStringWithOptions:)]\".format(\n                        HTTPData\n                    )\n                ):\n                    dataAsString = fb.evaluateExpressionValue(\n                        \"(id)[(id){} base64EncodedStringWithOptions:0]\".format(HTTPData)\n                    ).GetObjectDescription()\n                else:\n                    print(\"This version of OS doesn't supports base64 data encoding\")\n                    return False\n            elif not runtimeHelpers.isIOSDevice():\n                dataFile = self.generateTmpFilePath()\n                if not fb.evaluateBooleanExpression(\n                    '(BOOL)[{} writeToFile:@\"{}\" atomically:NO]'.format(\n                        HTTPData, dataFile\n                    )\n                ):\n                    print(\"Can't write data to file {}\".format(dataFile))\n                    return False\n            else:\n                print(\n                    'HTTPBody data for iOS Device is supported only with \"--embed-data\" flag'\n                )\n                return False\n\n        commandString = \"\"\n        if dataAsString is not None and len(dataAsString) > 0:\n            dataFile = self.generateTmpFilePath()\n            commandString += 'echo \"{}\" | base64 -D -o \"{}\" && '.format(\n                dataAsString, dataFile\n            )\n        commandString += \"curl -X {} --connect-timeout {}\".format(HTTPMethod, timeout)\n        if len(HTTPHeaderSring) > 0:\n            commandString += \" \" + HTTPHeaderSring\n        if dataFile is not None:\n            commandString += ' --data-binary @\"{}\"'.format(dataFile)\n\n        commandString += ' \"{}\"'.format(URL)\n        print(commandString)\n\n\nclass FBPrintToClipboard(fb.FBCommand):\n    def name(self):\n        return \"pbcopy\"\n\n    def description(self):\n        return \"Print object and copy output to clipboard\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(arg=\"object\", type=\"id\", help=\"The object to print\")\n        ]\n\n    def run(self, arguments, options):\n        lldbOutput = fb.evaluateExpressionValue(\n            \"[{changeset} description]\".format(changeset=arguments[0])\n        ).GetObjectDescription()\n        process = subprocess.Popen(\n            \"pbcopy\", env={\"LANG\": \"en_US.UTF-8\"}, stdin=subprocess.PIPE\n        )\n        process.communicate(lldbOutput.encode(\"utf-8\"))\n        print(\"Object copied to clipboard\")\n\n\nclass FBPrintObjectInObjc(fb.FBCommand):\n    def name(self):\n        return \"poobjc\"\n\n    def description(self):\n        return 'Print the expression result, with the expression run in an ObjC++ context. (Shortcut for \"expression -O -l ObjC++ -- \" )'\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"expression\", help=\"ObjC expression to evaluate and print.\"\n            )\n        ]\n\n    def run(self, arguments, options):\n        expression = arguments[0]\n        lldb.debugger.HandleCommand(\"expression -O -l ObjC++ -- \" + expression)\n"
  },
  {
    "path": "commands/FBTextInputCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport fbchisellldbbase as fb\nimport fbchisellldbviewhelpers as viewHelpers\n\n\nACCESSIBILITY_ID = 0\nREPLACEMENT_TEXT = 1\nINPUT_TEXT = 0\n\n\ndef lldbcommands():\n    return [FBInputTexByAccessibilityIdCommand(), FBInputTexToFirstResponderCommand()]\n\n\nclass FBInputTexByAccessibilityIdCommand(fb.FBCommand):\n    def name(self):\n        return \"settext\"\n\n    def description(self):\n        return \"Set text on a view by accessibility id.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"accessibilityId\",\n                type=\"string\",\n                help=\"The accessibility ID of the input view.\",\n            ),\n            fb.FBCommandArgument(\n                arg=\"replacementText\", type=\"string\", help=\"The text to set.\"\n            ),\n        ]\n\n    def run(self, arguments, options):\n        self.findView(\n            rootView(), arguments[ACCESSIBILITY_ID], arguments[REPLACEMENT_TEXT]\n        )\n\n    def findView(self, view, searchIdentifier, replacementText):\n        views = subviewsOfView(view)\n        for index in range(0, viewsCount(views)):\n            subview = subviewAtIndex(views, index)\n            self.findView(subview, searchIdentifier, replacementText)\n        else:\n            identifier = accessibilityIdentifier(view)\n            if isEqualToString(identifier, searchIdentifier):\n                setTextInView(view, replacementText)\n\n\nclass FBInputTexToFirstResponderCommand(fb.FBCommand):\n    def name(self):\n        return \"setinput\"\n\n    def description(self):\n        return \"Input text into text field or text view that is first responder.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"inputText\", type=\"string\", help=\"The text to input.\"\n            )\n        ]\n\n    def run(self, arguments, options):\n        self.findFirstResponder(rootView(), arguments[INPUT_TEXT])\n\n    def findFirstResponder(self, view, replacementText):\n        views = subviewsOfView(view)\n        if isFirstResponder(view):\n            setTextInView(view, replacementText)\n        else:\n            for index in range(0, viewsCount(views)):\n                subview = subviewAtIndex(views, index)\n                self.findFirstResponder(subview, replacementText)\n\n\n# Some helpers\ndef rootView():\n    return fb.evaluateObjectExpression(\"[[UIApplication sharedApplication] keyWindow]\")\n\n\ndef subviewsOfView(view):\n    return fb.evaluateObjectExpression(\"[%s subviews]\" % view)\n\n\ndef subviewAtIndex(views, index):\n    return fb.evaluateObjectExpression(\"[%s objectAtIndex:%i]\" % (views, index))\n\n\ndef viewsCount(views):\n    return int(fb.evaluateExpression(\"(int)[%s count]\" % views))\n\n\ndef accessibilityIdentifier(view):\n    return fb.evaluateObjectExpression(\"[%s accessibilityIdentifier]\" % view)\n\n\ndef isEqualToString(identifier, needle):\n    return fb.evaluateBooleanExpression(\n        '[%s isEqualToString:@\"%s\"]' % (identifier, needle)\n    )\n\n\ndef setTextInView(view, text):\n    fb.evaluateObjectExpression('[%s setText:@\"%s\"]' % (view, text))\n    viewHelpers.flushCoreAnimationTransaction()\n\n\ndef isFirstResponder(view):\n    return fb.evaluateBooleanExpression(\"[%s isFirstResponder]\" % view)\n"
  },
  {
    "path": "commands/FBVisualizationCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport errno\nimport os\nimport time\n\nimport fbchisellldbbase as fb\nimport fbchisellldbobjecthelpers as objectHelpers\nimport lldb\n\n\ndef lldbcommands():\n    return [FBVisualizeCommand()]\n\n\ndef _showImage(commandForImage):\n    imageDirectory = \"/tmp/xcode_debug_images/\"\n\n    imageName = time.strftime(\"%Y-%m-%d-%H-%M-%S\", time.gmtime()) + \".png\"\n    imagePath = imageDirectory + imageName\n\n    try:\n        os.makedirs(imageDirectory)\n    except OSError as e:\n        if e.errno == errno.EEXIST and os.path.isdir(imageDirectory):\n            pass\n        else:\n            raise\n\n    toPNG = \"(id)UIImagePNGRepresentation((id){})\".format(commandForImage)\n    imageDataAddress = fb.evaluateExpressionValue(toPNG, tryAllThreads=True).GetValue()\n    imageBytesStartAddress = fb.evaluateExpression(\n        \"(void *)[(id)\" + imageDataAddress + \" bytes]\"\n    )\n    imageBytesLength = fb.evaluateExpression(\n        \"(NSUInteger)[(id)\" + imageDataAddress + \" length]\"\n    )\n\n    address = int(imageBytesStartAddress, 16)\n    length = int(imageBytesLength)\n\n    if not (address or length):\n        print(\"Could not get image data.\")\n        return\n\n    process = lldb.debugger.GetSelectedTarget().GetProcess()\n    error = lldb.SBError()\n    mem = process.ReadMemory(address, length, error)\n\n    if error is not None and str(error) != \"success\":\n        print(error)\n    else:\n        with open(imagePath, \"wb\") as imgFile:\n            imgFile.write(mem)\n        os.system(\"open \" + imagePath)\n\n\ndef _colorIsCGColorRef(color):\n    color = \"(CGColorRef)(\" + color + \")\"\n\n    result = fb.evaluateExpressionValue(\n        \"(unsigned long)CFGetTypeID({color}) == (unsigned long)CGColorGetTypeID()\".format(\n            color=color\n        )\n    )\n\n    if result.GetError() is not None and str(result.GetError()) != \"success\":\n        print(\"got error: {}\".format(result))\n        return False\n    else:\n        isCFColor = result.GetValueAsUnsigned() != 0\n        return isCFColor\n\n\ndef _showColor(color):\n    color = \"(\" + color + \")\"\n\n    colorToUse = color\n    isCF = _colorIsCGColorRef(color)\n    if isCF:\n        colorToUse = \"[[UIColor alloc] initWithCGColor:(CGColorRef){}]\".format(color)\n    else:\n        isCI = objectHelpers.isKindOfClass(color, \"CIColor\")\n        if isCI:\n            colorToUse = \"[UIColor colorWithCIColor:(CIColor *){}]\".format(color)\n\n    imageSize = 58\n    fb.evaluateEffect(\n        \"UIGraphicsBeginImageContextWithOptions((CGSize)CGSizeMake({imageSize}, {imageSize}), NO, 0.0)\".format(\n            imageSize=imageSize\n        )\n    )\n    fb.evaluateEffect(\"[(id){} setFill]\".format(colorToUse))\n    fb.evaluateEffect(\n        \"UIRectFill((CGRect)CGRectMake(0.0, 0.0, {imageSize}, {imageSize}))\".format(\n            imageSize=imageSize\n        )\n    )\n\n    result = fb.evaluateExpressionValue(\n        \"(UIImage *)UIGraphicsGetImageFromCurrentImageContext()\"\n    )\n    if result.GetError() is not None and str(result.GetError()) != \"success\":\n        print(\"got error {}\".format(result))\n        print(result.GetError())\n    else:\n        image = result.GetValue()\n        _showImage(image)\n\n    fb.evaluateEffect(\"UIGraphicsEndImageContext()\")\n\n\ndef _showLayer(layer):\n    layer = \"(\" + layer + \")\"\n    size = \"((CGRect)[(id)\" + layer + \" bounds]).size\"\n\n    width = float(fb.evaluateExpression(\"(CGFloat)(\" + size + \".width)\"))\n    height = float(fb.evaluateExpression(\"(CGFloat)(\" + size + \".height)\"))\n    if width == 0.0 or height == 0.0:\n        print(\n            \"Nothing to see here - the size of this element is {} x {}.\".format(\n                width, height\n            )\n        )\n        return\n\n    fb.evaluateEffect(\"UIGraphicsBeginImageContextWithOptions(\" + size + \", NO, 0.0)\")\n    fb.evaluateEffect(\n        \"[(id)\" + layer + \" renderInContext:(void *)UIGraphicsGetCurrentContext()]\"\n    )\n\n    result = fb.evaluateExpressionValue(\n        \"(UIImage *)UIGraphicsGetImageFromCurrentImageContext()\"\n    )\n    if result.GetError() is not None and str(result.GetError()) != \"success\":\n        print(result.GetError())\n    else:\n        image = result.GetValue()\n        _showImage(image)\n\n    fb.evaluateEffect(\"UIGraphicsEndImageContext()\")\n\n\ndef _showPixelBuffer(target):\n    imgVar = \"$imageOut\" + str(round(time.time()))\n    fb.evaluateExpression(\"CGImageRef \" + imgVar + \" = NULL\")\n    fb.evaluateExpression(\n        \"(OSStatus)VTCreateCGImageFromCVPixelBuffer((CVPixelBufferRef)\"\n        + target\n        + \", NULL, &\"\n        + imgVar\n        + \")\"\n    )\n    image = fb.evaluateExpression(\"[UIImage imageWithCGImage:\" + imgVar + \"]\")\n    _showImage(image)\n    fb.evaluateExpression(\"CGImageRelease(\" + imgVar + \")\")\n\n\ndef _dataIsImage(data):\n    data = \"(\" + data + \")\"\n\n    result = fb.evaluateExpressionValue(\"(id)[UIImage imageWithData:\" + data + \"]\")\n\n    if result.GetError() is not None and str(result.GetError()) != \"success\":\n        return False\n    else:\n        isImage = result.GetValueAsUnsigned() != 0\n        return isImage\n\n\ndef _dataIsString(data):\n    data = \"(\" + data + \")\"\n\n    result = fb.evaluateExpressionValue(\n        \"(NSString*)[[NSString alloc] initWithData:\" + data + \" encoding:4]\"\n    )\n\n    if result.GetError() is not None and str(result.GetError()) != \"success\":\n        return False\n    else:\n        isString = result.GetValueAsUnsigned() != 0\n        return isString\n\n\ndef _visualize(target):\n    target = fb.evaluateInputExpression(target)\n\n    if fb.evaluateBooleanExpression(\n        \"(unsigned long)CFGetTypeID((CFTypeRef)\"\n        + target\n        + \") == (unsigned long)CGImageGetTypeID()\"\n    ):\n        _showImage(\"(id)[UIImage imageWithCGImage:\" + target + \"]\")\n    elif fb.evaluateBooleanExpression(\n        \"(unsigned long)CFGetTypeID((CFTypeRef)\"\n        + target\n        + \") == (unsigned long)CVPixelBufferGetTypeID()\"\n    ):\n        _showPixelBuffer(target)\n    else:\n        if objectHelpers.isKindOfClass(target, \"UIImage\"):\n            _showImage(target)\n        elif objectHelpers.isKindOfClass(target, \"UIView\"):\n            _showLayer(\"[(id)\" + target + \" layer]\")\n        elif objectHelpers.isKindOfClass(target, \"CALayer\"):\n            _showLayer(target)\n        elif (\n            objectHelpers.isKindOfClass(target, \"UIColor\")\n            or objectHelpers.isKindOfClass(target, \"CIColor\")\n            or _colorIsCGColorRef(target)\n        ):\n            _showColor(target)\n        elif objectHelpers.isKindOfClass(target, \"NSData\"):\n            if _dataIsImage(target):\n                _showImage(\"(id)[UIImage imageWithData:\" + target + \"]\")\n            elif _dataIsString(target):\n                print(\n                    fb.describeObject(\n                        \"[[NSString alloc] initWithData:\" + target + \" encoding:4]\"\n                    )\n                )\n            else:\n                print(\"Data isn't an image and isn't a string.\")\n        elif objectHelpers.isKindOfClass(target, \"CIImage\"):\n            _showImage(\"[UIImage imageWithCIImage:(id)\" + target + \"]\")\n        else:\n            print(\n                \"{} isn't supported. You can visualize UIImage, CGImageRef, UIView, CALayer, NSData, UIColor, CIColor, CIImage, CGColorRef or CVPixelBuffer.\".format(\n                    objectHelpers.className(target)\n                )\n            )\n\n\nclass FBVisualizeCommand(fb.FBCommand):\n    def name(self):\n        return \"visualize\"\n\n    def description(self):\n        return \"Open a UIImage, CGImageRef, UIView, CALayer, NSData, UIColor, CIColor, CIImage, CGColorRef or CVPixelBuffer in Preview.app on your Mac.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"target\", type=\"(id)\", help=\"The object to visualize.\"\n            )\n        ]\n\n    def run(self, arguments, options):\n        _visualize(arguments[0])\n"
  },
  {
    "path": "commands/FBXCTestCommands.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport re\n\nimport fbchisellldbbase as fb\nimport lldb\n\n\nNOT_FOUND = 0xFFFFFFFF  # UINT32_MAX\n\n\ndef lldbcommands():\n    return [FBXCPrintDebugDescription(), FBXCPrintTree(), FBXCPrintObject(), FBXCNoId()]\n\n\nclass FBXCPrintDebugDescription(fb.FBCommand):\n    def name(self):\n        return \"xdebug\"\n\n    def description(self):\n        return \"Print debug description the XCUIElement in human readable format.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"element\",\n                type=\"XCUIElement*\",\n                help=\"The element to print debug description.\",\n                default=\"__default__\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        element = arguments[0]\n        language = fb.currentLanguage()\n\n        if element == \"__default__\":\n            element = (\n                \"XCUIApplication()\"\n                if language == lldb.eLanguageTypeSwift\n                else \"(XCUIApplication *)[[XCUIApplication alloc] init]\"\n            )\n\n        if language == lldb.eLanguageTypeSwift:\n            print(\n                fb.evaluateExpressionValue(\n                    \"{}.debugDescription\".format(element), language=language\n                )\n                .GetObjectDescription()\n                .replace(\"\\\\n\", \"\\n\")\n                .replace(\"\\\\'\", \"'\")\n                .strip(' \"\\n\\t')\n            )\n        else:\n            print(\n                fb.evaluateExpressionValue(\n                    \"[{} debugDescription]\".format(element)\n                ).GetObjectDescription()\n            )\n\n\nclass FBXCPrintTree(fb.FBCommand):\n    def name(self):\n        return \"xtree\"\n\n    def description(self):\n        return \"Print XCUIElement subtree.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"element\",\n                type=\"XCUIElement*\",\n                help=\"The element to print tree.\",\n                default=\"__default__\",\n            )\n        ]\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"pointer\",\n                short=\"-p\",\n                long=\"--pointer\",\n                type=\"BOOL\",\n                boolean=True,\n                default=False,\n                help=\"Print pointers\",\n            ),\n            fb.FBCommandArgument(\n                arg=\"trait\",\n                short=\"-t\",\n                long=\"--traits\",\n                type=\"BOOL\",\n                boolean=True,\n                default=False,\n                help=\"Print traits\",\n            ),\n            fb.FBCommandArgument(\n                arg=\"frame\",\n                short=\"-f\",\n                long=\"--frame\",\n                type=\"BOOL\",\n                boolean=True,\n                default=False,\n                help=\"Print frames\",\n            ),\n        ]\n\n    def run(self, arguments, options):\n        element = arguments[0]\n        language = fb.currentLanguage()\n        if element == \"__default__\":\n            element = (\n                \"XCUIApplication()\"\n                if language == lldb.eLanguageTypeSwift\n                else \"(XCUIApplication *)[[XCUIApplication alloc] init]\"\n            )\n\n        # Evaluate object\n        element_sbvalue = fb.evaluateExpressionValue(\n            \"{}\".format(element), language=language\n        )\n        \"\"\":type: lldb.SBValue\"\"\"\n\n        # Get pointer value, so it will be working in Swift and Objective-C\n        element_pointer = int(element_sbvalue.GetValue(), 16)\n\n        # Get XCElementSnapshot object\n        snapshot = take_snapshot(element_pointer)\n\n        # Print tree for snapshot element\n        snapshot_object = XCElementSnapshot(snapshot, language=language)\n        print(\n            snapshot_object.tree().hierarchy_text(\n                pointer=options.pointer, trait=options.trait, frame=options.frame\n            )\n        )\n\n\nclass FBXCPrintObject(fb.FBCommand):\n    def name(self):\n        return \"xobject\"\n\n    def description(self):\n        return \"Print XCUIElement details.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"element\",\n                type=\"XCUIElement*\",\n                help=\"The element to print details.\",\n                default=\"__default__\",\n            )\n        ]\n\n    def run(self, arguments, options):\n        element = arguments[0]\n        language = fb.currentLanguage()\n        if element == \"__default__\":\n            element = (\n                \"XCUIApplication()\"\n                if language == lldb.eLanguageTypeSwift\n                else \"(XCUIApplication *)[[XCUIApplication alloc] init]\"\n            )\n\n        # Evaluate object\n        element_sbvalue = fb.evaluateExpressionValue(\n            \"{}\".format(element), language=language\n        )\n        \"\"\":type: lldb.SBValue\"\"\"\n\n        # Get pointer value, so it will be working in Swift and Objective-C\n        element_pointer = int(element_sbvalue.GetValue(), 16)\n\n        # Get XCElementSnapshot object\n        snapshot = take_snapshot(element_pointer)\n\n        # Print details of snapshot element\n        snapshot_object = XCElementSnapshot(snapshot, language=language)\n        print(snapshot_object.detail_summary())\n\n\nclass FBXCNoId(fb.FBCommand):\n    def name(self):\n        return \"xnoid\"\n\n    def description(self):\n        return \"Print XCUIElement objects with label but without identifier.\"\n\n    def args(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"element\",\n                type=\"XCUIElement*\",\n                help=\"The element from start to.\",\n                default=\"__default__\",\n            )\n        ]\n\n    def options(self):\n        return [\n            fb.FBCommandArgument(\n                arg=\"status_bar\",\n                short=\"-s\",\n                long=\"--status-bar\",\n                type=\"BOOL\",\n                boolean=True,\n                default=False,\n                help=\"Print status bar items\",\n            ),\n            fb.FBCommandArgument(\n                arg=\"pointer\",\n                short=\"-p\",\n                long=\"--pointer\",\n                type=\"BOOL\",\n                boolean=True,\n                default=False,\n                help=\"Print pointers\",\n            ),\n            fb.FBCommandArgument(\n                arg=\"trait\",\n                short=\"-t\",\n                long=\"--traits\",\n                type=\"BOOL\",\n                boolean=True,\n                default=False,\n                help=\"Print traits\",\n            ),\n            fb.FBCommandArgument(\n                arg=\"frame\",\n                short=\"-f\",\n                long=\"--frame\",\n                type=\"BOOL\",\n                boolean=True,\n                default=False,\n                help=\"Print frames\",\n            ),\n        ]\n\n    def run(self, arguments, options):\n        element = arguments[0]\n        language = fb.currentLanguage()\n        if element == \"__default__\":\n            element = (\n                \"XCUIApplication()\"\n                if language == lldb.eLanguageTypeSwift\n                else \"(XCUIApplication *)[[XCUIApplication alloc] init]\"\n            )\n\n        # Evaluate object\n        element_sbvalue = fb.evaluateExpressionValue(\n            \"{}\".format(element), language=language\n        )\n        \"\"\":type: lldb.SBValue\"\"\"\n\n        # Get pointer value, so it will be working in Swift and Objective-C\n        element_pointer = int(element_sbvalue.GetValue(), 16)\n\n        # Get XCElementSnapshot object\n        snapshot = take_snapshot(element_pointer)\n\n        # Print tree for snapshot element\n        snapshot_object = XCElementSnapshot(snapshot, language=language)\n        elements = snapshot_object.find_missing_identifiers(\n            status_bar=options.status_bar\n        )\n        if elements is not None:\n            print(\n                elements.hierarchy_text(\n                    pointer=options.pointer, trait=options.trait, frame=options.frame\n                )\n            )\n        else:\n            print(\"Couldn't found elements without identifier\")\n\n\ndef take_snapshot(element):\n    \"\"\"\n    Takes snapshot (XCElementSnapshot) from XCUIElement (as pointer)\n\n    :param int element: Pointer to the XCUIElement\n    :return: XCElementSnapshot object\n    :rtype: lldb.SBValue\n    \"\"\"\n    return fb.evaluateExpressionValue(\n        \"(XCElementSnapshot *)[[[{} query] matchingSnapshotsWithError:nil] firstObject]\".format(\n            element\n        )\n    )\n\n\nclass _ElementList(object):\n    \"\"\"\n    Store element and list of children\n\n    :param XCElementSnapshot element: XCElementSnapshot\n    :param list[_ElementList] children: List of XCElementSnapshot objects\n    \"\"\"\n\n    def __init__(self, element, children):\n        self.element = element\n        self.children = children\n\n    def text(self, pointer, trait, frame, indent):\n        \"\"\"\n        String representation of the element\n\n        :param bool pointer: Print pointers\n        :param bool trait: Print traits\n        :param bool frame: Print frames\n        :param int indent: Indention\n        :return: String representation of the element\n        :rtype: str\n        \"\"\"\n        indent_string = \" | \" * indent\n        return \"{}{}\\n\".format(\n            indent_string,\n            self.element.summary(pointer=pointer, trait=trait, frame=frame),\n        )\n\n    def hierarchy_text(self, pointer=False, trait=False, frame=False, indent=0):\n        \"\"\"\n        String representation of the hierarchy of elements\n\n        :param bool pointer: Print pointers\n        :param bool trait: Print traits\n        :param bool frame: Print frames\n        :param int indent: Indention\n        :return: String representation of the hierarchy of elements\n        :rtype: str\n        \"\"\"\n        s = self.text(pointer=pointer, trait=trait, frame=frame, indent=indent)\n        for e in self.children:\n            s += e.hierarchy_text(\n                pointer=pointer, trait=trait, frame=frame, indent=indent + 1\n            )\n        return s\n\n\nclass XCElementSnapshot(object):\n    \"\"\"\n    XCElementSnapshot wrapper\n\n    :param lldb.SBValue element: XCElementSnapshot object\n    :param str element_value: Pointer to XCElementSnapshot object\n    :param language: Project language\n    :param lldb.SBValue _type: XCUIElement type / XCUIElementType\n    :param lldb.SBValue _traits: UIAccessibilityTraits\n    :param lldb.SBValue | None _frame: XCUIElement frame\n    :param lldb.SBValue _identifier: XCUIElement identifier\n    :param lldb.SBValue _value: XCUIElement value\n    :param lldb.SBValue _placeholderValue: XCUIElement placeholder value\n    :param lldb.SBValue _label: XCUIElement label\n    :param lldb.SBValue _title: XCUIElement title\n    :param lldb.SBValue _children: XCUIElement children\n    :param lldb.SBValue _enabled: XCUIElement is enabled\n    :param lldb.SBValue _selected: XCUIElement is selected\n    :param lldb.SBValue _isMainWindow: XCUIElement is main window\n    :param lldb.SBValue _hasKeyboardFocus: XCUIElement has keyboard focus\n    :param lldb.SBValue _hasFocus: XCUIElement has focus\n    :param lldb.SBValue _generation: XCUIElement generation\n    :param lldb.SBValue _horizontalSizeClass: XCUIElement horizontal class\n    :param lldb.SBValue _verticalSizeClass: XCUIElement vertical class\n    \"\"\"\n\n    def __init__(self, element, language):\n        \"\"\"\n        :param lldb.SBValue element: XCElementSnapshot object\n        :param language: Project language\n        \"\"\"\n        super(XCElementSnapshot, self).__init__()\n        self.element = element\n        self.element_value = self.element.GetValue()\n        self.language = language\n\n        self._type = None\n        self._traits = None\n        self._frame = None\n        self._identifier = None\n        self._value = None\n        self._placeholderValue = None\n        self._label = None\n        self._title = None\n        self._children = None\n\n        self._enabled = None\n        self._selected = None\n        self._isMainWindow = None\n        self._hasKeyboardFocus = None\n        self._hasFocus = None\n        self._generation = None\n        self._horizontalSizeClass = None\n        self._verticalSizeClass = None\n\n    @property\n    def is_missing_identifier(self):\n        \"\"\"\n        Checks if element has a label but doesn't have an identifier.\n\n        :return: True if element has a label but doesn't have an identifier.\n        :rtype: bool\n        \"\"\"\n        return len(self.identifier_value) == 0 and len(self.label_value) > 0\n\n    @property\n    def type(self):\n        \"\"\"\n        :return: XCUIElement type / XCUIElementType\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._type is None:\n            name = \"_elementType\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._type = fb.evaluateExpressionValue(\n                    \"(int)[{} elementType]\".format(self.element_value)\n                )\n            else:\n                self._type = self.element.GetChildMemberWithName(name)\n        return self._type\n\n    @property\n    def type_value(self):\n        \"\"\"\n        :return: XCUIElementType value\n        :rtype: int\n        \"\"\"\n        return int(self.type.GetValue())\n\n    @property\n    def type_summary(self):\n        \"\"\"\n        :return: XCUIElementType summary\n        :rtype: str\n        \"\"\"\n        return self.get_type_value_string(self.type_value)\n\n    @property\n    def traits(self):\n        \"\"\"\n        :return: UIAccessibilityTraits\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._traits is None:\n            name = \"_traits\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._traits = fb.evaluateExpressionValue(\n                    \"(int)[{} traits]\".format(self.element_value)\n                )\n            else:\n                self._traits = self.element.GetChildMemberWithName(name)\n        return self._traits\n\n    @property\n    def traits_value(self):\n        \"\"\"\n        :return: UIAccessibilityTraits value\n        :rtype: int\n        \"\"\"\n        return int(self.traits.GetValue())\n\n    @property\n    def traits_summary(self):\n        \"\"\"\n        :return: UIAccessibilityTraits summary\n        :rtype: str\n        \"\"\"\n        return self.get_traits_value_string(self.traits_value)\n\n    @property\n    def frame(self):\n        \"\"\"\n        :return: XCUIElement frame\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._frame is None:\n            import_uikit()\n            name = \"_frame\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._frame = fb.evaluateExpressionValue(\n                    \"(CGRect)[{} frame]\".format(self.element_value)\n                )\n            else:\n                self._frame = self.element.GetChildMemberWithName(name)\n        return self._frame\n\n    @property\n    def frame_summary(self):\n        \"\"\"\n        :return: XCUIElement frame summary\n        :rtype: str\n        \"\"\"\n        return CGRect(self.frame).summary()\n\n    @property\n    def identifier(self):\n        \"\"\"\n        :return: XCUIElement identifier\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._identifier is None:\n            name = \"_identifier\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._identifier = fb.evaluateExpressionValue(\n                    \"(NSString *)[{} identifier]\".format(self.element_value)\n                )\n            else:\n                self._identifier = self.element.GetChildMemberWithName(name)\n        return self._identifier\n\n    @property\n    def identifier_value(self):\n        \"\"\"\n        :return: XCUIElement identifier value\n        :rtype: str\n        \"\"\"\n        return normalize_summary(self.identifier.GetSummary())\n\n    @property\n    def identifier_summary(self):\n        \"\"\"\n        :return: XCUIElement identifier summary\n        :rtype: str | None\n        \"\"\"\n        if len(self.identifier_value) == 0:\n            return None\n        return \"identifier: '{}'\".format(self.identifier_value)\n\n    @property\n    def value(self):\n        \"\"\"\n        :return: XCUIElement value\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._value is None:\n            name = \"_value\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._value = fb.evaluateExpressionValue(\n                    \"(NSString *)[{} value]\".format(self.element_value)\n                )\n            else:\n                self._value = self.element.GetChildMemberWithName(name)\n        return self._value\n\n    @property\n    def value_value(self):\n        \"\"\"\n        :return: XCUIElement value value\n        :rtype: str\n        \"\"\"\n        return normalize_summary(self.value.GetSummary())\n\n    @property\n    def value_summary(self):\n        \"\"\"\n        :return: XCUIElement value summary\n        :rtype: str | None\n        \"\"\"\n        if len(self.value_value) == 0:\n            return None\n        return \"value: '{}'\".format(self.value_value)\n\n    @property\n    def placeholder(self):\n        \"\"\"\n        :return: XCUIElement placeholder value\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._placeholderValue is None:\n            name = \"_placeholderValue\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._placeholderValue = fb.evaluateExpressionValue(\n                    \"(NSString *)[{} placeholderValue]\".format(self.element_value)\n                )\n            else:\n                self._placeholderValue = self.element.GetChildMemberWithName(name)\n        return self._placeholderValue\n\n    @property\n    def placeholder_value(self):\n        \"\"\"\n        :return: XCUIElement placeholderValue value\n        :rtype: str\n        \"\"\"\n        return normalize_summary(self.placeholder.GetSummary())\n\n    @property\n    def placeholder_summary(self):\n        \"\"\"\n        :return: XCUIElement placeholderValue summary\n        :rtype: str | None\n        \"\"\"\n        if len(self.placeholder_value) == 0:\n            return None\n        return \"placeholderValue: '{}'\".format(self.placeholder_value)\n\n    @property\n    def label(self):\n        \"\"\"\n        :return: XCUIElement label\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._label is None:\n            name = \"_label\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._label = fb.evaluateExpressionValue(\n                    \"(NSString *)[{} label]\".format(self.element_value)\n                )\n            else:\n                self._label = self.element.GetChildMemberWithName(name)\n        return self._label\n\n    @property\n    def label_value(self):\n        \"\"\"\n        :return: XCUIElement label value\n        :rtype: str\n        \"\"\"\n        return normalize_summary(self.label.GetSummary())\n\n    @property\n    def label_summary(self):\n        \"\"\"\n        :return: XCUIElement label summary\n        :rtype: str | None\n        \"\"\"\n        if len(self.label_value) == 0:\n            return None\n        return \"label: '{}'\".format(self.label_value)\n\n    @property\n    def title(self):\n        \"\"\"\n        :return: XCUIElement title\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._title is None:\n            name = \"_title\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._title = fb.evaluateExpressionValue(\n                    \"(NSString *)[{} title]\".format(self.element_value)\n                )\n            else:\n                self._title = self.element.GetChildMemberWithName(name)\n        return self._title\n\n    @property\n    def title_value(self):\n        \"\"\"\n        :return: XCUIElement title value\n        :rtype: str\n        \"\"\"\n        return normalize_summary(self.title.GetSummary())\n\n    @property\n    def title_summary(self):\n        \"\"\"\n        :return: XCUIElement title summary\n        :rtype: str | None\n        \"\"\"\n        if len(self.title_value) == 0:\n            return None\n        return \"title: '{}'\".format(self.title_value)\n\n    @property\n    def children(self):\n        \"\"\"\n        :return: XCUIElement children\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._children is None:\n            name = \"_children\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._children = fb.evaluateExpressionValue(\n                    \"(NSArray *)[{} children]\".format(self.element_value)\n                )\n            else:\n                self._children = self.element.GetChildMemberWithName(name)\n        return self._children\n\n    @property\n    def children_count(self):\n        \"\"\"\n        :return: XCUIElement children count\n        :rtype: int\n        \"\"\"\n        return self.children.GetNumChildren()\n\n    @property\n    def children_list(self):\n        \"\"\"\n        :return: XCUIElement children list\n        :rtype: list[lldb.SBValue]\n        \"\"\"\n        return [self.children.GetChildAtIndex(i) for i in range(self.children_count)]\n\n    @property\n    def enabled(self):\n        \"\"\"\n        :return: XCUIElement is enabled\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._enabled is None:\n            name = \"_enabled\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._enabled = fb.evaluateExpressionValue(\n                    \"(BOOL)[{} enabled]\".format(self.element_value)\n                )\n            else:\n                self._enabled = self.element.GetChildMemberWithName(name)\n        return self._enabled\n\n    @property\n    def enabled_value(self):\n        \"\"\"\n        :return: XCUIElement is enabled value\n        :rtype: bool\n        \"\"\"\n        return bool(self.enabled.GetValueAsSigned())\n\n    @property\n    def enabled_summary(self):\n        \"\"\"\n        :return: XCUIElement is enabled summary\n        :rtype: str | None\n        \"\"\"\n        if not self.enabled_value:\n            return \"enabled: {}\".format(self.enabled_value)\n        return None\n\n    @property\n    def selected(self):\n        \"\"\"\n        :return: XCUIElement is selected\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._selected is None:\n            name = \"_selected\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._selected = fb.evaluateExpressionValue(\n                    \"(BOOL)[{} selected]\".format(self.element_value)\n                )\n            else:\n                self._selected = self.element.GetChildMemberWithName(name)\n        return self._selected\n\n    @property\n    def selected_value(self):\n        \"\"\"\n        :return: XCUIElement is selected value\n        :rtype: bool\n        \"\"\"\n        return bool(self.selected.GetValueAsSigned())\n\n    @property\n    def selected_summary(self):\n        \"\"\"\n        :return: XCUIElement is selected summary\n        :rtype: str | None\n        \"\"\"\n        if self.selected_value:\n            return \"selected: {}\".format(self.selected_value)\n        return None\n\n    @property\n    def is_main_window(self):\n        \"\"\"\n        :return: XCUIElement isMainWindow\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._isMainWindow is None:\n            name = \"_isMainWindow\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._isMainWindow = fb.evaluateExpressionValue(\n                    \"(BOOL)[{} isMainWindow]\".format(self.element_value)\n                )\n            else:\n                self._isMainWindow = self.element.GetChildMemberWithName(name)\n        return self._isMainWindow\n\n    @property\n    def is_main_window_value(self):\n        \"\"\"\n        :return: XCUIElement isMainWindow value\n        :rtype: bool\n        \"\"\"\n        return bool(self.is_main_window.GetValueAsSigned())\n\n    @property\n    def is_main_window_summary(self):\n        \"\"\"\n        :return: XCUIElement isMainWindow summary\n        :rtype: str | None\n        \"\"\"\n        if self.is_main_window_value:\n            return \"MainWindow\"\n        return None\n\n    @property\n    def keyboard_focus(self):\n        \"\"\"\n        :return: XCUIElement hasKeyboardFocus\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._hasKeyboardFocus is None:\n            name = \"_hasKeyboardFocus\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._hasKeyboardFocus = fb.evaluateExpressionValue(\n                    \"(BOOL)[{} hasKeyboardFocus]\".format(self.element_value)\n                )\n            else:\n                self._hasKeyboardFocus = self.element.GetChildMemberWithName(name)\n        return self._hasKeyboardFocus\n\n    @property\n    def keyboard_focus_value(self):\n        \"\"\"\n        :return: XCUIElement hasKeyboardFocus value\n        :rtype: bool\n        \"\"\"\n        return bool(self.keyboard_focus.GetValueAsSigned())\n\n    @property\n    def keyboard_focus_summary(self):\n        \"\"\"\n        :return: XCUIElement hasKeyboardFocus summary\n        :rtype: str | None\n        \"\"\"\n        if self.keyboard_focus_value:\n            return \"hasKeyboardFocus: {}\".format(self.keyboard_focus_value)\n        return None\n\n    @property\n    def focus(self):\n        \"\"\"\n        :return: XCUIElement hasFocus\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._hasFocus is None:\n            name = \"_hasFocus\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._hasFocus = fb.evaluateExpressionValue(\n                    \"(BOOL)[{} hasFocus]\".format(self.element_value)\n                )\n            else:\n                self._hasFocus = self.element.GetChildMemberWithName(name)\n        return self._hasFocus\n\n    @property\n    def focus_value(self):\n        \"\"\"\n        :return: XCUIElement hasFocus value\n        :rtype: bool\n        \"\"\"\n        return bool(self.focus.GetValueAsSigned())\n\n    @property\n    def focus_summary(self):\n        \"\"\"\n        :return: XCUIElement hasFocus summary\n        :rtype: str | None\n        \"\"\"\n        if self.focus_value:\n            return \"hasFocus: {}\".format(self.focus_value)\n        return None\n\n    @property\n    def generation(self):\n        \"\"\"\n        :return: XCUIElement generation\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._generation is None:\n            name = \"_generation\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._generation = fb.evaluateExpressionValue(\n                    \"(unsigned int)[{} generation]\".format(self.element_value)\n                )\n            else:\n                self._generation = self.element.GetChildMemberWithName(name)\n        return self._generation\n\n    @property\n    def generation_value(self):\n        \"\"\"\n        :return: XCUIElement generation value\n        :rtype: int\n        \"\"\"\n        return int(self.generation.GetValueAsUnsigned())\n\n    @property\n    def horizontal_size_class(self):\n        \"\"\"\n        :return: XCUIElement horizontal size class\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._horizontalSizeClass is None:\n            name = \"_horizontalSizeClass\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._horizontalSizeClass = fb.evaluateExpressionValue(\n                    \"(int)[{} horizontalSizeClass]\".format(self.element_value)\n                )\n            else:\n                self._horizontalSizeClass = self.element.GetChildMemberWithName(name)\n        return self._horizontalSizeClass\n\n    @property\n    def horizontal_size_class_value(self):\n        \"\"\"\n        :return: XCUIElement horizontal size class value\n        :rtype: int\n        \"\"\"\n        return int(self.horizontal_size_class.GetValue())\n\n    @property\n    def horizontal_size_class_summary(self):\n        \"\"\"\n        :return:  XCUIElement horizontal size class summary\n        \"\"\"\n        return self.get_user_interface_size_class_string(\n            self.horizontal_size_class_value\n        )\n\n    @property\n    def vertical_size_class(self):\n        \"\"\"\n        :return: XCUIElement vertical size class\n        :rtype: lldb.SBValue\n        \"\"\"\n        if self._verticalSizeClass is None:\n            name = \"_verticalSizeClass\"\n            if self.element.GetIndexOfChildWithName(name) == NOT_FOUND:\n                self._verticalSizeClass = fb.evaluateExpressionValue(\n                    \"(int)[{} verticalSizeClass]\".format(self.element_value)\n                )\n            else:\n                self._verticalSizeClass = self.element.GetChildMemberWithName(name)\n        return self._verticalSizeClass\n\n    @property\n    def vertical_size_class_value(self):\n        \"\"\"\n        :return: XCUIElement vertical size class value\n        :rtype: int\n        \"\"\"\n        return int(self.vertical_size_class.GetValue())\n\n    @property\n    def vertical_size_class_summary(self):\n        \"\"\"\n        :return:  XCUIElement vertical size class summary\n        \"\"\"\n        return self.get_user_interface_size_class_string(self.vertical_size_class_value)\n\n    @property\n    def uniquely_identifying_objective_c_code(self):\n        \"\"\"\n        :return: XCUIElement uniquely identifying Objective-C code\n        :rtype: lldb.SBValue\n        \"\"\"\n        return fb.evaluateExpressionValue(\n            \"(id)[{} _uniquelyIdentifyingObjectiveCCode]\".format(self.element_value)\n        )\n\n    @property\n    def uniquely_identifying_objective_c_code_value(self):\n        \"\"\"\n        :return: XCUIElement uniquely identifying Objective-C code value\n        :rtype: str\n        \"\"\"\n        return normalize_array_description(\n            self.uniquely_identifying_objective_c_code.GetObjectDescription()\n        )\n\n    @property\n    def uniquely_identifying_swift_code(self):\n        \"\"\"\n        :return: XCUIElement uniquely identifying Swift code\n        :rtype: lldb.SBValue\n        \"\"\"\n        return fb.evaluateExpressionValue(\n            \"(id)[{} _uniquelyIdentifyingSwiftCode]\".format(self.element_value)\n        )\n\n    @property\n    def uniquely_identifying_swift_code_value(self):\n        \"\"\"\n        :return: XCUIElement uniquely identifying Swift code value\n        :rtype: str\n        \"\"\"\n        return normalize_array_description(\n            self.uniquely_identifying_swift_code.GetObjectDescription()\n        )\n\n    @property\n    def is_touch_bar_element(self):\n        \"\"\"\n        :return: XCUIElement is touch bar element\n        :rtype: lldb.SBValue\n        \"\"\"\n        return fb.evaluateExpressionValue(\n            \"(BOOL)[{} isTouchBarElement]\".format(self.element_value)\n        )\n\n    @property\n    def is_touch_bar_element_value(self):\n        \"\"\"\n        :return: XCUIElement is touch bar element value\n        :rtype: bool\n        \"\"\"\n        return bool(self.is_touch_bar_element.GetValueAsSigned())\n\n    @property\n    def is_top_level_touch_bar_element(self):\n        \"\"\"\n        :return: XCUIElement is top level touch bar element\n        :rtype: lldb.SBValue\n        \"\"\"\n        return fb.evaluateExpressionValue(\n            \"(BOOL)[{} isTopLevelTouchBarElement]\".format(self.element_value)\n        )\n\n    @property\n    def is_top_level_touch_bar_element_value(self):\n        \"\"\"\n        :return: XCUIElement is top level touch bar element value\n        :rtype: bool\n        \"\"\"\n        return bool(self.is_top_level_touch_bar_element.GetValueAsSigned())\n\n    @property\n    def suggested_hit_points(self):\n        \"\"\"\n        :return: XCUIElement suggested hit points\n        :rtype: lldb.SBValue\n        \"\"\"\n        return fb.evaluateExpressionValue(\n            \"(NSArray *)[{} suggestedHitpoints]\".format(self.element_value)\n        )\n\n    @property\n    def suggested_hit_points_value(self):\n        \"\"\"\n        :return: XCUIElement suggested hit points\n        :rtype: str\n        \"\"\"\n        return normalize_array_description(\n            self.suggested_hit_points.GetObjectDescription()\n        )\n\n    @property\n    def visible_frame(self):\n        \"\"\"\n        :return: XCUIElement visible frame\n        :rtype: lldb.SBValue\n        \"\"\"\n        import_uikit()\n        return fb.evaluateExpressionValue(\n            \"(CGRect)[{} visibleFrame]\".format(self.element_value)\n        )\n\n    @property\n    def visible_frame_summary(self):\n        \"\"\"\n        :return: XCUIElement visible frame\n        :rtype: str\n        \"\"\"\n        return CGRect(self.visible_frame).summary()\n\n    @property\n    def depth(self):\n        \"\"\"\n        :return: XCUIElement depth\n        :rtype: lldb.SBValue\n        \"\"\"\n        return fb.evaluateExpressionValue(\"(int)[{} depth]\".format(self.element_value))\n\n    @property\n    def depth_value(self):\n        \"\"\"\n        :return: XCUIElement depth\n        :rtype: int\n        \"\"\"\n        return int(self.depth.GetValue())\n\n    @property\n    def hit_point(self):\n        \"\"\"\n        :return: XCUIElement hit point\n        :rtype: lldb.SBValue\n        \"\"\"\n        import_uikit()\n        return fb.evaluateExpressionValue(\n            \"(CGPoint)[{} hitPoint]\".format(self.element_value)\n        )\n\n    @property\n    def hit_point_value(self):\n        \"\"\"\n        :return: XCUIElement hit point\n        :rtype: str\n        \"\"\"\n        return CGPoint(self.hit_point).summary()\n\n    @property\n    def hit_point_for_scrolling(self):\n        \"\"\"\n        :return: XCUIElement hit point for scrolling\n        :rtype: lldb.SBValue\n        \"\"\"\n        import_uikit()\n        return fb.evaluateExpressionValue(\n            \"(CGPoint)[{} hitPointForScrolling]\".format(self.element_value)\n        )\n\n    @property\n    def hit_point_for_scrolling_value(self):\n        \"\"\"\n        :return: XCUIElement hit point for scrolling\n        :rtype: str\n        \"\"\"\n        return CGPoint(self.hit_point_for_scrolling).summary()\n\n    def summary(self, pointer=False, trait=False, frame=False):\n        \"\"\"\n        Returns XCElementSnapshot summary\n\n        :param bool pointer: Print pointers\n        :param bool trait: Print traits\n        :param bool frame: Print frames\n        :return: XCElementSnapshot summary\n        :rtype: str\n        \"\"\"\n        type_text = self.type_summary\n        if pointer:\n            type_text += \" {:#x}\".format(int(self.element_value, 16))\n        if trait:\n            type_text += \" traits: {}({:#x})\".format(\n                self.traits_summary, self.traits_value\n            )\n\n        frame_text = self.frame_summary if frame else None\n        identifier = self.identifier_summary\n        label = self.label_summary\n        title = self.title_summary\n        value = self.value_summary\n        placeholder = self.placeholder_summary\n        enabled = self.enabled_summary\n        selected = self.selected_summary\n        main_window = self.is_main_window_summary\n        keyboard_focus = self.keyboard_focus_summary\n        focus = self.focus_summary\n\n        texts = [\n            t\n            for t in [\n                frame_text,\n                identifier,\n                label,\n                title,\n                value,\n                placeholder,\n                enabled,\n                selected,\n                main_window,\n                keyboard_focus,\n                focus,\n            ]\n            if t is not None\n        ]\n\n        return \"{}: {}\".format(type_text, \", \".join(texts))\n\n    def detail_summary(self):\n        \"\"\"\n        Returns XCElementSnapshot detail summary\n\n        :return: XCElementSnapshot detail summary\n        :rtype: str\n        \"\"\"\n        texts = list()\n        texts.append(\"Pointer: {:#x}\".format(int(self.element_value, 16)))\n        texts.append(\"Type: {}\".format(self.type_summary))\n        texts.append(\"Depth: {}\".format(self.depth_value))\n        texts.append(\n            \"Traits: {} ({:#x})\".format(self.traits_summary, self.traits_value)\n        )\n        texts.append(\"Frame: {}\".format(self.frame_summary))\n        texts.append(\"Visible frame: {}\".format(self.visible_frame_summary))\n        texts.append(\"Identifier: '{}'\".format(self.identifier_value))\n        texts.append(\"Label: '{}'\".format(self.label_value))\n        texts.append(\"Title: '{}'\".format(self.title_value))\n        texts.append(\"Value: '{}'\".format(self.value_value))\n        texts.append(\"Placeholder: '{}'\".format(self.placeholder_value))\n        if self.language != lldb.eLanguageTypeSwift:\n            # They doesn't work on Swift :(\n            texts.append(\"Hit point: {}\".format(self.hit_point_value))\n            texts.append(\n                \"Hit point for scrolling: {}\".format(self.hit_point_for_scrolling_value)\n            )\n        texts.append(\"Enabled: {}\".format(self.enabled_value))\n        texts.append(\"Selected: {}\".format(self.selected_value))\n        texts.append(\"Main Window: {}\".format(self.is_main_window_value))\n        texts.append(\"Keyboard focus: {}\".format(self.keyboard_focus_value))\n        texts.append(\"Focus: {}\".format(self.focus_value))\n        texts.append(\"Generation: {}\".format(self.generation_value))\n        texts.append(\n            \"Horizontal size class: {}\".format(self.horizontal_size_class_summary)\n        )\n        texts.append(\"Vertical size class: {}\".format(self.vertical_size_class_summary))\n        texts.append(\"TouchBar element: {}\".format(self.is_touch_bar_element_value))\n        texts.append(\n            \"TouchBar top level element: {}\".format(\n                self.is_top_level_touch_bar_element_value\n            )\n        )\n        texts.append(\n            \"Unique Objective-C: {}\".format(\n                self.uniquely_identifying_objective_c_code_value\n            )\n        )\n        texts.append(\n            \"Unique Swift: {}\".format(self.uniquely_identifying_swift_code_value)\n        )\n        texts.append(\"Suggested hit points: {}\".format(self.suggested_hit_points_value))\n        return \"\\n\".join(texts)\n\n    def tree(self):\n        \"\"\"\n        Returns tree of elements in hierarchy\n\n        :return: Elements hierarchy\n        :rtype: _ElementList\n        \"\"\"\n        children = [\n            XCElementSnapshot(e, self.language).tree() for e in self.children_list\n        ]\n        return _ElementList(self, children)\n\n    def find_missing_identifiers(self, status_bar):\n        \"\"\"\n        Find element which has a label but doesn't have an identifier\n\n        :param bool status_bar: Print status bar items\n        :return: Hierarchy structure with items which has a label but doesn't have an identifier\n        :rtype: _ElementList | None\n        \"\"\"\n        # Do not print status bar items\n        if status_bar is not True and self.type_value == XCUIElementType.StatusBar:\n            return None\n\n        children_missing = [\n            XCElementSnapshot(e, self.language).find_missing_identifiers(\n                status_bar=status_bar\n            )\n            for e in self.children_list\n        ]\n        children_missing = [x for x in children_missing if x is not None]\n\n        # Self and its children are not missing identifiers\n        if self.is_missing_identifier is False and len(children_missing) == 0:\n            return None\n\n        return _ElementList(self, children_missing)\n\n    @staticmethod\n    def get_type_value_string(value):\n        \"\"\"\n        Get element type string from XCUIElementType (as int)\n\n        :param int value: XCUIElementType (as int)\n        :return: XCUIElementType string\n        :rtype: str\n        \"\"\"\n        return XCUIElementType.name_for_value(value)\n\n    @staticmethod\n    def get_traits_value_string(value):\n        \"\"\"\n        Get element traits string from UIAccessibilityTraits (as int)\n\n        :param int value: UIAccessibilityTraits (as int)\n        :return: UIAccessibilityTraits string\n        :rtype: str\n        \"\"\"\n        return UIAccessibilityTraits.name_for_value(value)\n\n    @staticmethod\n    def get_user_interface_size_class_string(value):\n        \"\"\"\n        Get user interface size class string from UIUserInterfaceSizeClass (as int)\n\n        :param value: UIAccessibilityTraits (as int)\n        :return: UIUserInterfaceSizeClass string\n        :rtype: str\n        \"\"\"\n        return UIUserInterfaceSizeClass.name_for_value(value)\n\n\nclass XCUIElementType(object):\n    \"\"\"\n    Represents all XCUIElementType types\n    \"\"\"\n\n    Any = 0\n    Other = 1\n    Application = 2\n    Group = 3\n    Window = 4\n    Sheet = 5\n    Drawer = 6\n    Alert = 7\n    Dialog = 8\n    Button = 9\n    RadioButton = 10\n    RadioGroup = 11\n    CheckBox = 12\n    DisclosureTriangle = 13\n    PopUpButton = 14\n    ComboBox = 15\n    MenuButton = 16\n    ToolbarButton = 17\n    Popover = 18\n    Keyboard = 19\n    Key = 20\n    NavigationBar = 21\n    TabBar = 22\n    TabGroup = 23\n    Toolbar = 24\n    StatusBar = 25\n    Table = 26\n    TableRow = 27\n    TableColumn = 28\n    Outline = 29\n    OutlineRow = 30\n    Browser = 31\n    CollectionView = 32\n    Slider = 33\n    PageIndicator = 34\n    ProgressIndicator = 35\n    ActivityIndicator = 36\n    SegmentedControl = 37\n    Picker = 38\n    PickerWheel = 39\n    Switch = 40\n    Toggle = 41\n    Link = 42\n    Image = 43\n    Icon = 44\n    SearchField = 45\n    ScrollView = 46\n    ScrollBar = 47\n    StaticText = 48\n    TextField = 49\n    SecureTextField = 50\n    DatePicker = 51\n    TextView = 52\n    Menu = 53\n    MenuItem = 54\n    MenuBar = 55\n    MenuBarItem = 56\n    Map = 57\n    WebView = 58\n    IncrementArrow = 59\n    DecrementArrow = 60\n    Timeline = 61\n    RatingIndicator = 62\n    ValueIndicator = 63\n    SplitGroup = 64\n    Splitter = 65\n    RelevanceIndicator = 66\n    ColorWell = 67\n    HelpTag = 68\n    Matte = 69\n    DockItem = 70\n    Ruler = 71\n    RulerMarker = 72\n    Grid = 73\n    LevelIndicator = 74\n    Cell = 75\n    LayoutArea = 76\n    LayoutItem = 77\n    Handle = 78\n    Stepper = 79\n    Tab = 80\n    TouchBar = 81\n\n    @classmethod\n    def _attributes_by_value(cls):\n        \"\"\"\n        :return: Hash of all attributes and their values\n        :rtype: dict[int, str]\n        \"\"\"\n        class_attributes = set(dir(cls)) - set(dir(object))\n        return dict(\n            [\n                (getattr(cls, n), n)\n                for n in class_attributes\n                if not callable(getattr(cls, n)) and not n.startswith(\"__\")\n            ]\n        )\n\n    @classmethod\n    def name_for_value(cls, value):\n        \"\"\"\n        Get element type string from XCUIElementType (as int)\n\n        :param int value: XCUIElementType (as int)\n        :return: Name of type\n        :rtype: str\n        \"\"\"\n        attributes = cls._attributes_by_value()\n        if value in attributes:\n            return attributes[value]\n        else:\n            return \"Unknown ({:#x})\".format(value)\n\n\nclass UIAccessibilityTraits(object):\n    \"\"\"\n    Represents all UIAccessibilityTraits types\n    \"\"\"\n\n    Button = 0x0000000000000001\n    Link = 0x0000000000000002\n    Image = 0x0000000000000004\n    Selected = 0x0000000000000008\n    PlaysSound = 0x0000000000000010\n    KeyboardKey = 0x0000000000000020\n    StaticText = 0x0000000000000040\n    SummaryElement = 0x0000000000000080\n    NotEnabled = 0x0000000000000100\n    UpdatesFrequently = 0x0000000000000200\n    SearchField = 0x0000000000000400\n    StartsMediaSession = 0x0000000000000800\n    Adjustable = 0x0000000000001000\n    AllowsDirectInteraction = 0x0000000000002000\n    CausesPageTurn = 0x0000000000004000\n    TabBar = 0x0000000000008000\n    Header = 0x0000000000010000\n\n    @classmethod\n    def _attributes_by_value(cls):\n        \"\"\"\n        :return: Hash of all attributes and their values\n        :rtype: dict[int, str]\n        \"\"\"\n        class_attributes = set(dir(cls)) - set(dir(object))\n        return dict(\n            [\n                (getattr(cls, n), n)\n                for n in class_attributes\n                if not callable(getattr(cls, n)) and not n.startswith(\"__\")\n            ]\n        )\n\n    @classmethod\n    def name_for_value(cls, value):\n        \"\"\"\n        Get element traits string from UIAccessibilityTraits (as int)\n\n        :param int value: UIAccessibilityTraits (as int)\n        :return: UIAccessibilityTraits string\n        :rtype: str\n        \"\"\"\n        if value == 0:\n            return \"None\"\n\n        traits = []\n        attributes = cls._attributes_by_value()\n        for k in attributes.keys():\n            if value & k:\n                traits.append(attributes[k])\n\n        if len(traits) == 0:\n            return \"Unknown\"\n        else:\n            return \", \".join(traits)\n\n\nclass UIUserInterfaceSizeClass(object):\n    \"\"\"\n    Represents all UIUserInterfaceSizeClass types\n    \"\"\"\n\n    Unspecified = 0\n    Compact = 1\n    Regular = 2\n\n    @classmethod\n    def name_for_value(cls, value):\n        \"\"\"\n        Get user interface size class string from UIUserInterfaceSizeClass (as int)\n\n        :param int value: UIAccessibilityTraits (as int)\n        :return: UIUserInterfaceSizeClass string\n        :rtype: str\n        \"\"\"\n        if value == cls.Unspecified:\n            return \"Unspecified\"\n        elif value == cls.Compact:\n            return \"Compact\"\n        elif value == cls.Regular:\n            return \"Regular\"\n        else:\n            return \"Unknown ({:#x})\".format(value)\n\n\nclass CGRect(object):\n    \"\"\"\n    CGRect wrapper\n\n    :param lldb.SBValue element: CGRect object\n    \"\"\"\n\n    def __init__(self, element):\n        \"\"\"\n        :param lldb.SBValue element: CGRect object\n        \"\"\"\n        super(CGRect, self).__init__()\n\n        self.element = element\n\n    def summary(self):\n        \"\"\"\n        :return: CGRect summary\n        :rtype: str\n        \"\"\"\n        origin_element = self.element.GetChildMemberWithName(\"origin\")\n        origin = CGPoint(origin_element)\n\n        size = self.element.GetChildMemberWithName(\"size\")\n        width = size.GetChildMemberWithName(\"width\")\n        height = size.GetChildMemberWithName(\"height\")\n\n        width_value = float(width.GetValue())\n        height_value = float(height.GetValue())\n        return \"{{{}, {{{}, {}}}}}\".format(origin.summary(), width_value, height_value)\n\n\nclass CGPoint(object):\n    \"\"\"\n    CGPoint wrapper\n\n    :param lldb.SBValue element: CGPoint object\n    \"\"\"\n\n    def __init__(self, element):\n        super(CGPoint, self).__init__()\n\n        self.element = element\n\n    def summary(self):\n        \"\"\"\n        :return: CGPoint summary\n        :rtype: str\n        \"\"\"\n        x = self.element.GetChildMemberWithName(\"x\")\n        y = self.element.GetChildMemberWithName(\"y\")\n\n        x_value = float(x.GetValue())\n        y_value = float(y.GetValue())\n        return \"{{{}, {}}}\".format(x_value, y_value)\n\n\ndef normalize_summary(summary):\n    \"\"\"\n    Normalize summary by removing \"'\" and \"@\" characters\n\n    :param str summary: Summary string to normalize\n    :return: Normalized summary string\n    :rtype: str\n    \"\"\"\n    return summary.lstrip(\"@\").strip('\"')\n\n\ndef normalize_array_description(description):\n    \"\"\"\n    Normalize array object description by removing \"<\" and \">\" characters and content between them.\n\n    :param str description: Array object description\n    :return: Normalized array object description string\n    :rtype: str\n    \"\"\"\n    return re.sub(\"^(<.*>)\", \"\", description).strip()\n\n\n_uikit_imported = False\n\n\ndef import_uikit():\n    \"\"\"\n    Import UIKit framework to the debugger\n    \"\"\"\n    global _uikit_imported\n    if _uikit_imported:\n        return\n    _uikit_imported = True\n    fb.evaluateExpressionValue(\"@import UIKit\")\n\n\ndef debug(element):\n    \"\"\"\n    Debug helper\n\n    :param lldb.SBValue element: Element to debug\n    \"\"\"\n    print(\"---\")\n    print(\"element: {}\".format(element))\n    print(\"element class: {}\".format(element.__class__))\n    print(\"element name: {}\".format(element.GetName()))\n    print(\"element type name: {}\".format(element.GetTypeName()))\n    print(\"element value: {}\".format(element.GetValue()))\n    print(\"element value class: {}\".format(element.GetValue().__class__))\n    print(\"element value type: {}\".format(element.GetValueType()))\n    print(\"element value signed: {0}({0:#x})\".format(element.GetValueAsSigned()))\n    print(\"element value unsigned: {0}({0:#x})\".format(element.GetValueAsUnsigned()))\n    print(\"element summary: {}\".format(element.GetSummary()))\n    print(\"element description: {}\".format(element.GetObjectDescription()))\n    print(\"element children num: {}\".format(element.GetNumChildren()))\n    for i in range(0, element.GetNumChildren()):\n        child = element.GetChildAtIndex(i)\n        \"\"\":type: lldb.SBValue\"\"\"\n        print(\"element child {:02}: {}\".format(i, child.GetName()))\n    print(\"===\")\n"
  },
  {
    "path": "fbchisellldb.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport imp\nimport os\nfrom contextlib import redirect_stderr, redirect_stdout\nfrom optparse import OptionParser\n\nimport lldb\n\n\ndef __lldb_init_module(debugger, dict):\n    filePath = os.path.realpath(__file__)\n    lldbHelperDir = os.path.dirname(filePath)\n\n    commandsDirectory = os.path.join(lldbHelperDir, \"commands\")\n    loadCommandsInDirectory(commandsDirectory)\n\n\ndef loadCommandsInDirectory(commandsDirectory):\n    for file in os.listdir(commandsDirectory):\n        fileName, fileExtension = os.path.splitext(file)\n        if fileExtension == \".py\":\n            module = imp.load_source(fileName, os.path.join(commandsDirectory, file))\n\n            if hasattr(module, \"lldbinit\"):\n                module.lldbinit()\n\n            if hasattr(module, \"lldbcommands\"):\n                module._loadedFunctions = {}\n                for command in module.lldbcommands():\n                    loadCommand(\n                        module, command, commandsDirectory, fileName, fileExtension\n                    )\n\n\ndef loadCommand(module, command, directory, filename, extension):\n    func = makeRunCommand(command, os.path.join(directory, filename + extension))\n    name = command.name()\n    helpText = (\n        command.description().strip().splitlines()[0]\n    )  # first line of description\n\n    key = filename + \"_\" + name\n\n    module._loadedFunctions[key] = func\n\n    functionName = \"__\" + key\n\n    lldb.debugger.HandleCommand(\n        \"script \"\n        + functionName\n        + \" = sys.modules['\"\n        + module.__name__\n        + \"']._loadedFunctions['\"\n        + key\n        + \"']\"\n    )\n    lldb.debugger.HandleCommand(\n        'command script add --help \"{help}\" --function {function} {name}'.format(\n            help=helpText.replace('\"', '\\\\\"'),  # escape quotes\n            function=functionName,\n            name=name,\n        )\n    )\n\n\ndef makeRunCommand(command, filename):\n    def runCommand(debugger, input, exe_ctx, result, _):\n        # lldb assumes that any output meant for the user is written\n        # to the result object. By redirecting stdout here, we can\n        # use methods like print (or parse_args) in the command logic\n        # as if they are writing to stdout, but write to result\n        # instead. lldb will handle displaying it to the user.\n        with redirect_stdout(result), redirect_stderr(result):\n            command.result = result\n            command.context = exe_ctx\n            splitInput = command.lex(input)\n\n            # OptionParser will throw in the case where you want just one\n            # big long argument and no options and you enter something\n            # that starts with '-' in the argument. e.g.:\n            #     somecommand -[SomeClass someSelector:]\n            # This solves that problem by prepending a '--' so that\n            # OptionParser does the right thing.\n            options = command.options()\n            if len(options) == 0:\n                if \"--\" not in splitInput:\n                    splitInput.insert(0, \"--\")\n\n            parser = optionParserForCommand(command)\n            (options, args) = parser.parse_args(splitInput)\n\n            # When there are more args than the command has declared, assume\n            # the initial args form an expression and combine them into a single arg.\n            if len(args) > len(command.args()):\n                overhead = len(args) - len(command.args())\n                head = args[: overhead + 1]  # Take N+1 and reduce to 1.\n                args = [\" \".join(head)] + args[-overhead:]\n\n            if validateArgsForCommand(args, command):\n                command.run(args, options)\n\n    runCommand.__doc__ = helpForCommand(command, filename)\n    return runCommand\n\n\ndef validateArgsForCommand(args, command):\n    if len(args) < len(command.args()):\n        defaultArgs = [arg.default for arg in command.args()]\n        defaultArgsToAppend = defaultArgs[len(args) :]\n\n        index = len(args)\n        for defaultArg in defaultArgsToAppend:\n            if not defaultArg:\n                arg = command.args()[index]\n                print(\"Whoops! You are missing the <\" + arg.argName + \"> argument.\")\n                print(\"\\nUsage: \" + usageForCommand(command))\n                return\n            index += 1\n\n        args.extend(defaultArgsToAppend)\n    return True\n\n\ndef optionParserForCommand(command):\n    parser = OptionParser()\n\n    for argument in command.options():\n        if argument.boolean:\n            parser.add_option(\n                argument.shortName,\n                argument.longName,\n                dest=argument.argName,\n                help=argument.help,\n                action=(\"store_false\" if argument.default else \"store_true\"),\n            )\n        else:\n            parser.add_option(\n                argument.shortName,\n                argument.longName,\n                dest=argument.argName,\n                help=argument.help,\n                default=argument.default,\n            )\n\n    return parser\n\n\ndef helpForCommand(command, filename):\n    help = command.description()\n\n    argSyntax = \"\"\n    optionSyntax = \"\"\n\n    if command.args():\n        help += \"\\n\\nArguments:\"\n        for arg in command.args():\n            help += \"\\n  <\" + arg.argName + \">; \"\n            if arg.argType:\n                help += \"Type: \" + arg.argType + \"; \"\n            help += arg.help\n            argSyntax += \" <\" + arg.argName + \">\"\n\n    if command.options():\n        help += \"\\n\\nOptions:\"\n        for option in command.options():\n            if option.longName and option.shortName:\n                optionFlag = option.longName + \"/\" + option.shortName\n            elif option.longName:\n                optionFlag = option.longName\n            else:\n                optionFlag = option.shortName\n\n            help += \"\\n  \" + optionFlag + \" \"\n\n            if not option.boolean:\n                help += \"<\" + option.argName + \">; Type: \" + option.argType\n\n            help += \"; \" + option.help\n\n            optionSyntax += \" [{name}{arg}]\".format(\n                name=(option.longName or option.shortName),\n                arg=(\"\" if option.boolean else (\"=\" + option.argName)),\n            )\n\n    help += \"\\n\\nSyntax: \" + command.name() + optionSyntax + argSyntax\n\n    help += \"\\n\\nThis command is implemented as %s in %s.\" % (\n        command.__class__.__name__,\n        filename,\n    )\n\n    return help\n\n\ndef usageForCommand(command):\n    usage = command.name()\n    for arg in command.args():\n        if arg.default:\n            usage += \" [\" + arg.argName + \"]\"\n        else:\n            usage += \" \" + arg.argName\n\n    return usage\n"
  },
  {
    "path": "fbchisellldbbase.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport json\nimport shlex\n\nimport lldb\n\n\nclass FBCommandArgument:  # noqa B903\n    def __init__(\n        self, short=\"\", long=\"\", arg=\"\", type=\"\", help=\"\", default=\"\", boolean=False\n    ):\n        self.shortName = short\n        self.longName = long\n        self.argName = arg\n        self.argType = type\n        self.help = help\n        self.default = default\n        self.boolean = boolean\n\n\nclass FBCommand:\n    def name(self):\n        return None\n\n    def options(self):\n        return []\n\n    def args(self):\n        return []\n\n    def description(self):\n        return \"\"\n\n    def lex(self, commandLine):\n        return shlex.split(commandLine)\n\n    def run(self, arguments, option):\n        pass\n\n\ndef isSuccess(error):\n    # When evaluating a `void` expression, the returned value will indicate an\n    # error. This error is named: kNoResult. This error value does *not* mean\n    # there was a problem. This logic follows what the builtin `expression`\n    # command does. See: https://git.io/vwpjl (UserExpression.h)\n    kNoResult = 0x1001\n    return error.success or error.value == kNoResult\n\n\ndef importModule(frame, module):\n    options = lldb.SBExpressionOptions()\n    options.SetLanguage(lldb.eLanguageTypeObjC)\n    value = frame.EvaluateExpression(\"@import \" + module, options)\n    return isSuccess(value.error)\n\n\n# evaluates expression in Objective-C++ context, so it will work even for\n# Swift projects\ndef evaluateExpressionValue(\n    expression,\n    printErrors=True,\n    language=lldb.eLanguageTypeObjC_plus_plus,\n    tryAllThreads=False,\n):\n    frame = (\n        lldb.debugger.GetSelectedTarget()\n        .GetProcess()\n        .GetSelectedThread()\n        .GetSelectedFrame()\n    )\n    options = lldb.SBExpressionOptions()\n    options.SetLanguage(language)\n\n    # Allow evaluation that contains a @throw/@catch.\n    #   By default, ObjC @throw will cause evaluation to be aborted. At the time\n    #   of a @throw, it's not known if the exception will be handled by a @catch.\n    #   An exception that's caught, should not cause evaluation to fail.\n    options.SetTrapExceptions(False)\n\n    # Give evaluation more time.\n    options.SetTimeoutInMicroSeconds(5000000)  # 5s\n\n    # Most Chisel commands are not multithreaded.\n    options.SetTryAllThreads(tryAllThreads)\n\n    value = frame.EvaluateExpression(expression, options)\n    error = value.GetError()\n\n    # Retry if the error could be resolved by first importing UIKit.\n    if (\n        error.type == lldb.eErrorTypeExpression\n        and error.value == lldb.eExpressionParseError\n        and importModule(frame, \"UIKit\")\n    ):\n        value = frame.EvaluateExpression(expression, options)\n        error = value.GetError()\n\n    if printErrors and not isSuccess(error):\n        print(error)\n\n    return value\n\n\ndef evaluateInputExpression(expression, printErrors=True):\n    # HACK\n    if expression.startswith(\"(id)\"):\n        return evaluateExpressionValue(expression, printErrors=printErrors).GetValue()\n\n    frame = (\n        lldb.debugger.GetSelectedTarget()\n        .GetProcess()\n        .GetSelectedThread()\n        .GetSelectedFrame()\n    )\n    options = lldb.SBExpressionOptions()\n    options.SetTrapExceptions(False)\n    value = frame.EvaluateExpression(expression, options)\n    error = value.GetError()\n\n    if printErrors and error.Fail():\n        print(error)\n\n    return value.GetValue()\n\n\ndef evaluateIntegerExpression(expression, printErrors=True):\n    output = evaluateExpression(\"(int)(\" + expression + \")\", printErrors).replace(\n        \"'\", \"\"\n    )\n    if output.startswith(\"\\\\x\"):  # Booleans may display as \\x01 (Hex)\n        output = output[2:]\n    elif output.startswith(\"\\\\\"):  # Or as \\0 (Dec)\n        output = output[1:]\n    return int(output, 0)\n\n\ndef evaluateBooleanExpression(expression, printErrors=True):\n    return (\n        int(evaluateIntegerExpression(\"(BOOL)(\" + expression + \")\", printErrors)) != 0\n    )\n\n\ndef evaluateExpression(expression, printErrors=True):\n    return evaluateExpressionValue(expression, printErrors=printErrors).GetValue()\n\n\ndef describeObject(expression, printErrors=True):\n    return evaluateExpressionValue(\n        \"(id)(\" + expression + \")\", printErrors\n    ).GetObjectDescription()\n\n\ndef evaluateEffect(expression, printErrors=True):\n    evaluateExpressionValue(\"(void)(\" + expression + \")\", printErrors=printErrors)\n\n\ndef evaluateObjectExpression(expression, printErrors=True):\n    return evaluateExpression(\"(id)(\" + expression + \")\", printErrors)\n\n\ndef evaluateCStringExpression(expression, printErrors=True):\n    ret = evaluateExpression(expression, printErrors)\n\n    process = lldb.debugger.GetSelectedTarget().GetProcess()\n    error = lldb.SBError()\n    ret = process.ReadCStringFromMemory(int(ret, 16), 256, error)\n    if error.Success():\n        return ret\n    else:\n        if printErrors:\n            print(error)\n        return None\n\n\nRETURN_MACRO = \"\"\"\n#define IS_JSON_OBJ(obj)\\\n    (obj != nil && ((bool)[NSJSONSerialization isValidJSONObject:obj] ||\\\n    (bool)[obj isKindOfClass:[NSString class]] ||\\\n    (bool)[obj isKindOfClass:[NSNumber class]]))\n#define RETURN(ret) ({\\\n    if (!IS_JSON_OBJ(ret)) {\\\n        (void)[NSException raise:@\"Invalid RETURN argument\" format:@\"\"];\\\n    }\\\n    NSDictionary *__dict = @{@\"return\":ret};\\\n    NSData *__data = (id)[NSJSONSerialization dataWithJSONObject:__dict options:0 error:NULL];\\\n    NSString *__str = (id)[[NSString alloc] initWithData:__data encoding:4];\\\n    (char *)[__str UTF8String];})\n#define RETURNCString(ret)\\\n    ({NSString *___cstring_ret = [NSString stringWithUTF8String:ret];\\\n    RETURN(___cstring_ret);})\n\"\"\"\n\n\ndef check_expr(expr):\n    return expr.strip().split(\";\")[-2].find(\"RETURN\") != -1\n\n\n# evaluate a batch of Objective-C expressions, the last expression\n# must contain a RETURN marco and it will automatic transform the\n# Objective-C object to Python object\n# Example:\n#       >>> fbchisellldbbase.evaluate('NSString *str = @\"hello world\"; RETURN(@{@\"key\": str});')\n#       {u'key': u'hello world'}\ndef evaluate(expr):\n    if not check_expr(expr):\n        raise Exception(\n            \"Invalid Expression, the last expression not include a RETURN family marco\"\n        )\n\n    command = \"({\" + RETURN_MACRO + \"\\n\" + expr + \"})\"\n    ret = evaluateExpressionValue(command, printErrors=True)\n    if not ret.GetError().Success():\n        print(ret.GetError())\n        return None\n    else:\n        process = lldb.debugger.GetSelectedTarget().GetProcess()\n        error = lldb.SBError()\n        ret = process.ReadCStringFromMemory(int(ret.GetValue(), 16), 2**20, error)\n        if not error.Success():\n            print(error)\n            return None\n        else:\n            ret = json.loads(ret)\n            return ret[\"return\"]\n\n\ndef currentLanguage():\n    return (\n        lldb.debugger.GetSelectedTarget()\n        .GetProcess()\n        .GetSelectedThread()\n        .GetSelectedFrame()\n        .GetCompileUnit()\n        .GetLanguage()\n    )\n"
  },
  {
    "path": "fbchisellldbinputhelpers.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport lldb\n\n\nclass FBInputHandler:\n    def __init__(self, debugger, callback):\n        self.debugger = debugger\n        self.callback = callback\n        self.inputReader = lldb.SBInputReader()\n        self.inputReader.Initialize(\n            debugger,\n            self.handleInput,\n            lldb.eInputReaderGranularityLine,\n            None,\n            None,  # prompt\n            True,  # echo\n        )\n\n    def isValid(self):\n        return not self.inputReader.IsDone()\n\n    def start(self):\n        self.debugger.PushInputReader(self.inputReader)\n\n    def stop(self):\n        self.inputReader.SetIsDone(True)\n\n    def handleInput(self, inputReader, notification, bytes):\n        if notification == lldb.eInputReaderGotToken:\n            self.callback(bytes)\n        elif notification == lldb.eInputReaderInterrupt:\n            self.stop()\n\n        return len(bytes)\n"
  },
  {
    "path": "fbchisellldbobjcruntimehelpers.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport re\n\nimport fbchisellldbbase as fb\nimport lldb\n\n\ndef objc_getClass(className):\n    command = '(void*)objc_getClass(\"{}\")'.format(className)\n    value = fb.evaluateExpression(command)\n    return value\n\n\ndef object_getClass(object):\n    command = \"(void*)object_getClass((id){})\".format(object)\n    value = fb.evaluateExpression(command)\n    return value\n\n\ndef class_getName(klass):\n    command = \"(const char*)class_getName((Class){})\".format(klass)\n    value = fb.evaluateExpressionValue(command).GetSummary().strip('\"')\n    return value\n\n\ndef class_getSuperclass(klass):\n    command = \"(void*)class_getSuperclass((Class){})\".format(klass)\n    value = fb.evaluateExpression(command)\n    return value\n\n\ndef class_isMetaClass(klass):\n    command = \"class_isMetaClass((Class){})\".format(klass)\n    return fb.evaluateBooleanExpression(command)\n\n\ndef class_getInstanceMethod(klass, selector):\n    command = \"(void*)class_getInstanceMethod((Class){}, @selector({}))\".format(\n        klass, selector\n    )\n    value = fb.evaluateExpression(command)\n    return value\n\n\ndef currentArch():\n    targetTriple = lldb.debugger.GetSelectedTarget().GetTriple()\n    arch = targetTriple.split(\"-\")[0]\n    if arch == \"x86_64h\":\n        arch = \"x86_64\"\n    return arch\n\n\ndef functionPreambleExpressionForSelf():\n    import re\n\n    arch = currentArch()\n    expressionForSelf = None\n    if arch == \"i386\":\n        expressionForSelf = \"*(id*)($esp+4)\"\n    elif arch == \"x86_64\":\n        expressionForSelf = \"(id)$rdi\"\n    elif arch == \"arm64\":\n        expressionForSelf = \"(id)$x0\"\n    elif re.match(r\"^armv.*$\", arch):\n        expressionForSelf = \"(id)$r0\"\n    return expressionForSelf\n\n\ndef functionPreambleExpressionForObjectParameterAtIndex(parameterIndex):\n    arch = currentArch()\n    expresssion = None\n    if arch == \"i386\":\n        expresssion = \"*(id*)($esp + \" + str(12 + parameterIndex * 4) + \")\"\n    elif arch == \"x86_64\":\n        if parameterIndex > 3:\n            raise Exception(\n                \"Current implementation can not return object at index greater than 3 for x86_64\"\n            )\n        registersList = [\"rdx\", \"rcx\", \"r8\", \"r9\"]\n        expresssion = \"(id)$\" + registersList[parameterIndex]\n    elif arch == \"arm64\":\n        if parameterIndex > 5:\n            raise Exception(\n                \"Current implementation can not return object at index greater than 5 for arm64\"\n            )\n        expresssion = \"(id)$x\" + str(parameterIndex + 2)\n    elif re.match(r\"^armv.*$\", arch):\n        if parameterIndex > 1:\n            raise Exception(\n                \"Current implementation can not return object at index greater than 1 for arm32\"\n            )\n        expresssion = \"(id)$r\" + str(parameterIndex + 2)\n    return expresssion\n\n\ndef isMacintoshArch():\n    arch = currentArch()\n    if not arch == \"x86_64\":\n        return False\n\n    nsClassName = \"NSApplication\"\n    command = '(void*)objc_getClass(\"{}\")'.format(nsClassName)\n\n    return fb.evaluateBooleanExpression(command + \"!= nil\")\n\n\ndef isIOSSimulator():\n    return (\n        fb.evaluateExpressionValue(\"(id)[[UIDevice currentDevice] model]\")\n        .GetObjectDescription()\n        .lower()\n        .find(\"simulator\")\n        >= 0\n    )\n\n\ndef isIOSDevice():\n    return not isMacintoshArch() and not isIOSSimulator()\n"
  },
  {
    "path": "fbchisellldbobjecthelpers.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport fbchisellldbbase as fb\n\n\ndef isKindOfClass(obj, className):\n    isKindOfClassStr = \"[(id)\" + obj + \" isKindOfClass:[{} class]]\"\n    return fb.evaluateBooleanExpression(isKindOfClassStr.format(className))\n\n\ndef className(obj):\n    return fb.evaluateExpressionValue(\n        \"(id)[(\" + obj + \") class]\"\n    ).GetObjectDescription()\n"
  },
  {
    "path": "fbchisellldbviewcontrollerhelpers.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport fbchisellldbbase as fb\nimport fbchisellldbobjcruntimehelpers as runtimeHelpers\n\n\ndef presentViewController(viewController):\n    vc = \"(%s)\" % (viewController)\n\n    if fb.evaluateBooleanExpression(\n        \"%s != nil && ((BOOL)[(id)%s isKindOfClass:(Class)[UIViewController class]])\"\n        % (vc, vc)\n    ):\n        notPresented = fb.evaluateBooleanExpression(\n            \"[%s presentingViewController] == nil\" % vc\n        )\n\n        if notPresented:\n            fb.evaluateEffect(\n                \"[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:%s animated:YES completion:nil]\"\n                % vc\n            )\n        else:\n            raise Exception(\"Argument is already presented\")\n    else:\n        raise Exception(\"Argument must be a UIViewController\")\n\n\ndef dismissViewController(viewController):\n    vc = \"(%s)\" % (viewController)\n\n    if fb.evaluateBooleanExpression(\n        \"%s != nil && ((BOOL)[(id)%s isKindOfClass:(Class)[UIViewController class]])\"\n        % (vc, vc)\n    ):\n        isPresented = fb.evaluateBooleanExpression(\n            \"[%s presentingViewController] != nil\" % vc\n        )\n\n        if isPresented:\n            fb.evaluateEffect(\n                \"[(UIViewController *)%s dismissViewControllerAnimated:YES completion:nil]\"\n                % vc\n            )\n        else:\n            raise Exception(\"Argument must be presented\")\n    else:\n        raise Exception(\"Argument must be a UIViewController\")\n\n\ndef viewControllerRecursiveDescription(vc):\n    return _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(\n        fb.evaluateObjectExpression(vc), \"\", \"\", \"\"\n    )\n\n\ndef _viewControllerDescription(viewController):\n    vc = \"(%s)\" % (viewController)\n\n    if fb.evaluateBooleanExpression(\"[(id)%s isViewLoaded]\" % (vc)):\n        result = fb.evaluateExpressionValue(\n            '(id)[[NSString alloc] initWithFormat:@\"<%%@: %%p; view = <%%@; %%p>; frame = (%%g, %%g; %%g, %%g)>\", (id)NSStringFromClass((id)[(id)%s class]), %s, (id)[(id)[(id)%s view] class], (id)[(id)%s view], ((CGRect)[(id)[(id)%s view] frame]).origin.x, ((CGRect)[(id)[(id)%s view] frame]).origin.y, ((CGRect)[(id)[(id)%s view] frame]).size.width, ((CGRect)[(id)[(id)%s view] frame]).size.height]'\n            % (vc, vc, vc, vc, vc, vc, vc, vc)\n        )\n    else:\n        result = fb.evaluateExpressionValue(\n            '(id)[[NSString alloc] initWithFormat:@\"<%%@: %%p; view not loaded>\", (id)NSStringFromClass((id)[(id)%s class]), %s]'\n            % (vc, vc)\n        )\n\n    if result.GetError() is not None and str(result.GetError()) != \"success\":\n        return \"[Error getting description.]\"\n    else:\n        return result.GetObjectDescription()\n\n\ndef _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(\n    vc, string, prefix, childPrefix\n):\n    isMac = runtimeHelpers.isMacintoshArch()\n\n    s = \"%s%s%s\\n\" % (\n        prefix,\n        \"\" if prefix == \"\" else \" \",\n        _viewControllerDescription(vc),\n    )\n\n    nextPrefix = childPrefix + \"   |\"\n\n    numChildViewControllers = fb.evaluateIntegerExpression(\n        \"(int)[(id)[%s childViewControllers] count]\" % (vc)\n    )\n\n    for i in range(0, numChildViewControllers):\n        viewController = fb.evaluateExpression(\n            \"(id)[(id)[%s childViewControllers] objectAtIndex:%d]\" % (vc, i)\n        )\n        s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(\n            viewController, string, nextPrefix, nextPrefix\n        )\n\n    if not isMac:\n        isModal = fb.evaluateBooleanExpression(\n            \"%s != nil && ((id)[(id)[(id)%s presentedViewController] presentingViewController]) == %s\"\n            % (vc, vc, vc)\n        )\n\n        if isModal:\n            modalVC = fb.evaluateObjectExpression(\n                \"(id)[(id)%s presentedViewController]\" % (vc)\n            )\n            s += _recursiveViewControllerDescriptionWithPrefixAndChildPrefix(\n                modalVC, string, childPrefix + \"  *M\", nextPrefix\n            )\n            s += \"\\n// '*M' means the view controller is presented modally.\"\n\n    return string + s\n"
  },
  {
    "path": "fbchisellldbviewhelpers.py",
    "content": "#!/usr/bin/python\n\n# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport fbchisellldbbase as fb\nimport fbchisellldbobjcruntimehelpers as runtimeHelpers\n\n\ndef flushCoreAnimationTransaction():\n    fb.evaluateEffect(\"[CATransaction flush]\")\n\n\ndef setViewHidden(object, hidden):\n    fb.evaluateEffect(\"[{} setHidden:{}]\".format(object, int(hidden)))\n    flushCoreAnimationTransaction()\n\n\ndef maskView(viewOrLayer, color, alpha):\n    unmaskView(viewOrLayer)\n    window = fb.evaluateExpression(\n        \"(UIWindow *)[[UIApplication sharedApplication] keyWindow]\"\n    )\n    origin = convertPoint(0, 0, viewOrLayer, window)\n    size = fb.evaluateExpressionValue(\n        \"(CGSize)((CGRect)[(id)%s frame]).size\" % viewOrLayer\n    )\n\n    rectExpr = \"(CGRect){{%s, %s}, {%s, %s}}\" % (\n        origin.GetChildMemberWithName(\"x\").GetValue(),\n        origin.GetChildMemberWithName(\"y\").GetValue(),\n        size.GetChildMemberWithName(\"width\").GetValue(),\n        size.GetChildMemberWithName(\"height\").GetValue(),\n    )\n    mask = fb.evaluateExpression(\"(id)[[UIView alloc] initWithFrame:%s]\" % rectExpr)\n\n    fb.evaluateEffect(\"[%s setTag:(NSInteger)%s]\" % (mask, viewOrLayer))\n    fb.evaluateEffect(\"[%s setBackgroundColor:[UIColor %sColor]]\" % (mask, color))\n    fb.evaluateEffect(\"[%s setAlpha:(CGFloat)%s]\" % (mask, alpha))\n    fb.evaluateEffect(\"[%s addSubview:%s]\" % (window, mask))\n    flushCoreAnimationTransaction()\n\n\ndef unmaskView(viewOrLayer):\n    window = fb.evaluateExpression(\n        \"(UIWindow *)[[UIApplication sharedApplication] keyWindow]\"\n    )\n    mask = fb.evaluateExpression(\n        \"(UIView *)[%s viewWithTag:(NSInteger)%s]\" % (window, viewOrLayer)\n    )\n    fb.evaluateEffect(\"[%s removeFromSuperview]\" % mask)\n    flushCoreAnimationTransaction()\n\n\ndef convertPoint(x, y, fromViewOrLayer, toViewOrLayer):\n    fromLayer = convertToLayer(fromViewOrLayer)\n    toLayer = convertToLayer(toViewOrLayer)\n    return fb.evaluateExpressionValue(\n        \"(CGPoint)[%s convertPoint:(CGPoint){ .x = %s, .y = %s } toLayer:(CALayer *)%s]\"\n        % (fromLayer, x, y, toLayer)\n    )\n\n\ndef convertToLayer(viewOrLayer):\n    if fb.evaluateBooleanExpression(\n        \"[(id)%s isKindOfClass:(Class)[CALayer class]]\" % viewOrLayer\n    ):\n        return viewOrLayer\n    elif fb.evaluateBooleanExpression(\n        \"[(id)%s respondsToSelector:(SEL)@selector(layer)]\" % viewOrLayer\n    ):\n        return fb.evaluateExpression(\"(CALayer *)[%s layer]\" % viewOrLayer)\n    else:\n        raise Exception(\"Argument must be a CALayer, UIView, or NSView.\")\n\n\ndef isUIView(obj):\n    return not runtimeHelpers.isMacintoshArch() and fb.evaluateBooleanExpression(\n        \"[(id)%s isKindOfClass:(Class)[UIView class]]\" % obj\n    )\n\n\ndef isNSView(obj):\n    return runtimeHelpers.isMacintoshArch() and fb.evaluateBooleanExpression(\n        \"[(id)%s isKindOfClass:(Class)[NSView class]]\" % obj\n    )\n\n\ndef isView(obj):\n    return isUIView(obj) or isNSView(obj)\n\n\n# Generates a BFS of the views tree starting at the given view as root.\n# Yields a tuple of the current view in the tree and its level (view, level)\ndef subviewsOfView(view):\n    views = [(view, 0)]\n    yield views[0]\n    while views:\n        (view, level) = views.pop(0)\n        subviews = fb.evaluateExpression(\"(id)[%s subviews]\" % view)\n        subviewsCount = int(fb.evaluateExpression(\"(int)[(id)%s count]\" % subviews))\n        for i in range(subviewsCount):\n            subview = fb.evaluateExpression(\"(id)[%s objectAtIndex:%i]\" % (subviews, i))\n            views.append((subview, level + 1))\n            yield (subview, level + 1)\n\n\ndef upwardsRecursiveDescription(view, maxDepth=0):\n    if not fb.evaluateBooleanExpression(\n        \"[(id)%s isKindOfClass:(Class)[UIView class]]\" % view\n    ) and not fb.evaluateBooleanExpression(\n        \"[(id)%s isKindOfClass:(Class)[NSView class]]\" % view\n    ):\n        return None\n\n    currentView = view\n    recursiveDescription = []\n    depth = 0\n\n    while currentView and (maxDepth <= 0 or depth <= maxDepth):\n        depth += 1\n\n        viewDescription = fb.evaluateExpressionValue(\n            \"(id)[%s debugDescription]\" % (currentView)\n        ).GetObjectDescription()\n        currentView = fb.evaluateExpression(\"(void*)[%s superview]\" % (currentView))\n        try:\n            if int(currentView, 0) == 0:\n                currentView = None\n        except Exception:\n            currentView = None\n\n        if viewDescription:\n            recursiveDescription.insert(0, viewDescription)\n\n    if not len(viewDescription):\n        return None\n\n    currentPrefix = \"\"\n    builder = \"\"\n    for viewDescription in recursiveDescription:\n        builder += currentPrefix + viewDescription + \"\\n\"\n        currentPrefix += \"   | \"\n\n    return builder\n\n\ndef slowAnimation(speed=1):\n    fb.evaluateEffect(\n        '[[[UIApplication sharedApplication] windows] setValue:@(%s) forKeyPath:@\"layer.speed\"]'\n        % speed\n    )\n"
  }
]