diff --git a/CHANGELOG.md b/CHANGELOG.md
index 210f123a94..cb8adffa6b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,7 +8,10 @@
##### Enhancements
-* None.
+* Add `checkstyle` reporter to generate XML reports in the Checkstyle 4.3
+ format.
+ [JP Simard](https://github.com/jpsim)
+ [#277](https://github.com/realm/SwiftLint/issues/277)
##### Bug Fixes
diff --git a/README.md b/README.md
index 1532081f93..392e64cc18 100644
--- a/README.md
+++ b/README.md
@@ -133,7 +133,7 @@ variable_name_max_length:
variable_name_min_length:
- 3 # warning
- 2 # error
-reporter: "csv" # reporter type (xcode, json, csv)
+reporter: "csv" # reporter type (xcode, json, csv, checkstyle)
```
### Auto-correct
diff --git a/Source/SwiftLintFramework/Models/Configuration.swift b/Source/SwiftLintFramework/Models/Configuration.swift
index 0e3b2b0c28..b80f12e7ec 100644
--- a/Source/SwiftLintFramework/Models/Configuration.swift
+++ b/Source/SwiftLintFramework/Models/Configuration.swift
@@ -25,7 +25,7 @@ public struct Configuration {
public let disabledRules: [String] // disabled_rules
public let included: [String] // included
public let excluded: [String] // excluded
- public let reporter: String // reporter (xcode, json, csv)
+ public let reporter: String // reporter (xcode, json, csv, checkstyle)
public let rules: [Rule]
public var reporterFromString: Reporter.Type {
@@ -36,6 +36,8 @@ public struct Configuration {
return JSONReporter.self
case CSVReporter.identifier:
return CSVReporter.self
+ case CheckstyleReporter.identifier:
+ return CheckstyleReporter.self
default:
fatalError("no reporter with identifier '\(reporter)' available.")
}
diff --git a/Source/SwiftLintFramework/Reporters/CheckstyleReporter.swift b/Source/SwiftLintFramework/Reporters/CheckstyleReporter.swift
new file mode 100644
index 0000000000..ae68015a55
--- /dev/null
+++ b/Source/SwiftLintFramework/Reporters/CheckstyleReporter.swift
@@ -0,0 +1,33 @@
+//
+// CheckstyleReporter.swift
+// SwiftLint
+//
+// Created by JP Simard on 12/25/15.
+// Copyright © 2015 Realm. All rights reserved.
+//
+
+import Foundation
+
+public struct CheckstyleReporter: Reporter {
+ public static let identifier = "checkstyle"
+ public static let isRealtime = false
+
+ public var description: String {
+ return "Reports violations as Checkstyle XML."
+ }
+
+ public static func generateReport(violations: [StyleViolation]) -> String {
+ var report = "\n"
+ report += violations.map { violation in
+ let fileName = violation.location.file ?? ""
+ return "\n\t\n" +
+ "\t\t\n" +
+ "\t"
+ }.joinWithSeparator("")
+ report += "\n"
+ return report
+ }
+}
diff --git a/Source/SwiftLintFrameworkTests/ReporterTests.swift b/Source/SwiftLintFrameworkTests/ReporterTests.swift
index dd98a8bed5..66c66762ae 100644
--- a/Source/SwiftLintFrameworkTests/ReporterTests.swift
+++ b/Source/SwiftLintFrameworkTests/ReporterTests.swift
@@ -65,4 +65,16 @@ class ReporterTests: XCTestCase {
"filename,1,2,Error,Line Length,Violation Reason.,line_length"
)
}
+
+ func testCheckstyleReporter() {
+ XCTAssertEqual(
+ CheckstyleReporter.generateReport(generateViolations()),
+ "\n\n" +
+ "\t\n\t\t\n\t\n" +
+ "\t\n\t\t\n\t\n" +
+ ""
+ )
+ }
}
diff --git a/SwiftLint.xcodeproj/project.pbxproj b/SwiftLint.xcodeproj/project.pbxproj
index ef5318c893..b26e74ff8c 100644
--- a/SwiftLint.xcodeproj/project.pbxproj
+++ b/SwiftLint.xcodeproj/project.pbxproj
@@ -88,6 +88,7 @@
E8C0DFCD1AD349DB007EE3D4 /* SWXMLHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8C0DFCC1AD349DB007EE3D4 /* SWXMLHash.framework */; };
E8C0DFCE1AD349E5007EE3D4 /* SWXMLHash.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = E8C0DFCC1AD349DB007EE3D4 /* SWXMLHash.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
E8C164C21BEA9EDA00177258 /* ASTRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8BB8F991B17DDB200199606 /* ASTRuleTests.swift */; };
+ E8EA41171C2D1DBE004F9930 /* CheckstyleReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8EA41161C2D1DBE004F9930 /* CheckstyleReporter.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -235,6 +236,7 @@
E8BB8F991B17DDB200199606 /* ASTRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASTRuleTests.swift; sourceTree = ""; };
E8BB8F9B1B17DE3B00199606 /* StringRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringRuleTests.swift; sourceTree = ""; };
E8C0DFCC1AD349DB007EE3D4 /* SWXMLHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SWXMLHash.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ E8EA41161C2D1DBE004F9930 /* CheckstyleReporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckstyleReporter.swift; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -450,6 +452,7 @@
E86396C31BADAC0D002C9E88 /* Reporters */ = {
isa = PBXGroup;
children = (
+ E8EA41161C2D1DBE004F9930 /* CheckstyleReporter.swift */,
E86396CA1BADB519002C9E88 /* CSVReporter.swift */,
E86396C81BADB2B9002C9E88 /* JSONReporter.swift */,
E86396C41BADAC15002C9E88 /* XcodeReporter.swift */,
@@ -725,6 +728,7 @@
E88198531BEA944400333A11 /* LineLengthRule.swift in Sources */,
E88198441BEA93D200333A11 /* ColonRule.swift in Sources */,
E809EDA11B8A71DF00399043 /* Configuration.swift in Sources */,
+ E8EA41171C2D1DBE004F9930 /* CheckstyleReporter.swift in Sources */,
E88DEA731B0984C400A66CB0 /* String+SwiftLint.swift in Sources */,
E88198591BEA95F100333A11 /* LeadingWhitespaceRule.swift in Sources */,
24E17F721B14BB3F008195BE /* File+Cache.swift in Sources */,