<commit_before>//
//  DecorationViewsHandler.swift
//  Pods
//
//  Created by <NAME> on 07/09/2017.
//
//

import Foundation
import UIKit
import CoreGraphics

public typealias DecorationAttributes = [String : [IndexPath : UICollectionViewLayoutAttributes]]

public struct DecorationViewsHandler {
    
    unowned let _collectionViewLayout: UICollectionViewLayout
    var _elementKinds = [String]()
    var _attributes = DecorationAttributes()
    var _oldAttributes:DecorationAttributes?
    
    // update
    var _inserted = [String : [IndexPath]]()
    var _deleted = [String : [IndexPath]]()
    
    public init(collectionViewLayout: UICollectionViewLayout) {
        _collectionViewLayout = collectionViewLayout
    }
    
    public mutating func register(viewClass:AnyClass, for elementKind:String) {
        if let _ = _attributes[elementKind] {
            return
        }
        _elementKinds.append(elementKind)
        _attributes[elementKind] = [IndexPath : UICollectionViewLayoutAttributes]()
        _collectionViewLayout.register(viewClass, forDecorationViewOfKind: elementKind)
    }
    
    public mutating func register(nib:UINib, for elementKind:String) {
        if let _ = _attributes[elementKind] {
            return
        }
        _elementKinds.append(elementKind)
        _attributes[elementKind] = [IndexPath : UICollectionViewLayoutAttributes]()
        _collectionViewLayout.register(nib, forDecorationViewOfKind: elementKind)
    }
    
    public mutating func add(attributes:UICollectionViewLayoutAttributes) {
        guard let elementKind = attributes.representedElementKind else {
            return
        }
        _attributes[elementKind]![attributes.indexPath] = attributes
    }
    
    public mutating func prepare() {
        _oldAttributes = _attributes
        _elementKinds.forEach { elementKind in
            _attributes[elementKind]?.removeAll()
        }
    }
    
    
    
    public func attributes(in rect:CGRect) -> [UICollectionViewLayoutAttributes] {
        return _attributes.flatMap { $0.value }.map { $0.value }.filter { $0.frame.intersects(rect) }
    }
    
    public func attributes(for elementKind:String) -> [IndexPath : UICollectionViewLayoutAttributes] {
        return attributes(for: elementKind, into: _attributes)
    }
    
    public func attributes<T:UICollectionViewLayoutAttributes>(for elementKind:String, at indexPath:IndexPath) -> T? {
        return attributes(for: elementKind, at: indexPath, into: _attributes)
    }
    
    public func oldAttributes(for elementKind:String) -> [IndexPath : UICollectionViewLayoutAttributes] {
        return attributes(for: elementKind, into: _oldAttributes)
    }
    
    public func oldAttributes<T:UICollectionViewLayoutAttributes>(for elementKind:String, at indexPath:IndexPath) -> T? {
        return attributes(for: elementKind, at: indexPath, into: _oldAttributes)
    }
    
    public mutating func prepare(forCollectionViewUpdates updateItems: [UICollectionViewUpdateItem]) {
        
        _elementKinds.forEach { elementKind in
            _inserted[elementKind] = [IndexPath]()
            _deleted[elementKind] = [IndexPath]()
        }
        
        updateItems.forEach { updateItem in
            switch (updateItem.updateAction) {
            case .delete:
                elementKind(for: updateItem.indexPathBeforeUpdate!, in: _oldAttributes!).forEach { kind in
                    _deleted[kind]!.append(updateItem.indexPathBeforeUpdate!)
                }
            case .insert:
                elementKind(for: updateItem.indexPathAfterUpdate!, in: _attributes).forEach { kind in
                    _inserted[kind]!.append(updateItem.indexPathAfterUpdate!)
                }
            case .reload, .move: //TODO: if move, try to check if same kind of decorationView doesn't impact the move
                elementKind(for: updateItem.indexPathBeforeUpdate!, in: _oldAttributes!).forEach { kind in
                    _deleted[kind]!.append(updateItem.indexPathBeforeUpdate!)
                }
                elementKind(for: updateItem.indexPathAfterUpdate!, in: _attributes).forEach { kind in
                    _inserted[kind]!.append(updateItem.indexPathAfterUpdate!)
                }
            default:
                break
            }
        }
    }
    
    public func inserted(for elementKind:String) -> [IndexPath] {
        return _inserted[elementKind] ?? []
    }
    
    public func deleted(for elementKind:String) -> [IndexPath] {
        return _deleted[elementKind] ?? []
    }
}<commit_msg>Ensure prepare(forCollectionViewUpdates:) will not attempt to unwrap nil optionals (fixes crashing test)<commit_after>//
//  DecorationViewsHandler.swift
//  Pods
//
//  Created by <NAME> on 07/09/2017.
//
//

import Foundation
import UIKit
import CoreGraphics

public typealias DecorationAttributes = [String : [IndexPath : UICollectionViewLayoutAttributes]]

public struct DecorationViewsHandler {
    
    unowned let _collectionViewLayout: UICollectionViewLayout
    var _elementKinds = [String]()
    var _attributes = DecorationAttributes()
    var _oldAttributes:DecorationAttributes?
    
    // update
    var _inserted = [String : [IndexPath]]()
    var _deleted = [String : [IndexPath]]()
    
    public init(collectionViewLayout: UICollectionViewLayout) {
        _collectionViewLayout = collectionViewLayout
    }
    
    public mutating func register(viewClass:AnyClass, for elementKind:String) {
        if let _ = _attributes[elementKind] {
            return
        }
        _elementKinds.append(elementKind)
        _attributes[elementKind] = [IndexPath : UICollectionViewLayoutAttributes]()
        _collectionViewLayout.register(viewClass, forDecorationViewOfKind: elementKind)
    }
    
    public mutating func register(nib:UINib, for elementKind:String) {
        if let _ = _attributes[elementKind] {
            return
        }
        _elementKinds.append(elementKind)
        _attributes[elementKind] = [IndexPath : UICollectionViewLayoutAttributes]()
        _collectionViewLayout.register(nib, forDecorationViewOfKind: elementKind)
    }
    
    public mutating func add(attributes:UICollectionViewLayoutAttributes) {
        guard let elementKind = attributes.representedElementKind else {
            return
        }
        _attributes[elementKind]![attributes.indexPath] = attributes
    }
    
    public mutating func prepare() {
        _oldAttributes = _attributes
        _elementKinds.forEach { elementKind in
            _attributes[elementKind]?.removeAll()
        }
    }
    
    
    
    public func attributes(in rect:CGRect) -> [UICollectionViewLayoutAttributes] {
        return _attributes.flatMap { $0.value }.map { $0.value }.filter { $0.frame.intersects(rect) }
    }
    
    public func attributes(for elementKind:String) -> [IndexPath : UICollectionViewLayoutAttributes] {
        return attributes(for: elementKind, into: _attributes)
    }
    
    public func attributes<T:UICollectionViewLayoutAttributes>(for elementKind:String, at indexPath:IndexPath) -> T? {
        return attributes(for: elementKind, at: indexPath, into: _attributes)
    }
    
    public func oldAttributes(for elementKind:String) -> [IndexPath : UICollectionViewLayoutAttributes] {
        return attributes(for: elementKind, into: _oldAttributes)
    }
    
    public func oldAttributes<T:UICollectionViewLayoutAttributes>(for elementKind:String, at indexPath:IndexPath) -> T? {
        return attributes(for: elementKind, at: indexPath, into: _oldAttributes)
    }
    
    public mutating func prepare(forCollectionViewUpdates updateItems: [UICollectionViewUpdateItem]) {
        
        _elementKinds.forEach { elementKind in
            _inserted[elementKind] = [IndexPath]()
            _deleted[elementKind] = [IndexPath]()
        }
        
        updateItems.forEach { updateItem in
            switch (updateItem.updateAction) {
            case .delete:
                guard let indexPathBeforeUpdate = updateItem.indexPathBeforeUpdate else {
                    break
                }
                elementKind(for: indexPathBeforeUpdate, in: _oldAttributes!).forEach { kind in
                    _deleted[kind]!.append(indexPathBeforeUpdate)
                }
            case .insert:
                guard let indexPathAfterUpdate = updateItem.indexPathAfterUpdate else {
                    break
                }
                elementKind(for: indexPathAfterUpdate, in: _attributes).forEach { kind in
                    _inserted[kind]!.append(indexPathAfterUpdate)
                }
            case .reload, .move: //TODO: if move, try to check if same kind of decorationView doesn't impact the move
                guard let indexPathBeforeUpdate = updateItem.indexPathBeforeUpdate,
                    let indexPathAfterUpdate = updateItem.indexPathAfterUpdate else {
                    break
                }
                elementKind(for: indexPathBeforeUpdate, in: _oldAttributes!).forEach { kind in
                    _deleted[kind]!.append(indexPathBeforeUpdate)
                }
                elementKind(for: indexPathAfterUpdate, in: _attributes).forEach { kind in
                    _inserted[kind]!.append(indexPathAfterUpdate)
                }
            default:
                break
            }
        }
    }
    
    public func inserted(for elementKind:String) -> [IndexPath] {
        return _inserted[elementKind] ?? []
    }
    
    public func deleted(for elementKind:String) -> [IndexPath] {
        return _deleted[elementKind] ?? []
    }
}
{'fraction_non_alphanumeric': 0.08342845283802013, 'fraction_numerical': 0.002282868112483138, 'mean_word_length': 2.5577703949796975, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 23, 'https://': 0, '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': '6260361', 'n_tokens_mistral': 2537, 'n_tokens_neox': 2509, 'n_words': 534}