mirror of
https://github.com/realm/SwiftLint.git
synced 2026-06-06 20:18:40 +00:00
792032480e
Co-authored-by: Saleem Abdulrasool <compnerd@compnerd.org> Co-authored-by: Roman Lavrov <roman.lavrov@thebrowser.company>
93 lines
3.4 KiB
Swift
93 lines
3.4 KiB
Swift
import Foundation
|
|
import SourceKittenFramework
|
|
|
|
/// To some tools (i.e. Datadog), code quality findings are reported in the SARIF format:
|
|
/// - Full Spec: https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html
|
|
/// - Samples: https://github.com/microsoft/sarif-tutorials/blob/main/samples/
|
|
/// - JSON Validator: https://sarifweb.azurewebsites.net/Validation
|
|
struct SARIFReporter: Reporter {
|
|
// MARK: - Reporter Conformance
|
|
static let identifier = "sarif"
|
|
static let isRealtime = false
|
|
static let description = "Reports violations in the Static Analysis Results Interchange Format (SARIF)"
|
|
static let swiftlintVersion = "https://github.com/realm/SwiftLint/blob/\(Version.current.value)/README.md"
|
|
|
|
static func generateReport(_ violations: [StyleViolation]) -> String {
|
|
let SARIFJson = [
|
|
"version": "2.1.0",
|
|
"$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json",
|
|
"runs": [
|
|
[
|
|
"tool": [
|
|
"driver": [
|
|
"name": "SwiftLint",
|
|
"semanticVersion": Version.current.value,
|
|
"informationUri": swiftlintVersion,
|
|
"rules": RuleRegistry.shared.list.list.values
|
|
.sorted { $0.identifier < $1.identifier }
|
|
.map(dictionary(for:)),
|
|
],
|
|
],
|
|
"results": violations.map(dictionary(for:)),
|
|
],
|
|
],
|
|
] as [String: Any]
|
|
|
|
return toJSON(SARIFJson, options: [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes])
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
private static func dictionary(for ruleType: any Rule.Type) -> [String: Any] {
|
|
let description = ruleType.description
|
|
return [
|
|
"id": description.identifier,
|
|
"shortDescription": [
|
|
"text": description.name
|
|
],
|
|
"fullDescription": [
|
|
"text": description.description
|
|
],
|
|
"helpUri": "https://realm.github.io/SwiftLint/\(description.identifier).html",
|
|
]
|
|
}
|
|
|
|
private static func dictionary(for violation: StyleViolation) -> [String: Any] {
|
|
[
|
|
"level": violation.severity.rawValue,
|
|
"ruleId": violation.ruleIdentifier,
|
|
"message": [
|
|
"text": violation.reason
|
|
],
|
|
"locations": [
|
|
dictionary(for: violation.location)
|
|
],
|
|
]
|
|
}
|
|
|
|
private static func dictionary(for location: Location) -> [String: Any] {
|
|
// According to SARIF specification JSON1008, minimum value for line is 1
|
|
if let line = location.line, line > 0 {
|
|
return [
|
|
"physicalLocation": [
|
|
"artifactLocation": [
|
|
"uri": location.file?.relativeDisplayPath ?? ""
|
|
],
|
|
"region": [
|
|
"startLine": line,
|
|
"startColumn": location.character ?? 1,
|
|
],
|
|
],
|
|
]
|
|
}
|
|
|
|
return [
|
|
"physicalLocation": [
|
|
"artifactLocation": [
|
|
"uri": location.file?.relativeDisplayPath ?? ""
|
|
],
|
|
],
|
|
]
|
|
}
|
|
}
|