Skip to content

Commit 2d964e4

Browse files
authored
Merge pull request #962 from TTOzzi/unicode-exception
Unify whitespace handling in linter and formatter
2 parents c41363d + 57ec53b commit 2d964e4

File tree

4 files changed

+59
-15
lines changed

4 files changed

+59
-15
lines changed

Sources/SwiftFormat/PrettyPrint/Comment.swift

+20-6
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,27 @@ extension StringProtocol {
2121
/// - Returns: The string with trailing whitespace removed.
2222
func trimmingTrailingWhitespace() -> String {
2323
if isEmpty { return String() }
24-
let scalars = unicodeScalars
25-
var idx = scalars.index(before: scalars.endIndex)
26-
while scalars[idx].properties.isWhitespace {
27-
if idx == scalars.startIndex { return String() }
28-
idx = scalars.index(before: idx)
24+
let utf8Array = Array(utf8)
25+
var idx = utf8Array.endIndex - 1
26+
while utf8Array[idx].isWhitespace {
27+
if idx == utf8Array.startIndex { return String() }
28+
idx -= 1
29+
}
30+
return String(decoding: utf8Array[...idx], as: UTF8.self)
31+
}
32+
}
33+
34+
extension UTF8.CodeUnit {
35+
/// Checks if the UTF-8 code unit represents a whitespace character.
36+
///
37+
/// - Returns: `true` if the code unit represents a whitespace character, otherwise `false`.
38+
var isWhitespace: Bool {
39+
switch self {
40+
case UInt8(ascii: " "), UInt8(ascii: "\n"), UInt8(ascii: "\t"), UInt8(ascii: "\r"), /*VT*/ 0x0B, /*FF*/ 0x0C:
41+
return true
42+
default:
43+
return false
2944
}
30-
return String(String.UnicodeScalarView(scalars[...idx]))
3145
}
3246
}
3347

Sources/SwiftFormat/PrettyPrint/WhitespaceLinter.swift

+1-9
Original file line numberDiff line numberDiff line change
@@ -339,16 +339,8 @@ public class WhitespaceLinter {
339339
startingAt offset: Int,
340340
in data: [UTF8.CodeUnit]
341341
) -> ArraySlice<UTF8.CodeUnit> {
342-
func isWhitespace(_ char: UTF8.CodeUnit) -> Bool {
343-
switch char {
344-
case UInt8(ascii: " "), UInt8(ascii: "\n"), UInt8(ascii: "\t"), UInt8(ascii: "\r"), /*VT*/ 0x0B, /*FF*/ 0x0C:
345-
return true
346-
default:
347-
return false
348-
}
349-
}
350342
guard
351-
let whitespaceEnd = data[offset...].firstIndex(where: { !isWhitespace($0) })
343+
let whitespaceEnd = data[offset...].firstIndex(where: { !$0.isWhitespace })
352344
else {
353345
return data[offset..<data.endIndex]
354346
}

Tests/SwiftFormatTests/PrettyPrint/CommentTests.swift

+13
Original file line numberDiff line numberDiff line change
@@ -1094,4 +1094,17 @@ final class CommentTests: PrettyPrintTestCase {
10941094

10951095
assertPrettyPrintEqual(input: input, expected: input, linelength: 80)
10961096
}
1097+
1098+
func testUnexpectedUnicodeCharacters() {
1099+
let input =
1100+
"""
1101+
// Hello World\u{2028}
1102+
// Hello\u{20}\u{2028}World
1103+
// Hello World\u{2028}\u{2029}\u{2029}
1104+
// Hello World\u{20}\u{20}\u{20}\u{2028}
1105+
1106+
"""
1107+
1108+
assertPrettyPrintEqual(input: input, expected: input, linelength: 80)
1109+
}
10971110
}

Tests/SwiftFormatTests/PrettyPrint/WhitespaceLintTests.swift

+25
Original file line numberDiff line numberDiff line change
@@ -255,4 +255,29 @@ final class WhitespaceLintTests: WhitespaceTestCase {
255255
]
256256
)
257257
}
258+
259+
func testUnexpectedUnicodeCharacters() {
260+
assertWhitespaceLint(
261+
input: """
262+
// Hello World\u{2028}
263+
// Hello\u{20}\u{2028}World
264+
// Hello World\u{2028}\u{2029}\u{2029}
265+
// Hello World \u{2028}
266+
// Hello World\u{2028}1️⃣\u{20}\u{20}\u{20}
267+
268+
""",
269+
expected: """
270+
// Hello World\u{2028}
271+
// Hello\u{20}\u{2028}World
272+
// Hello World\u{2028}\u{2029}\u{2029}
273+
// Hello World \u{2028}
274+
// Hello World\u{2028}
275+
276+
""",
277+
linelength: 30,
278+
findings: [
279+
FindingSpec("1️⃣", message: "remove trailing whitespace")
280+
]
281+
)
282+
}
258283
}

0 commit comments

Comments
 (0)