<commit_before>//
//  MethodNode.swift
//  Mapper
//
//  Created by LZephyr on 2017/9/27.
//  Copyright © 2017年 LZephyr. All rights reserved.
//

import Foundation

// MARK: - Param

struct Param {
    var outterName: String  // 参数的名字
    var type: String  // 参数类型
    var innerName: String  // 内部形参的名字
}

// MARK: - MethodNode

/// 方法定义
class MethodNode: Node {
    var isSwift = false  // 是否为swift方法
    var isStatic = false  // 是否为类方法
    var returnType: String = "" // 返回值类型
    var methodName: String = "" // 方法的名字
    var params: [Param] = [] // 方法的参数
    var invokes: [MethodInvokeNode] = [] // 方法体中调用的方法
}

// MARK: - 初始化方法

extension MethodNode {
    /// OC初始化方法
    class func ocInit(_ isStatic: Bool, _ retType: String, _ params: [Param], _ invokes: [MethodInvokeNode]) -> MethodNode {
        let method = MethodNode()
        
        method.isSwift = false
        method.isStatic = isStatic
        method.returnType = retType
        method.params = params
        method.invokes = invokes
        
        return method
    }
    
    /// swift初始化方法
    class func swiftInit(_ isStatic: Bool, _ name: String, _ params: [Param], _ retType: String, _ invokes: [MethodInvokeNode]) -> MethodNode {
        let method = MethodNode()
        
        method.isSwift = true
        method.isStatic = isStatic
        method.returnType = retType
        method.methodName = name
        method.params = params
        method.invokes = invokes
        
        return method
    }
}

// MARK: - 数据格式化

extension MethodNode: CustomStringConvertible {
    var description: String {
        if isSwift {
            return swiftDescription
        } else {
            return objcDescription
        }
    }
    
    /// 格式化成OC风格
    var objcDescription: String {
        var method = "\(isStatic ? "+" : "-") ["
        
        let methodDesc = params.join(stringify: { (param) -> String in
            if !param.innerName.isEmpty {
                return "\(param.outterName):"
            } else {
                return param.outterName
            }
        }, separator: " ")
        method.append(contentsOf: "\(methodDesc)]")
        
        return method
    }
    
    /// 格式化成swift风格
    var swiftDescription: String {
        var method = ""
        
        if methodName != "init" {
            method.append(contentsOf: "func ")
        }
        method.append(contentsOf: "\(methodName)(")
        
        if isStatic {
            method.insert(contentsOf: "static ", at: method.startIndex)
        }
        
        let paramStr = params.join(stringify: { (param) -> String in
            return "\(param.outterName.isEmpty ? "_" : param.outterName): "
        }, separator: ", ")
        method.append(contentsOf: "\(paramStr))")
        
        return method
    }
}

extension MethodNode {
    /// 将方法转化成JSON字典
    func toJson(clsId: String, methods: [Int]) -> [String: Any] {
        var info: [String: Any] = [:]
        info["type"] = "method"                         // type
        info["classId"] = clsId                         // classId
        info["static"] = self.isStatic                  // static
        info["isSwift"] = self.isSwift                  // isSwift
        
        if isSwift {
            info["name"] = methodName                   // name
        }
        
        info["returnType"] = returnType                 // returnType
        info["id"] = ID_MD5("\(clsId)\(self.hashValue)") // 类id加上自身的id作为方法的id
        
        // 参数
        var paramInfo: [[String: String]] = []
        for param in params {
            paramInfo.append(["type": param.type, "sel": param.outterName, "name": param.innerName])
        }
        info["params"] = paramInfo                      // params
        
        // 调用的方法
        var invokeInfos: [[String: String]] = []
        for invoke in invokes {
            // 如果调用的是自身的方法
            if methods.contains(invoke.hashValue) {
                invokeInfos.append([
                    "methodId": ID_MD5("\(clsId)\(invoke.hashValue)"),
                    "classId": clsId
                    ])
            } else {
                invokeInfos.append(["formatedName": invoke.description])
            }
        }
        info["invokes"] = invokeInfos                   // invokes
        
        return info
    }
}

// MARK: - Hashable

extension MethodNode: Hashable {
    
    static func ==(_ left: MethodNode, _ right: MethodNode) -> Bool {
        return left.hashValue == right.hashValue
    }
    
    /// 目前swift和oc之间不能判等
    var hashValue: Int {
        if isSwift {
            return swiftHashValue
        } else {<commit_msg>invokes去重<commit_after>//
//  MethodNode.swift
//  Mapper
//
//  Created by LZephyr on 2017/9/27.
//  Copyright © 2017年 LZephyr. All rights reserved.
//

import Foundation

// MARK: - Param

struct Param {
    var outterName: String  // 参数的名字
    var type: String  // 参数类型
    var innerName: String  // 内部形参的名字
}

// MARK: - MethodNode

/// 方法定义
class MethodNode: Node {
    var isSwift = false  // 是否为swift方法
    var isStatic = false  // 是否为类方法
    var returnType: String = "" // 返回值类型
    var methodName: String = "" // 方法的名字
    var params: [Param] = [] // 方法的参数
    var invokes: [MethodInvokeNode] = [] // 方法体中调用的方法
}

// MARK: - 初始化方法

extension MethodNode {
    /// OC初始化方法
    class func ocInit(_ isStatic: Bool, _ retType: String, _ params: [Param], _ invokes: [MethodInvokeNode]) -> MethodNode {
        let method = MethodNode()
        
        method.isSwift = false
        method.isStatic = isStatic
        method.returnType = retType
        method.params = params
        method.invokes = invokes
        
        return method
    }
    
    /// swift初始化方法
    class func swiftInit(_ isStatic: Bool, _ name: String, _ params: [Param], _ retType: String, _ invokes: [MethodInvokeNode]) -> MethodNode {
        let method = MethodNode()
        
        method.isSwift = true
        method.isStatic = isStatic
        method.returnType = retType
        method.methodName = name
        method.params = params
        method.invokes = invokes
        
        return method
    }
}

// MARK: - 数据格式化

extension MethodNode: CustomStringConvertible {
    var description: String {
        if isSwift {
            return swiftDescription
        } else {
            return objcDescription
        }
    }
    
    /// 格式化成OC风格
    var objcDescription: String {
        var method = "\(isStatic ? "+" : "-") ["
        
        let methodDesc = params.join(stringify: { (param) -> String in
            if !param.innerName.isEmpty {
                return "\(param.outterName):"
            } else {
                return param.outterName
            }
        }, separator: " ")
        method.append(contentsOf: "\(methodDesc)]")
        
        return method
    }
    
    /// 格式化成swift风格
    var swiftDescription: String {
        var method = ""
        
        if methodName != "init" {
            method.append(contentsOf: "func ")
        }
        method.append(contentsOf: "\(methodName)(")
        
        if isStatic {
            method.insert(contentsOf: "static ", at: method.startIndex)
        }
        
        let paramStr = params.join(stringify: { (param) -> String in
            return "\(param.outterName.isEmpty ? "_" : param.outterName): "
        }, separator: ", ")
        method.append(contentsOf: "\(paramStr))")
        
        return method
    }
}

extension MethodNode {
    /// 将方法转化成JSON字典
    func toJson(clsId: String, methods: [Int]) -> [String: Any] {
        var info: [String: Any] = [:]
        info["type"] = "method"                         // type
        info["classId"] = clsId                         // classId
        info["static"] = self.isStatic                  // static
        info["isSwift"] = self.isSwift                  // isSwift
        
        if isSwift {
            info["name"] = methodName                   // name
        }
        
        info["returnType"] = returnType                 // returnType
        info["id"] = ID_MD5("\(clsId)\(self.hashValue)") // 类id加上自身的id作为方法的id
        
        // 参数
        var paramInfo: [[String: String]] = []
        for param in params {
            paramInfo.append(["type": param.type, "sel": param.outterName, "name": param.innerName])
        }
        info["params"] = paramInfo                      // params
        
        // 调用的方法
        var invokeInfos: [[String: String]] = []
        var set = Set<MethodInvokeNode>() // 去重
        for invoke in invokes {
            if set.contains(invoke) {
                continue
            }
            // 如果调用的是自身的方法
            if methods.contains(invoke.hashValue) {
                invokeInfos.append([
                    "methodId": ID_MD5("\(clsId)\(invoke.hashValue)"),
                    "classId": clsId
                    ])
            } else {
                invokeInfos.append(["formatedName": invoke.description])
            }
            set.insert(invoke)
        }
        info["invokes"] = invokeInfos                   // invokes
        
        return info
    }
}

// MARK: - Hashable

extension MethodNode: Hashable {
    
    static func ==(_ left: MethodNode, _ right: MethodNode) -> Bool {
        return left.hashValue == right.hashValue
    }
    
    /// 目前swift和oc之间不能判等
    var hashValue: Int {
        if isSwift {
            return swiftHashValue
        } else {
{'fraction_non_alphanumeric': 0.11549862375608723, 'fraction_numerical': 0.0027524878255346177, 'mean_word_length': 1.5118319595852168, 'pattern_counts': {'":': 12, '<': 4, '<?xml version=': 0, '>': 16, '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': '956638', 'n_tokens_mistral': 2898, 'n_tokens_neox': 2800, 'n_words': 616}