// // HTMLReporter.swift // SwiftLint // // Created by Johnykutty on 10/27/16. // Copyright © 2016 Realm. All rights reserved. // import Foundation private let formatter: DateFormatter = { let formatter = DateFormatter() formatter.dateStyle = .short return formatter }() public struct HTMLReporter: Reporter { public static let identifier = "html" public static let isRealtime = false public var description: String { return "Reports violations as HTML" } public static func generateReport(_ violations: [StyleViolation]) -> String { return generateReport(violations, swiftlintVersion: Version.current.value, dateString: formatter.string(from: Date())) } // swiftlint:disable:next function_body_length internal static func generateReport(_ violations: [StyleViolation], swiftlintVersion: String, dateString: String) -> String { let rows = violations.enumerated().reduce("") { rows, indexAndViolation in return rows + generateSingleRow(for: indexAndViolation.1, at: indexAndViolation.0 + 1) } let fileCount = Set(violations.flatMap({ $0.location.file })).count let warningCount = violations.filter({ $0.severity == .warning }).count let errorCount = violations.filter({ $0.severity == .error }).count return [ "\n", "\n", "\t\n", "\t\t\n", "\t\t\n", "\t\t\n", "\t\t\n", "\t\t\n", "\t\tSwiftLint Report\n", "\t\n", "\t\n", "\t\t

SwiftLint Report

\n", "\t\t\n", "\t\t
\n", "\t\t\n", "\t\t

Violations

\n", "\t\t\n", "\t\t\n", "\t\t\t\n", "\t\t\t\t\n", "\t\t\t\t\t\n", "\t\t\t\t\t\n", "\t\t\t\t\t\n", "\t\t\t\t\t\n", "\t\t\t\t\t\n", "\t\t\t\t\n", "\t\t\t\n", "\t\t\t\n", rows, "\t\t\t\n", "\t\t
\n", "\t\t\t\t\t\tSerial No.\n", "\t\t\t\t\t\n", "\t\t\t\t\t\tFile\n", "\t\t\t\t\t\n", "\t\t\t\t\t\tLocation\n", "\t\t\t\t\t\n", "\t\t\t\t\t\tSeverity\n", "\t\t\t\t\t\n", "\t\t\t\t\t\tMessage\n", "\t\t\t\t\t
\n", "\t\t\n", "\t\t
\n", "\t\t\n", "\t\t

Summary

\n", "\t\t\n", "\t\t\n", "\t\t\t\n", "\t\t\t\t\n", "\t\t\t\t\t\n", "\t\t\t\t\t\n", "\t\t\t\t\n", "\t\t\t\t\n", "\t\t\t\t\t\n", "\t\t\t\t\t\n", "\t\t\t\t\n", "\t\t\t\t\n", "\t\t\t\t\t\n", "\t\t\t\t\t\n", "\t\t\t\t\n", "\t\t\t\n", "\t\t
Total files with violations\(fileCount)
Total warnings\(warningCount)
Total errors\(errorCount)
\n", "\t\t\n", "\t\t
\n", "\t\t\n", "\t\t

\n", "\t\t\tCreated with\n", "\t\t\tSwiftLint\n", "\t\t\t", swiftlintVersion, " on ", dateString, "\n", "\t\t

\n", "\t\n", "" ].joined() } private static func generateSingleRow(for violation: StyleViolation, at index: Int) -> String { let severity: String = violation.severity.rawValue.capitalized let location = violation.location let file: String = (violation.location.relativeFile ?? "").escapedForXML() let line: Int = location.line ?? 0 let character: Int = location.character ?? 0 return [ "\t\t\t\t\n", "\t\t\t\t\t\(index)\n", "\t\t\t\t\t", file, "\n", "\t\t\t\t\t\(line):\(character)\n", "\t\t\t\t\t", severity, "\n", "\t\t\t\t\t\(violation.reason.escapedForXML())\n", "\t\t\t\t\n" ].joined() } }