diff --git a/Sources/SwiftFormat/PrettyPrint/PrettyPrintBuffer.swift b/Sources/SwiftFormat/PrettyPrint/PrettyPrintBuffer.swift index 4b02d372..e82b4ed3 100644 --- a/Sources/SwiftFormat/PrettyPrint/PrettyPrintBuffer.swift +++ b/Sources/SwiftFormat/PrettyPrint/PrettyPrintBuffer.swift @@ -119,18 +119,21 @@ struct PrettyPrintBuffer { consecutiveNewlineCount = 0 pendingSpaces = 0 - // In case of comments, we may get a multi-line string. - // To account for that case, we need to correct the lineNumber count. - // The new column is only the position within the last line. - let lines = text.split(separator: "\n") - lineNumber += lines.count - 1 - if lines.count > 1 { - // in case we have inserted new lines, we need to reset the column - column = lines.last?.count ?? 0 - } else { - // in case it is an end of line comment or a single line comment, - // we just add to the current column - column += lines.last?.count ?? 0 + guard let lastNewlineIndex = text.lastIndex(of: "\n") else { + // In case there's no newline, the string itself is the only line + column += text.count + return + } + + let lastLine = text[lastNewlineIndex...] + column += lastLine.count + + // Now count the rest of the lines in a possible multi-line string. We are only interested in '\n' so we can use + // the UTF8 view and skip grapheme clustering entirely. + for element in text[...lastNewlineIndex].utf8 { + if element == UInt8(ascii: "\n") { + lineNumber += 1 + } } } diff --git a/Tests/SwiftFormatTests/PrettyPrint/LineNumbersTests.swift b/Tests/SwiftFormatTests/PrettyPrint/LineNumbersTests.swift index 1bb58f7a..a8195640 100644 --- a/Tests/SwiftFormatTests/PrettyPrint/LineNumbersTests.swift +++ b/Tests/SwiftFormatTests/PrettyPrint/LineNumbersTests.swift @@ -81,4 +81,38 @@ final class LineNumbersTests: PrettyPrintTestCase { ] ) } + + func testCharacterVsCodepoint() { + let input = + """ + let fo = 1 // 🤥 + + """ + + assertPrettyPrintEqual( + input: input, + expected: input, + linelength: 16, + whitespaceOnly: true, + findings: [] + ) + } + + func testCharacterVsCodepointMultiline() { + let input = + #""" + /// This is a multiline + /// comment that is in 🤥 + /// fact perfectly sized + + """# + + assertPrettyPrintEqual( + input: input, + expected: input, + linelength: 25, + whitespaceOnly: true, + findings: [] + ) + } }