Skip to content

Commit 6e4416a

Browse files
committed
Diagnose using line & col of formatted text in PrettyPrinter.
The PrettyPrinter was using `AbsolutePosition`s from the TokenStreamCreator when creating diagnostics. Those are based on a utf8 offset, which is invalidated when the PrettyPrinter adds/removes content from the text while printing it. Instead, the diagnostics from the PrettyPrinter use a line and column computed based on its output buffer. I removed all instances of storing `AbsolutePosition` from TokenStreamCreator, since using `AbsolutePosition` in PrettyPrinter is inherently flawed.
1 parent 6dc8fc2 commit 6e4416a

File tree

6 files changed

+22
-26
lines changed

6 files changed

+22
-26
lines changed

Sources/SwiftFormatPrettyPrint/Comment.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@ struct Comment {
4040

4141
let kind: Kind
4242
var text: [String]
43-
let position: AbsolutePosition?
4443
public var length: Int
4544

46-
init(kind: Kind, text: String, position: AbsolutePosition? = nil) {
45+
init(kind: Kind, text: String) {
4746
self.kind = kind
48-
self.position = position
4947

5048
switch kind {
5149
case .line, .docLine:

Sources/SwiftFormatPrettyPrint/PrettyPrint.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ public class PrettyPrinter {
435435
write(comment.print(indent: currentIndentation))
436436
if wasEndOfLine {
437437
if comment.length > spaceRemaining {
438-
diagnose(.moveEndOfLineComment, at: comment.position)
438+
diagnose(.moveEndOfLineComment)
439439
}
440440
} else {
441441
spaceRemaining -= comment.length
@@ -459,21 +459,22 @@ public class PrettyPrinter {
459459
case .commaDelimitedRegionStart:
460460
commaDelimitedRegionStack.append(openCloseBreakCompensatingLineNumber)
461461

462-
case .commaDelimitedRegionEnd(let hasTrailingComma, let position):
462+
case .commaDelimitedRegionEnd(let hasTrailingComma):
463463
guard let startLineNumber = commaDelimitedRegionStack.popLast() else {
464464
fatalError("Found trailing comma end with no corresponding start.")
465465
}
466466

467467
let shouldHaveTrailingComma = startLineNumber != openCloseBreakCompensatingLineNumber
468468
if shouldHaveTrailingComma && !hasTrailingComma {
469-
diagnose(.addTrailingComma, at: position)
469+
diagnose(.addTrailingComma)
470470
} else if !shouldHaveTrailingComma && hasTrailingComma {
471-
diagnose(.removeTrailingComma, at: position)
471+
diagnose(.removeTrailingComma)
472472
}
473473

474474
let shouldWriteComma = whitespaceOnly ? hasTrailingComma : shouldHaveTrailingComma
475475
if shouldWriteComma {
476476
write(",")
477+
spaceRemaining -= 1
477478
}
478479
}
479480
}
@@ -679,14 +680,13 @@ public class PrettyPrinter {
679680
}
680681
}
681682

682-
private func diagnose(_ message: Diagnostic.Message, at position: AbsolutePosition?) {
683-
let location: SourceLocation?
684-
if let position = position {
685-
location
686-
= SourceLocation(offset: position.utf8Offset, converter: context.sourceLocationConverter)
687-
} else {
688-
location = nil
689-
}
683+
/// Diagnoses the given message at the current location in `outputBuffer`.
684+
private func diagnose(_ message: Diagnostic.Message) {
685+
// Add 1 since columns uses 1-based indices.
686+
let column = maxLineLength - spaceRemaining + 1
687+
let offset = outputBuffer.utf8.count
688+
let location =
689+
SourceLocation(line: lineNumber, column: column, offset: offset, file: context.fileURL.path)
690690
context.diagnosticEngine?.diagnose(message, location: location)
691691
}
692692
}

Sources/SwiftFormatPrettyPrint/Token.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ enum Token {
177177

178178
/// Marks the end of a comma delimited collection, where a trailing comma should be inserted
179179
/// if and only if the collection spans multiple lines.
180-
case commaDelimitedRegionEnd(hasTrailingComma: Bool, position: AbsolutePosition)
180+
case commaDelimitedRegionEnd(hasTrailingComma: Bool)
181181

182182
// Convenience overloads for the enum types
183183
static let open = Token.open(.inconsistent, 0)

Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -714,8 +714,8 @@ private final class TokenStreamCreator: SyntaxVisitor {
714714
// a trailing comma to 1 element arrays.
715715
if let firstElement = node.first, let lastElement = node.last, firstElement != lastElement {
716716
before(firstElement.firstToken, tokens: .commaDelimitedRegionStart)
717-
let endToken = Token.commaDelimitedRegionEnd(
718-
hasTrailingComma: lastElement.trailingComma != nil, position: lastElement.endPosition)
717+
let endToken =
718+
Token.commaDelimitedRegionEnd(hasTrailingComma: lastElement.trailingComma != nil)
719719
after(lastElement.lastToken, tokens: endToken)
720720
if let existingTrailingComma = lastElement.trailingComma {
721721
ignoredTokens.insert(existingTrailingComma)
@@ -745,8 +745,8 @@ private final class TokenStreamCreator: SyntaxVisitor {
745745
// so we never add a trailing comma to 1 element dictionaries.
746746
if let firstElement = node.first, let lastElement = node.last, firstElement != lastElement {
747747
before(firstElement.firstToken, tokens: .commaDelimitedRegionStart)
748-
let endToken = Token.commaDelimitedRegionEnd(
749-
hasTrailingComma: lastElement.trailingComma != nil, position: lastElement.endPosition)
748+
let endToken =
749+
Token.commaDelimitedRegionEnd(hasTrailingComma: lastElement.trailingComma != nil)
750750
after(lastElement.lastToken, tokens: endToken)
751751
if let existingTrailingComma = lastElement.trailingComma {
752752
ignoredTokens.insert(existingTrailingComma)
@@ -2320,15 +2320,13 @@ private final class TokenStreamCreator: SyntaxVisitor {
23202320
return (false, [])
23212321
}
23222322

2323-
let position = token.endPosition
2324-
23252323
switch firstPiece {
23262324
case .lineComment(let text):
23272325
return (
23282326
true,
23292327
[
23302328
.space(size: 2, flexible: true),
2331-
.comment(Comment(kind: .line, text: text, position: position), wasEndOfLine: true),
2329+
.comment(Comment(kind: .line, text: text), wasEndOfLine: true),
23322330
// There must be a break with a soft newline after the comment, but it's impossible to
23332331
// know which kind of break must be used. Adding this newline is deferred until the
23342332
// comment is added to the token stream.
@@ -2339,7 +2337,7 @@ private final class TokenStreamCreator: SyntaxVisitor {
23392337
false,
23402338
[
23412339
.space(size: 1, flexible: true),
2342-
.comment(Comment(kind: .block, text: text, position: position), wasEndOfLine: false),
2340+
.comment(Comment(kind: .block, text: text), wasEndOfLine: false),
23432341
// We place a size-0 break after the comment to allow a discretionary newline after
23442342
// the comment if the user places one here but the comment is otherwise adjacent to a
23452343
// text token.

Tests/SwiftFormatPrettyPrintTests/ArrayDeclTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public class ArrayDeclTests: PrettyPrintTestCase {
109109
assertPrettyPrintEqual(
110110
input: input, expected: input + "\n", linelength: 45, whitespaceOnly: true)
111111

112-
XCTAssertDiagnosed(Diagnostic.Message.removeTrailingComma, line: 1, column: 18)
112+
XCTAssertDiagnosed(Diagnostic.Message.removeTrailingComma, line: 1, column: 17)
113113
XCTAssertDiagnosed(Diagnostic.Message.addTrailingComma, line: 4, column: 26)
114114
}
115115
}

Tests/SwiftFormatPrettyPrintTests/DictionaryDeclTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public class DictionaryDeclTests: PrettyPrintTestCase {
9292
assertPrettyPrintEqual(
9393
input: input, expected: input + "\n", linelength: 50, whitespaceOnly: true)
9494

95-
XCTAssertDiagnosed(Diagnostic.Message.removeTrailingComma, line: 1, column: 33)
95+
XCTAssertDiagnosed(Diagnostic.Message.removeTrailingComma, line: 1, column: 32)
9696
XCTAssertDiagnosed(Diagnostic.Message.addTrailingComma, line: 4, column: 17)
9797
}
9898
}

0 commit comments

Comments
 (0)