<commit_before>import Foundation

/// PBXProjPlist string that contains a comment.
struct PBXProjPlistCommentedString: Hashable, ExpressibleByStringLiteral {

    /// Entity string value.
    let string: String

    /// String comment.
    let comment: String?
    
    /// Initializes the commented string with the value and the comment.
    ///
    /// - Parameters:
    ///   - string: string value.
    ///   - comment: comment.
    init(_ string: String, comment: String? = nil) {
        self.string = string
        self.comment = comment
    }
    
    // MARK: - Hashable
    
    var hashValue: Int { return string.hashValue }
    static func == (lhs: PBXProjPlistCommentedString, rhs: PBXProjPlistCommentedString) -> Bool {
        return lhs.string == rhs.string && lhs.comment == rhs.comment
    }
    
    // MARK: - ExpressibleByStringLiteral
    
    public init(stringLiteral value: String) {
        self.init(value)
    }

    public init(extendedGraphemeClusterLiteral value: String) {
        self.init(value)
    }
    
    public init(unicodeScalarLiteral value: String) {
        self.init(value)
    }
    
}

/// It represents a PBXProj Plist valid value.
///
/// - string: commented string.
/// - array: array of plist values.
/// - dictionary: dictionary where the keys are a commented strings and the values are a plist values.
enum PBXProjPlistValue: ExpressibleByArrayLiteral, ExpressibleByDictionaryLiteral, ExpressibleByStringLiteral {
    case string(PBXProjPlistCommentedString)
    case array([PBXProjPlistValue])
    case dictionary([PBXProjPlistCommentedString: PBXProjPlistValue])
    var string: (PBXProjPlistCommentedString)? {
        switch self {
        case .string(let string): return string
        default: return nil
        }
    }
    var array: [PBXProjPlistValue]? {
        switch self {
        case .array(let array): return array
        default: return nil
        }
    }
    var dictionary: [PBXProjPlistCommentedString: PBXProjPlistValue]? {
        switch self {
        case .dictionary(let dictionary): return dictionary
        default: return nil
        }
    }
    
    // MARK: - ExpressibleByArrayLiteral
    
    public init(arrayLiteral elements: PBXProjPlistValue...) {
        self = .array(elements)
    }
    
    // MARK: - ExpressibleByDictionaryLiteral
    
    public init(dictionaryLiteral elements: (PBXProjPlistCommentedString, PBXProjPlistValue)...) {
        var dictionary: [PBXProjPlistCommentedString: PBXProjPlistValue] = [:]
        elements.forEach { dictionary[$0.0] = $0.1 }
        self = .dictionary(dictionary)
    }
    
    // MARK: - ExpressibleByStringLiteral
    
    public init(stringLiteral value: String) {
        self = .string(PBXProjPlistCommentedString(value))
    }
    public init(extendedGraphemeClusterLiteral value: String) {
        self = .string(PBXProjPlistCommentedString(value))
    }
    public init(unicodeScalarLiteral value: String) {
        self = .string(PBXProjPlistCommentedString(value))
    }
}

/// Protocol that defines that the element can return a plist element that represents itself.
protocol PBXProjPlistSerializable {
    func pbxProjPlistElement(proj: PBXProj) -> (key: PBXProjPlistCommentedString, value: PBXProjPlistValue)
}

/// Writes your PBXProj files
class PBXProjWriter {
    
    var indent: UInt = 0
    var output: String = ""
    
    func write(proj: PBXProj) -> String {
        writeUtf8()
        writeNewLine()
        writeDictionaryStart()
        write(dictionaryKey: "archiveVersion", dictionaryValue: .string(PBXProjPlistCommentedString("\(proj.archiveVersion)")))
        write(dictionaryKey: "classes", dictionaryValue: .array([]))
        write(dictionaryKey: "objectVersion", dictionaryValue: .string(PBXProjPlistCommentedString("\(proj.objectVersion)")))
        writeIndent()
        write(string: "objects = {")
        increaseIndent()
        writeNewLine()
        write(section: "PBXNativeTarget", proj: proj, object: proj.objects.nativeTargets)
        write(section: "XCConfigurationList", proj: proj, object: proj.objects.configurationLists)
        write(section: "PBXProject", proj: proj, object: proj.objects.projects)
        write(section: "XCBuildConfiguration", proj: proj, object: proj.objects.buildConfigurations)
        write(section: "PBXVariantGroup", proj: proj, object: proj.objects.variantGroups)
        write(section: "PBXTargetDependency", proj: proj, object: proj.objects.targetDependencies)
        write(section: "PBXSourcesBuildPhase", proj: proj, object: proj.objects.sourcesBuildPhases)
        write(section: "PBXShellScriptBuildPhase", proj: proj, object: proj.objects.shellScriptBuildPhases)
        decreaseIndent()
        writeIndent()
        write(string: "};")
        writeNewLine()
        write(dictionaryKey: "rootObject",
              dictionaryValue: .string(PBXProjPlistCommentedString(proj.rootObject,
                                                                   comment: "Project object")))
        writeDictionaryEnd()
        return output
    }
    
    // MARK: - Private
    
    private func writeUtf8() {
        output.append("// !$*UTF8*$!")
    }
    
    private func writeNewLine() {
        output.append("\n")
    }
    
    private func write(value: PBXProjPlistValue) {
        switch value {
        case .array(let array):
            write(array: array)
        case .dictionary(let dictionary):
            write(dictionary: dictionary)
        case .string(let commentedString):
            write(commentedString: commentedString)
        }
    }<commit_msg>[pbxprojwriter] Add comments with the objects that are missing for writing<commit_after>import Foundation

/// PBXProjPlist string that contains a comment.
struct PBXProjPlistCommentedString: Hashable, ExpressibleByStringLiteral {

    /// Entity string value.
    let string: String

    /// String comment.
    let comment: String?
    
    /// Initializes the commented string with the value and the comment.
    ///
    /// - Parameters:
    ///   - string: string value.
    ///   - comment: comment.
    init(_ string: String, comment: String? = nil) {
        self.string = string
        self.comment = comment
    }
    
    // MARK: - Hashable
    
    var hashValue: Int { return string.hashValue }
    static func == (lhs: PBXProjPlistCommentedString, rhs: PBXProjPlistCommentedString) -> Bool {
        return lhs.string == rhs.string && lhs.comment == rhs.comment
    }
    
    // MARK: - ExpressibleByStringLiteral
    
    public init(stringLiteral value: String) {
        self.init(value)
    }

    public init(extendedGraphemeClusterLiteral value: String) {
        self.init(value)
    }
    
    public init(unicodeScalarLiteral value: String) {
        self.init(value)
    }
    
}

/// It represents a PBXProj Plist valid value.
///
/// - string: commented string.
/// - array: array of plist values.
/// - dictionary: dictionary where the keys are a commented strings and the values are a plist values.
enum PBXProjPlistValue: ExpressibleByArrayLiteral, ExpressibleByDictionaryLiteral, ExpressibleByStringLiteral {
    case string(PBXProjPlistCommentedString)
    case array([PBXProjPlistValue])
    case dictionary([PBXProjPlistCommentedString: PBXProjPlistValue])
    var string: (PBXProjPlistCommentedString)? {
        switch self {
        case .string(let string): return string
        default: return nil
        }
    }
    var array: [PBXProjPlistValue]? {
        switch self {
        case .array(let array): return array
        default: return nil
        }
    }
    var dictionary: [PBXProjPlistCommentedString: PBXProjPlistValue]? {
        switch self {
        case .dictionary(let dictionary): return dictionary
        default: return nil
        }
    }
    
    // MARK: - ExpressibleByArrayLiteral
    
    public init(arrayLiteral elements: PBXProjPlistValue...) {
        self = .array(elements)
    }
    
    // MARK: - ExpressibleByDictionaryLiteral
    
    public init(dictionaryLiteral elements: (PBXProjPlistCommentedString, PBXProjPlistValue)...) {
        var dictionary: [PBXProjPlistCommentedString: PBXProjPlistValue] = [:]
        elements.forEach { dictionary[$0.0] = $0.1 }
        self = .dictionary(dictionary)
    }
    
    // MARK: - ExpressibleByStringLiteral
    
    public init(stringLiteral value: String) {
        self = .string(PBXProjPlistCommentedString(value))
    }
    public init(extendedGraphemeClusterLiteral value: String) {
        self = .string(PBXProjPlistCommentedString(value))
    }
    public init(unicodeScalarLiteral value: String) {
        self = .string(PBXProjPlistCommentedString(value))
    }
}

/// Protocol that defines that the element can return a plist element that represents itself.
protocol PBXProjPlistSerializable {
    func pbxProjPlistElement(proj: PBXProj) -> (key: PBXProjPlistCommentedString, value: PBXProjPlistValue)
}

/// Writes your PBXProj files
class PBXProjWriter {
    
    var indent: UInt = 0
    var output: String = ""
    
    func write(proj: PBXProj) -> String {
        writeUtf8()
        writeNewLine()
        writeDictionaryStart()
        write(dictionaryKey: "archiveVersion", dictionaryValue: .string(PBXProjPlistCommentedString("\(proj.archiveVersion)")))
        write(dictionaryKey: "classes", dictionaryValue: .array([]))
        write(dictionaryKey: "objectVersion", dictionaryValue: .string(PBXProjPlistCommentedString("\(proj.objectVersion)")))
        writeIndent()
        write(string: "objects = {")
        increaseIndent()
        writeNewLine()
        write(section: "PBXNativeTarget", proj: proj, object: proj.objects.nativeTargets)
        // PBXAggregateTarget
        // PBXBuildFile
        // PBXFileReference
        write(section: "PBXProject", proj: proj, object: proj.objects.projects)
        // PBXFileElement
        // PBXGroup
        // PBXHeadersBuildPhase
        // PBXFrameworksBuildPhase
        // PBXResourcesBuildPhase
        write(section: "PBXShellScriptBuildPhase", proj: proj, object: proj.objects.shellScriptBuildPhases)
        write(section: "PBXSourcesBuildPhase", proj: proj, object: proj.objects.sourcesBuildPhases)
        write(section: "PBXTargetDependency", proj: proj, object: proj.objects.targetDependencies)
        write(section: "PBXVariantGroup", proj: proj, object: proj.objects.variantGroups)
        write(section: "XCBuildConfiguration", proj: proj, object: proj.objects.buildConfigurations)
        write(section: "XCConfigurationList", proj: proj, object: proj.objects.configurationLists)
        // PBXCopyFilesBuildPhase
        // PBXContainerItemProxy
        decreaseIndent()
        writeIndent()
        write(string: "};")
        writeNewLine()
        write(dictionaryKey: "rootObject",
              dictionaryValue: .string(PBXProjPlistCommentedString(proj.rootObject,
                                                                   comment: "Project object")))
        writeDictionaryEnd()
        return output
    }
    
    // MARK: - Private
    
    private func writeUtf8() {
        output.append("// !$*UTF8*$!")
    }
    
    private func writeNewLine() {
        output.append("\n")
    }
    
    private func write(value: PBXProjPlistValue) {
        switch value {
        case .array(let array):
            write(array: array)
        case .dictionary(let dictionary):
            write(dictionary: dictionary)
        case .string(let commentedString):
            write(commentedString: commentedString)
        }
    }
{'fraction_non_alphanumeric': 0.09973208884279665, 'fraction_numerical': 0.001382767262985049, 'mean_word_length': 2.647021745981721, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1440936', 'n_tokens_mistral': 3420, 'n_tokens_neox': 3255, 'n_words': 752}