mirror of
https://github.com/realm/SwiftLint.git
synced 2026-05-07 20:12:49 +00:00
a6c4fd98bc
Ideally, SwiftLintCore would some day only contain components that are needed to define rules. Consequently, it would be the only bundle required to import for (external) rule development.
169 lines
5.6 KiB
Swift
169 lines
5.6 KiB
Swift
import Foundation
|
|
|
|
private let formatter: DateFormatter = {
|
|
let formatter = DateFormatter()
|
|
formatter.dateStyle = .short
|
|
return formatter
|
|
}()
|
|
|
|
/// Reports violations as HTML.
|
|
struct HTMLReporter: Reporter {
|
|
// MARK: - Reporter Conformance
|
|
|
|
static let identifier = "html"
|
|
static let isRealtime = false
|
|
static let description = "Reports violations as HTML."
|
|
|
|
static func generateReport(_ violations: [StyleViolation]) -> String {
|
|
generateReport(violations, swiftlintVersion: Version.current.value, dateString: formatter.string(from: Date()))
|
|
}
|
|
|
|
// MARK: - Internal
|
|
|
|
// swiftlint:disable:next function_body_length
|
|
internal static func generateReport(_ violations: [StyleViolation],
|
|
swiftlintVersion: String,
|
|
dateString: String) -> String {
|
|
let rows = violations.enumerated()
|
|
.map { generateSingleRow(for: $1, at: $0 + 1) }
|
|
.joined(separator: "\n")
|
|
|
|
let fileCount = Set(violations.compactMap(\.location.file)).count
|
|
let warningCount = violations.filter({ $0.severity == .warning }).count
|
|
let errorCount = violations.filter({ $0.severity == .error }).count
|
|
|
|
return """
|
|
<!doctype html>
|
|
<html>
|
|
\t<head>
|
|
\t\t<meta charset="utf-8" />
|
|
\t\t<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
\t\t
|
|
\t\t<style type="text/css">
|
|
\t\t\tbody {
|
|
\t\t\t\tfont-family: Arial, Helvetica, sans-serif;
|
|
\t\t\t\tfont-size: 0.9rem;
|
|
\t\t\t}
|
|
\t\t\t
|
|
\t\t\ttable {
|
|
\t\t\t\tborder: 1px solid gray;
|
|
\t\t\t\tborder-collapse: collapse;
|
|
\t\t\t\t-moz-box-shadow: 3px 3px 4px #AAA;
|
|
\t\t\t\t-webkit-box-shadow: 3px 3px 4px #AAA;
|
|
\t\t\t\tbox-shadow: 3px 3px 4px #AAA;
|
|
\t\t\t\tvertical-align: top;
|
|
\t\t\t\theight: 64px;
|
|
\t\t\t}
|
|
\t\t\t
|
|
\t\t\ttd, th {
|
|
\t\t\t\tborder: 1px solid #D3D3D3;
|
|
\t\t\t\tpadding: 5px 10px 5px 10px;
|
|
\t\t\t}
|
|
\t\t\t
|
|
\t\t\tth {
|
|
\t\t\t\tborder-bottom: 1px solid gray;
|
|
\t\t\t\tbackground-color: rgba(41,52,92,0.313);
|
|
\t\t\t}
|
|
\t\t\t
|
|
\t\t\t.error, .warning {
|
|
\t\t\t\ttext-align: center;
|
|
\t\t\t}
|
|
\t\t\t
|
|
\t\t\t.error {
|
|
\t\t\t\tbackground-color: #FF9D92;
|
|
\t\t\t\tcolor: #7F0800;
|
|
\t\t\t}
|
|
\t\t\t
|
|
\t\t\t.warning {
|
|
\t\t\t\tbackground-color: #FFF59E;
|
|
\t\t\t\tcolor: #7F7000;
|
|
\t\t\t}
|
|
\t\t</style>
|
|
\t\t
|
|
\t\t<title>SwiftLint Report</title>
|
|
\t</head>
|
|
\t<body>
|
|
\t\t<h1>SwiftLint Report</h1>
|
|
\t\t
|
|
\t\t<hr />
|
|
\t\t
|
|
\t\t<h2>Violations</h2>
|
|
\t\t
|
|
\t\t<table>
|
|
\t\t\t<thead>
|
|
\t\t\t\t<tr>
|
|
\t\t\t\t\t<th style="width: 60pt;">
|
|
\t\t\t\t\t\t<b>Serial No.</b>
|
|
\t\t\t\t\t</th>
|
|
\t\t\t\t\t<th style="width: 500pt;">
|
|
\t\t\t\t\t\t<b>File</b>
|
|
\t\t\t\t\t</th>
|
|
\t\t\t\t\t<th style="width: 60pt;">
|
|
\t\t\t\t\t\t<b>Location</b>
|
|
\t\t\t\t\t</th>
|
|
\t\t\t\t\t<th style="width: 60pt;">
|
|
\t\t\t\t\t\t<b>Severity</b>
|
|
\t\t\t\t\t</th>
|
|
\t\t\t\t\t<th style="width: 500pt;">
|
|
\t\t\t\t\t\t<b>Message</b>
|
|
\t\t\t\t\t</th>
|
|
\t\t\t\t</tr>
|
|
\t\t\t</thead>
|
|
\t\t\t<tbody>
|
|
\(rows)
|
|
\t\t\t</tbody>
|
|
\t\t</table>
|
|
\t\t
|
|
\t\t<br/>
|
|
\t\t
|
|
\t\t<h2>Summary</h2>
|
|
\t\t
|
|
\t\t<table>
|
|
\t\t\t<tbody>
|
|
\t\t\t\t<tr>
|
|
\t\t\t\t\t<td>Total files with violations</td>
|
|
\t\t\t\t\t<td>\(fileCount)</td>
|
|
\t\t\t\t</tr>
|
|
\t\t\t\t<tr>
|
|
\t\t\t\t\t<td>Total warnings</td>
|
|
\t\t\t\t\t<td>\(warningCount)</td>
|
|
\t\t\t\t</tr>
|
|
\t\t\t\t<tr>
|
|
\t\t\t\t\t<td>Total errors</td>
|
|
\t\t\t\t\t<td>\(errorCount)</td>
|
|
\t\t\t\t</tr>
|
|
\t\t\t</tbody>
|
|
\t\t</table>
|
|
\t\t
|
|
\t\t<hr />
|
|
\t\t
|
|
\t\t<p>
|
|
\t\t\tCreated with
|
|
\t\t\t<a href="https://github.com/realm/SwiftLint"><b>SwiftLint</b></a>
|
|
\t\t\t\(swiftlintVersion) on \(dateString)
|
|
\t\t</p>
|
|
\t</body>
|
|
</html>
|
|
"""
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
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 ?? "<nopath>").escapedForXML()
|
|
let line: Int = location.line ?? 0
|
|
let character: Int = location.character ?? 0
|
|
return """
|
|
\t\t\t\t<tr>
|
|
\t\t\t\t\t<td style="text-align: right;">\(index)</td>
|
|
\t\t\t\t\t<td>\(file)</td>
|
|
\t\t\t\t\t<td style="text-align: center;">\(line):\(character)</td>
|
|
\t\t\t\t\t<td class="\(severity.lowercased())">\(severity)</td>
|
|
\t\t\t\t\t<td>\(violation.reason.escapedForXML())</td>
|
|
\t\t\t\t</tr>
|
|
"""
|
|
}
|
|
}
|