Files
Danny Mösch a6c4fd98bc Move files from SwiftLintCore to SwiftLintFramework
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.
2024-12-23 12:51:43 +01:00

47 lines
1.8 KiB
Swift

/// Reports violations as XML conforming to the Checkstyle specification, as defined here:
/// https://www.jetbrains.com/help/teamcity/xml-report-processing.html
struct CheckstyleReporter: Reporter {
// MARK: - Reporter Conformance
static let identifier = "checkstyle"
static let isRealtime = false
static let description = "Reports violations as Checkstyle XML."
static func generateReport(_ violations: [StyleViolation]) -> String {
[
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<checkstyle version=\"4.3\">",
violations
.group(by: { ($0.location.file ?? "<nopath>").escapedForXML() })
.sorted(by: { $0.key < $1.key })
.map(generateForViolationFile).joined(),
"\n</checkstyle>",
].joined()
}
// MARK: - Private
private static func generateForViolationFile(_ file: String, violations: [StyleViolation]) -> String {
[
"\n\t<file name=\"", file, "\">\n",
violations.map(generateForSingleViolation).joined(),
"\t</file>",
].joined()
}
private static func generateForSingleViolation(_ violation: StyleViolation) -> String {
let line: Int = violation.location.line ?? 0
let col: Int = violation.location.character ?? 0
let severity: String = violation.severity.rawValue
let reason: String = violation.reason.escapedForXML()
let identifier: String = violation.ruleIdentifier
let source: String = "swiftlint.rules.\(identifier)".escapedForXML()
return [
"\t\t<error line=\"\(line)\" ",
"column=\"\(col)\" ",
"severity=\"", severity, "\" ",
"message=\"", reason, "\" ",
"source=\"\(source)\"/>\n",
].joined()
}
}