diff --git a/Source/SwiftLintFramework/Reporters/CheckstyleReporter.swift b/Source/SwiftLintFramework/Reporters/CheckstyleReporter.swift index 866c9d894..936acdb45 100644 --- a/Source/SwiftLintFramework/Reporters/CheckstyleReporter.swift +++ b/Source/SwiftLintFramework/Reporters/CheckstyleReporter.swift @@ -25,11 +25,11 @@ public struct CheckstyleReporter: Reporter { } private static func generateForSingleViolation(_ violation: StyleViolation) -> String { - let file: String = violation.location.file ?? "" + let file: String = violation.location.file?.escapedForXml() ?? "" 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 + let reason: String = violation.reason.escapedForXml() return [ "\n\t\n", "\t\t String { let severity: String = violation.severity.rawValue.capitalized let location = violation.location - let file: String = location.file ?? "" + let file: String = location.file?.escapedForXml() ?? "" let line: Int = location.line ?? 0 let character: Int = location.character ?? 0 return [ @@ -129,7 +129,7 @@ public struct HTMLReporter: Reporter { "\t\t\t\t\t", file, "\n", "\t\t\t\t\t\(line):\(character)\n", "\t\t\t\t\t", severity, "\n", - "\t\t\t\t\t\(violation.reason)\n", + "\t\t\t\t\t\(violation.reason.escapedForXml())\n", "\t\t\t\t\n" ].joined() } diff --git a/Source/SwiftLintFramework/Reporters/JUnitReporter.swift b/Source/SwiftLintFramework/Reporters/JUnitReporter.swift index 1a04c8a5d..fa77e9229 100644 --- a/Source/SwiftLintFramework/Reporters/JUnitReporter.swift +++ b/Source/SwiftLintFramework/Reporters/JUnitReporter.swift @@ -19,11 +19,12 @@ public struct JUnitReporter: Reporter { public static func generateReport(_ violations: [StyleViolation]) -> String { return "\n" + violations.map({ violation in - let fileName = violation.location.file ?? "" + let fileName = violation.location.file?.escapedForXml() ?? "" let severity = violation.severity.rawValue + ":\n" let message = severity + "Line:" + String(violation.location.line ?? 0) + " " + let reason = violation.reason.escapedForXml() return ["\n\t\n", - "" + message + "", + "" + message + "", "\t"].joined(separator: "") }).joined(separator: "") + "\n" } diff --git a/Source/SwiftLintFramework/Reporters/String+XML.swift b/Source/SwiftLintFramework/Reporters/String+XML.swift new file mode 100644 index 000000000..6d67d520e --- /dev/null +++ b/Source/SwiftLintFramework/Reporters/String+XML.swift @@ -0,0 +1,25 @@ +// +// CheckstyleReporter.swift +// SwiftLint +// +// Created by Fabian Ehrentraud on 12/12/16. +// Copyright © 2016 Realm. All rights reserved. +// + +extension String { + func escapedForXml() -> String { + // & needs to go first, otherwise other replacements will be replaced again + let htmlEscapes = [ + ("&", "&"), + ("\"", """), + ("'", "'"), + (">", ">"), + ("<", "<") + ] + var newString = self + for (key, value) in htmlEscapes { + newString = newString.replacingOccurrences(of: key, with: value) + } + return newString + } +} diff --git a/SwiftLint.xcodeproj/project.pbxproj b/SwiftLint.xcodeproj/project.pbxproj index cbcf18d2d..d33a38439 100644 --- a/SwiftLint.xcodeproj/project.pbxproj +++ b/SwiftLint.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 1E82D5591D7775C7009553D7 /* ClosureSpacingRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E82D5581D7775C7009553D7 /* ClosureSpacingRule.swift */; }; 1EC163521D5992D900DD2928 /* VerticalWhitespaceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EC163511D5992D900DD2928 /* VerticalWhitespaceRule.swift */; }; 1F11B3CF1C252F23002E8FA8 /* ClosingBraceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F11B3CE1C252F23002E8FA8 /* ClosingBraceRule.swift */; }; + 1F8547141DFEA44C0052E729 /* String+XML.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8547131DFEA44C0052E729 /* String+XML.swift */; }; 24B4DF0D1D6DFDE90097803B /* RedundantNilCoalescingRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24B4DF0B1D6DFA370097803B /* RedundantNilCoalescingRule.swift */; }; 24E17F721B14BB3F008195BE /* File+Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E17F701B1481FF008195BE /* File+Cache.swift */; }; 2E02005F1C54BF680024D09D /* CyclomaticComplexityRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E02005E1C54BF680024D09D /* CyclomaticComplexityRule.swift */; }; @@ -219,6 +220,7 @@ 1E82D5581D7775C7009553D7 /* ClosureSpacingRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClosureSpacingRule.swift; sourceTree = ""; }; 1EC163511D5992D900DD2928 /* VerticalWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalWhitespaceRule.swift; sourceTree = ""; }; 1F11B3CE1C252F23002E8FA8 /* ClosingBraceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClosingBraceRule.swift; sourceTree = ""; }; + 1F8547131DFEA44C0052E729 /* String+XML.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+XML.swift"; sourceTree = ""; }; 24B4DF0B1D6DFA370097803B /* RedundantNilCoalescingRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedundantNilCoalescingRule.swift; sourceTree = ""; }; 24E17F701B1481FF008195BE /* File+Cache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "File+Cache.swift"; sourceTree = ""; }; 2E02005E1C54BF680024D09D /* CyclomaticComplexityRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CyclomaticComplexityRule.swift; sourceTree = ""; }; @@ -660,6 +662,7 @@ E86396C41BADAC15002C9E88 /* XcodeReporter.swift */, 4A9A3A391DC1D75F00DF5183 /* HTMLReporter.swift */, 2E336D191DF08AF200CCFE77 /* EmojiReporter.swift */, + 1F8547131DFEA44C0052E729 /* String+XML.swift */, ); path = Reporters; sourceTree = ""; @@ -1059,6 +1062,7 @@ B2902A0E1D6681F700BFCCF7 /* PrivateUnitTestConfiguration.swift in Sources */, D47A510E1DB29EEB00A4CC21 /* SwitchCaseOnNewlineRule.swift in Sources */, D48AE2CC1DFB58C5001C6A4A /* AttributesRulesExamples.swift in Sources */, + 1F8547141DFEA44C0052E729 /* String+XML.swift in Sources */, E88DEA6F1B09843F00A66CB0 /* Location.swift in Sources */, 93E0C3CE1D67BD7F007FA25D /* ConditionalReturnsOnNewline.swift in Sources */, D43DB1081DC573DA00281215 /* ImplicitGetterRule.swift in Sources */,