Skip to content

Commit

Permalink
Add markdown reporter (realm#2486)
Browse files Browse the repository at this point in the history
  • Loading branch information
madcato authored and jpsim committed Nov 27, 2018
1 parent 827410a commit b58c4e3
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@

#### Enhancements

* Add custom markdown reporter
Markdown reporter (formatted with tables for Gitlab and Github)
[Dani Vela](https://github.com/madcato)

* Add `SWIFTLINT_DISABLE_SOURCEKIT` environment variable to allow running
SwiftLint without connecting to SourceKit. This will run a subset of rules
that don't require SourceKit, which is useful when running in a sandboxed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ identifier_name:
- id
- URL
- GlobalAPIKey
reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit, html, emoji, sonarqube)
reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit, html, emoji, sonarqube, markdown)
```
You can also use environment variables in your configuration file,
Expand Down
2 changes: 1 addition & 1 deletion README_KR.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ identifier_name:
- id
- URL
- GlobalAPIKey
reporter: "xcode" # 보고 유형 (xcode, json, csv, checkstyle, junit, html, emoji)
reporter: "xcode" # 보고 유형 (xcode, json, csv, checkstyle, junit, html, emoji, markdown)
```
#### 커스텀 룰 정의
Expand Down
2 changes: 2 additions & 0 deletions Source/SwiftLintFramework/Protocols/Reporter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public func reporterFrom(identifier: String) -> Reporter.Type {
return EmojiReporter.self
case SonarQubeReporter.identifier:
return SonarQubeReporter.self
case MarkdownReporter.identifier:
return MarkdownReporter.self
default:
queuedFatalError("no reporter with identifier '\(identifier)' available.")
}
Expand Down
52 changes: 52 additions & 0 deletions Source/SwiftLintFramework/Reporters/MarkdownReporter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Foundation

private extension String {
func escapedForMarkdown() -> String {
let escapedString = replacingOccurrences(of: "\"", with: "\"\"")
if escapedString.contains("|") || escapedString.contains("\n") {
return "\"\(escapedString)\""
}
return escapedString
}
}

public struct MarkdownReporter: Reporter {
public static let identifier = "markdown"
public static let isRealtime = false

public var description: String {
return "Reports violations as markdown formated (with tables)"
}

public static func generateReport(_ violations: [StyleViolation]) -> String {
let keys = [
"file",
"line",
"severity",
"reason",
"rule_id"
].joined(separator: " | ")

let rows = [keys, "--- | --- | --- | --- | ---"] + violations.map(markdownRow(for:))
return rows.joined(separator: "\n")
}

fileprivate static func markdownRow(for violation: StyleViolation) -> String {
return [
violation.location.file?.escapedForMarkdown() ?? "",
violation.location.line?.description ?? "",
severity(for: violation.severity),
violation.ruleDescription.name.escapedForMarkdown() + ": " + violation.reason.escapedForMarkdown(),
violation.ruleDescription.identifier
].joined(separator: " | ")
}

fileprivate static func severity(for severity: ViolationSeverity) -> String {
switch severity {
case .error:
return ":stop\\_sign:"
case .warning:
return ":warning:"
}
}
}
8 changes: 8 additions & 0 deletions SwiftLint.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
2E336D1B1DF08BFB00CCFE77 /* EmojiReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E336D191DF08AF200CCFE77 /* EmojiReporter.swift */; };
2E5761AA1C573B83003271AF /* FunctionParameterCountRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E5761A91C573B83003271AF /* FunctionParameterCountRule.swift */; };
31F1B6CC1F60BF4500A57456 /* SwitchCaseAlignmentRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31F1B6CB1F60BF4500A57456 /* SwitchCaseAlignmentRule.swift */; };
341FDB1F21AD66550022E8E9 /* CannedMarkdownReporterOutput.md in Resources */ = {isa = PBXBuildFile; fileRef = 341FDB1E21AD66550022E8E9 /* CannedMarkdownReporterOutput.md */; };
341FDB2021AD69970022E8E9 /* MarkdownReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 341FDB1C21AD61B20022E8E9 /* MarkdownReporter.swift */; };
37B3FA8B1DFD45A700AD30D2 /* Dictionary+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B3FA8A1DFD45A700AD30D2 /* Dictionary+SwiftLint.swift */; };
3A915E5B20A1543700519F3A /* ClosureEndIndentationRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A915E5920A1543000519F3A /* ClosureEndIndentationRuleExamples.swift */; };
3ABE19CF20B7CE32009C2EC2 /* MultilineFunctionChainsRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABE19CD20B7CDE0009C2EC2 /* MultilineFunctionChainsRule.swift */; };
Expand Down Expand Up @@ -459,6 +461,8 @@
2E336D191DF08AF200CCFE77 /* EmojiReporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmojiReporter.swift; sourceTree = "<group>"; };
2E5761A91C573B83003271AF /* FunctionParameterCountRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionParameterCountRule.swift; sourceTree = "<group>"; };
31F1B6CB1F60BF4500A57456 /* SwitchCaseAlignmentRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwitchCaseAlignmentRule.swift; sourceTree = "<group>"; };
341FDB1C21AD61B20022E8E9 /* MarkdownReporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownReporter.swift; sourceTree = "<group>"; };
341FDB1E21AD66550022E8E9 /* CannedMarkdownReporterOutput.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CannedMarkdownReporterOutput.md; sourceTree = "<group>"; };
37B3FA8A1DFD45A700AD30D2 /* Dictionary+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Dictionary+SwiftLint.swift"; sourceTree = "<group>"; };
3A915E5920A1543000519F3A /* ClosureEndIndentationRuleExamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosureEndIndentationRuleExamples.swift; sourceTree = "<group>"; };
3ABE19CD20B7CDE0009C2EC2 /* MultilineFunctionChainsRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilineFunctionChainsRule.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -867,6 +871,7 @@
B3935001033261E5A70CE101 /* CannedEmojiReporterOutput.txt */,
B39350463894A3FC1338E0AF /* CannedJSONReporterOutput.json */,
584B0D3B2112E8FB002F7E25 /* CannedSonarQubeReporterOutput.json */,
341FDB1E21AD66550022E8E9 /* CannedMarkdownReporterOutput.md */,
);
path = Resources;
sourceTree = "<group>";
Expand Down Expand Up @@ -1396,6 +1401,7 @@
4A9A3A391DC1D75F00DF5183 /* HTMLReporter.swift */,
E86396C81BADB2B9002C9E88 /* JSONReporter.swift */,
57ED82791CF65183002B3513 /* JUnitReporter.swift */,
341FDB1C21AD61B20022E8E9 /* MarkdownReporter.swift */,
E86396C41BADAC15002C9E88 /* XcodeReporter.swift */,
584B0D392112BA78002F7E25 /* SonarQubeReporter.swift */,
);
Expand Down Expand Up @@ -1620,6 +1626,7 @@
files = (
3B12C9C11C3209CB000B423F /* test.yml in Resources */,
F9D73F031D0CF15E00222FC4 /* test.txt in Resources */,
341FDB1F21AD66550022E8E9 /* CannedMarkdownReporterOutput.md in Resources */,
3BDB224B1C345B4900473680 /* ProjectMock in Resources */,
B3935797FF80C7F97953D375 /* CannedHTMLReporterOutput.html in Resources */,
B3935371E92E0CF3F7668303 /* CannedJunitReporterOutput.xml in Resources */,
Expand Down Expand Up @@ -1782,6 +1789,7 @@
D4E92D1F2137B4C9002EDD48 /* IdenticalOperandsRule.swift in Sources */,
6250D32A1ED4DFEB00735129 /* MultilineParametersRule.swift in Sources */,
009E092A1DFEE4DD00B588A7 /* ProhibitedSuperConfiguration.swift in Sources */,
341FDB2021AD69970022E8E9 /* MarkdownReporter.swift in Sources */,
181D9E172038343D001F6887 /* UntypedErrorInCatchRule.swift in Sources */,
47FF3BE11E7C75B600187E6D /* ImplicitlyUnwrappedOptionalRule.swift in Sources */,
623E36F01F3DB1B1002E5B71 /* QuickDiscouragedCallRule.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
3 changes: 2 additions & 1 deletion Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,8 @@ extension ReporterTests {
("testCheckstyleReporter", testCheckstyleReporter),
("testJunitReporter", testJunitReporter),
("testHTMLReporter", testHTMLReporter),
("testSonarQubeReporter", testSonarQubeReporter)
("testSonarQubeReporter", testSonarQubeReporter),
("testMarkdownReporter", testMarkdownReporter)
]
}

Expand Down
9 changes: 8 additions & 1 deletion Tests/SwiftLintFrameworkTests/ReporterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ class ReporterTests: XCTestCase {
JUnitReporter.self,
HTMLReporter.self,
EmojiReporter.self,
SonarQubeReporter.self
SonarQubeReporter.self,
MarkdownReporter.self
]
for reporter in reporters {
XCTAssertEqual(reporter.identifier, reporterFrom(identifier: reporter.identifier).identifier)
Expand Down Expand Up @@ -109,4 +110,10 @@ class ReporterTests: XCTestCase {
let result = SonarQubeReporter.generateReport(generateViolations())
XCTAssertEqual(try jsonValue(result), try jsonValue(expectedOutput))
}

func testMarkdownReporter() {
let expectedOutput = stringFromFile("CannedMarkdownReporterOutput.md")
let result = MarkdownReporter.generateReport(generateViolations())
XCTAssertEqual(result, expectedOutput)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
file | line | severity | reason | rule_id
--- | --- | --- | --- | ---
filename | 1 | :warning: | Line Length: Violation Reason. | line_length
filename | 1 | :stop\_sign: | Line Length: Violation Reason. | line_length
filename | 1 | :stop\_sign: | Syntactic Sugar: Shorthand syntactic sugar should be used, i.e. [Int] instead of Array<Int>. | syntactic_sugar
| | :stop\_sign: | Colon: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals. | colon

0 comments on commit b58c4e3

Please sign in to comment.