<commit_before>//
//  UIMenuController.swift
//  MenuItemKit
//
//  Created by <NAME> on 1/17/16.
//  Copyright © 2016 lazyapps. All rights reserved.
//

import UIKit
import ObjectiveC.runtime

// This is inspired by https://github.com/steipete/PSMenuItem
internal func swizzle(class klass: AnyClass, shouldShowForAction: @escaping (_ action: Selector, _ default: Bool) -> Bool = { $1 }) {
  objc_sync_enter(klass)
  defer { objc_sync_exit(klass) }
  let key: StaticString = #function
  guard objc_getAssociatedObject(klass, key.utf8Start) == nil else { return }
  if true {
    // swizzle canBecomeFirstResponder
    let selector = #selector(getter: UIResponder.canBecomeFirstResponder)
    let block: @convention(block) (AnyObject) -> Bool = { _ in true }
    setNewIMPWithBlock(block, forSelector: selector, toClass: klass)
  }

  if true {
    // swizzle canPerformAction:withSender:
    let selector = #selector(UIResponder.canPerformAction(_:withSender:))
    let origIMP = class_getMethodImplementation(klass, selector)
    typealias IMPType = @convention(c) (AnyObject, Selector, Selector, AnyObject) -> Bool
    let origIMPC = unsafeBitCast(origIMP, to: IMPType.self)
    let block: @convention(block) (AnyObject, Selector, AnyObject) -> Bool = {
      let `default` = UIMenuItem.isMenuItemKitSelector($1) ? true : origIMPC($0, selector, $1, $2)
      return shouldShowForAction($1, `default`)
    }

    setNewIMPWithBlock(block, forSelector: selector, toClass: klass)
  }

  if true {
    // swizzle methodSignatureForSelector:
    let selector = NSSelectorFromString("methodSignatureForSelector:")
    let origIMP = class_getMethodImplementation(klass, selector)
    typealias IMPType = @convention(c) (AnyObject, Selector, Selector) -> AnyObject
    let origIMPC = unsafeBitCast(origIMP, to: IMPType.self)
    let block: @convention(block) (AnyObject, Selector) -> AnyObject = {
      if UIMenuItem.isMenuItemKitSelector($1) {
        // `NSMethodSignature` is not allowed in Swift, this is a workaround
        return NSObject.perform(NSSelectorFromString("_mik_fakeSignature")).takeUnretainedValue()
      }

      return origIMPC($0, selector, $1)
    }

    setNewIMPWithBlock(block, forSelector: selector, toClass: klass)
  }

  if true {
    // swizzle forwardInvocation:
    // `NSInvocation` is not allowed in Swift, so we just use AnyObject
    let selector = NSSelectorFromString("forwardInvocation:")
    let origIMP = class_getMethodImplementation(klass, selector)
    typealias IMPType = @convention(c) (AnyObject, Selector, AnyObject) -> ()
    let origIMPC = unsafeBitCast(origIMP, to: IMPType.self)
    let block: @convention(block) (AnyObject, AnyObject) -> () = {
      if UIMenuItem.isMenuItemKitSelector($1.selector) {
        guard let item = UIMenuController.shared.findMenuItemBySelector($1.selector) else { return }
        item.actionBox.value?(item)
      } else {
        origIMPC($0, selector, $1)
      }
    }

    setNewIMPWithBlock(block, forSelector: selector, toClass: klass)
  }

  objc_setAssociatedObject(klass, key.utf8Start, true, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}

private extension UIMenuController {
  @objc class func _mik_load() {
    if true {
      let selector = #selector(setter: menuItems)
      let origIMP = class_getMethodImplementation(self, selector)
      typealias IMPType = @convention(c) (AnyObject, Selector, AnyObject) -> ()
      let origIMPC = unsafeBitCast(origIMP, to: IMPType.self)
      let block: @convention(block) (AnyObject, AnyObject) -> () = {
        if let firstResp = UIResponder.mik_firstResponder {
          swizzle(class: type(of: firstResp.mik_responderToSwizzle))
        }

        origIMPC($0, selector, makeUniqueImageTitles($1))
      }

      setNewIMPWithBlock(block, forSelector: selector, toClass: self)
    }
<commit_msg>Fix issues on nil menu items<commit_after>//
//  UIMenuController.swift
//  MenuItemKit
//
//  Created by <NAME> on 1/17/16.
//  Copyright © 2016 lazyapps. All rights reserved.
//

import UIKit
import ObjectiveC.runtime

// This is inspired by https://github.com/steipete/PSMenuItem
internal func swizzle(class klass: AnyClass, shouldShowForAction: @escaping (_ action: Selector, _ default: Bool) -> Bool = { $1 }) {
  objc_sync_enter(klass)
  defer { objc_sync_exit(klass) }
  let key: StaticString = #function
  guard objc_getAssociatedObject(klass, key.utf8Start) == nil else { return }
  if true {
    // swizzle canBecomeFirstResponder
    let selector = #selector(getter: UIResponder.canBecomeFirstResponder)
    let block: @convention(block) (AnyObject) -> Bool = { _ in true }
    setNewIMPWithBlock(block, forSelector: selector, toClass: klass)
  }

  if true {
    // swizzle canPerformAction:withSender:
    let selector = #selector(UIResponder.canPerformAction(_:withSender:))
    let origIMP = class_getMethodImplementation(klass, selector)
    typealias IMPType = @convention(c) (AnyObject, Selector, Selector, AnyObject) -> Bool
    let origIMPC = unsafeBitCast(origIMP, to: IMPType.self)
    let block: @convention(block) (AnyObject, Selector, AnyObject) -> Bool = {
      let `default` = UIMenuItem.isMenuItemKitSelector($1) ? true : origIMPC($0, selector, $1, $2)
      return shouldShowForAction($1, `default`)
    }

    setNewIMPWithBlock(block, forSelector: selector, toClass: klass)
  }

  if true {
    // swizzle methodSignatureForSelector:
    let selector = NSSelectorFromString("methodSignatureForSelector:")
    let origIMP = class_getMethodImplementation(klass, selector)
    typealias IMPType = @convention(c) (AnyObject, Selector, Selector) -> AnyObject
    let origIMPC = unsafeBitCast(origIMP, to: IMPType.self)
    let block: @convention(block) (AnyObject, Selector) -> AnyObject = {
      if UIMenuItem.isMenuItemKitSelector($1) {
        // `NSMethodSignature` is not allowed in Swift, this is a workaround
        return NSObject.perform(NSSelectorFromString("_mik_fakeSignature")).takeUnretainedValue()
      }

      return origIMPC($0, selector, $1)
    }

    setNewIMPWithBlock(block, forSelector: selector, toClass: klass)
  }

  if true {
    // swizzle forwardInvocation:
    // `NSInvocation` is not allowed in Swift, so we just use AnyObject
    let selector = NSSelectorFromString("forwardInvocation:")
    let origIMP = class_getMethodImplementation(klass, selector)
    typealias IMPType = @convention(c) (AnyObject, Selector, AnyObject) -> ()
    let origIMPC = unsafeBitCast(origIMP, to: IMPType.self)
    let block: @convention(block) (AnyObject, AnyObject) -> () = {
      if UIMenuItem.isMenuItemKitSelector($1.selector) {
        guard let item = UIMenuController.shared.findMenuItemBySelector($1.selector) else { return }
        item.actionBox.value?(item)
      } else {
        origIMPC($0, selector, $1)
      }
    }

    setNewIMPWithBlock(block, forSelector: selector, toClass: klass)
  }

  objc_setAssociatedObject(klass, key.utf8Start, true, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}

private extension UIMenuController {
  @objc class func _mik_load() {
    if true {
      let selector = #selector(setter: menuItems)
      let origIMP = class_getMethodImplementation(self, selector)
      typealias IMPType = @convention(c) (AnyObject, Selector, AnyObject?) -> ()
      let origIMPC = unsafeBitCast(origIMP, to: IMPType.self)
      let block: @convention(block) (AnyObject, AnyObject?) -> () = {
        if let firstResp = UIResponder.mik_firstResponder {
          swizzle(class: type(of: firstResp.mik_responderToSwizzle))
        }

        origIMPC($0, selector, $1.flatMap(makeUniqueImageTitles))
      }

      setNewIMPWithBlock(block, forSelector: selector, toClass: self)
    }

{'fraction_non_alphanumeric': 0.10949095169899753, 'fraction_numerical': 0.006769951829188907, 'mean_word_length': 3.8898790579248885, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 25, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5601659', 'n_tokens_mistral': 2498, 'n_tokens_neox': 2419, 'n_words': 559}