Skip to content

Commit 60c7037

Browse files
committed
Change trivia attribution rule to make comments trailing trivia unless separated by a newline
This changes the trivia attribution rule in the new parser to consider all trivia up to the next newline as trailing trivia. Previously, comments were always considered trailing trivia. This was discussed last year in https://forums.swift.org/t/changing-comment-trivia-attribution-from-trailing-trivia-to-leading-trivia/50773. My idea is that right now is probably one of the best times to change this because switching from the old to the new parser is an active source change for all clients. Resolves rdar://68234477 Resolves rdar://95639215 Fixes #438
1 parent add30e7 commit 60c7037

File tree

6 files changed

+167
-105
lines changed

6 files changed

+167
-105
lines changed

Sources/SwiftParser/Diagnostics/MissingNodesError.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,16 @@ fileprivate enum NodesDescriptionPart {
2828

2929
func description(format: Bool) -> String? {
3030
switch self {
31-
case .tokensWithDefaultText(let tokens):
32-
let tokenContents: String
31+
case .tokensWithDefaultText(var tokens):
3332
if format {
34-
tokenContents = tokens.map({ BasicFormat().visit($0).description }).joined()
35-
} else {
36-
tokenContents = tokens.map(\.description).joined()
33+
tokens = tokens.map({ BasicFormat().visit($0) })
34+
}
35+
if !tokens.isEmpty {
36+
tokens[0] = tokens[0].withLeadingTrivia([])
37+
tokens[tokens.count - 1] = tokens[tokens.count - 1].withTrailingTrivia([])
3738
}
38-
return "'\(tokenContents.trimmingWhitespace())'"
39+
let tokenContents = tokens.map(\.description).joined()
40+
return "'\(tokenContents)'"
3941
case .tokenWithoutDefaultText(let token):
4042
if let childName = token.childNameInParent {
4143
return childName

Sources/SwiftParser/Lexer.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -921,10 +921,6 @@ extension Lexer.Cursor {
921921
guard !self.isAtEndOfFile else {
922922
break
923923
}
924-
if case .trailing = position {
925-
// Don't lex comments as trailing trivia (for now).
926-
break
927-
}
928924

929925
switch self.peek() {
930926
case UInt8(ascii: "/"):

Tests/SwiftParserTest/Assertions.swift

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,30 @@ func AssertEqualTokens(_ actual: [Lexer.Lexeme], _ expected: [Lexer.Lexeme], fil
2727
}
2828

2929
guard l.leadingTriviaText == r.leadingTriviaText else {
30-
return XCTFail("""
31-
Token at index \(idx) does not have matching leading trivia! \
32-
\(l.leadingTriviaText.debugDescription) != \(r.leadingTriviaText.debugDescription)
33-
""", file: file, line: line)
30+
return FailStringsEqualWithDiff(
31+
String(syntaxText: l.leadingTriviaText),
32+
String(syntaxText: r.leadingTriviaText),
33+
"Token at index \(idx) does not have matching leading trivia",
34+
file: file, line: line
35+
)
3436
}
3537

36-
guard l.tokenText == r.tokenText else {
37-
return XCTFail("""
38-
Text at index \(idx) does not have matching text! \
39-
\(l.tokenText.debugDescription) != \(r.tokenText.debugDescription)"
40-
""", file: file, line: line)
38+
guard l.tokenText.debugDescription == r.tokenText.debugDescription else {
39+
return FailStringsEqualWithDiff(
40+
l.tokenText.debugDescription,
41+
r.tokenText.debugDescription,
42+
"Text at index \(idx) does not have matching text",
43+
file: file, line: line
44+
)
4145
}
4246

4347
guard l.trailingTriviaText == r.trailingTriviaText else {
44-
return XCTFail("""
45-
Token at index \(idx) does not have matching trailing trivia! \
46-
\(l.trailingTriviaText.debugDescription) != \(r.trailingTriviaText.debugDescription)
47-
""", file: file, line: line)
48+
return FailStringsEqualWithDiff(
49+
String(syntaxText: l.trailingTriviaText),
50+
String(syntaxText: r.trailingTriviaText),
51+
"Token at index \(idx) does not have matching trailing trivia",
52+
file: file, line: line
53+
)
4854
}
4955
}
5056
}

Tests/SwiftParserTest/ClassificationTests.swift

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import SwiftParser
55
public class ClassificationTests: XCTestCase {
66

77
public func testClassification() {
8-
let source = "// blah.\nlet x/*yo*/ = 0"
8+
let source = """
9+
// blah.
10+
let x/*yo*/ = 0
11+
"""
912
let tree = Parser.parse(source: source)
1013
do {
1114
let classif = Array(tree.classifications)
@@ -56,28 +59,28 @@ public class ClassificationTests: XCTestCase {
5659
return
5760
}
5861
XCTAssertEqual(classif[0].kind, .none)
59-
XCTAssertEqual(classif[0].range, ByteSourceRange(offset: 20, length: 3))
62+
XCTAssertEqual(classif[0].range, ByteSourceRange(offset: 21, length: 2))
6063
}
6164
do {
62-
let initializer = (tree.statements[0].item.as(VariableDeclSyntax.self)!).bindings[0].initializer!
63-
XCTAssertEqual(initializer.description, "/*yo*/ = 0")
65+
let pattern = (tree.statements[0].item.as(VariableDeclSyntax.self)!).bindings[0].pattern
66+
XCTAssertEqual(pattern.description, "x/*yo*/ ")
6467
// Classify with a relative range inside this node.
65-
let classif = Array(initializer.classifications(in: ByteSourceRange(offset: 5, length: 2)))
68+
let classif = Array(pattern.classifications(in: ByteSourceRange(offset: 5, length: 2)))
6669
XCTAssertEqual(classif.count, 2)
6770
guard classif.count == 2 else {
6871
return
6972
}
7073
XCTAssertEqual(classif[0].kind, .blockComment)
7174
XCTAssertEqual(classif[0].range, ByteSourceRange(offset: 14, length: 6))
7275
XCTAssertEqual(classif[1].kind, .none)
73-
XCTAssertEqual(classif[1].range, ByteSourceRange(offset: 20, length: 3))
76+
XCTAssertEqual(classif[1].range, ByteSourceRange(offset: 20, length: 1))
7477

7578
do {
76-
let singleClassif = initializer.classification(at: 5)
79+
let singleClassif = pattern.classification(at: 5)
7780
XCTAssertEqual(singleClassif, classif[0])
7881
}
7982
do {
80-
let singleClassif = initializer.classification(at: AbsolutePosition(utf8Offset: 19))
83+
let singleClassif = pattern.classification(at: AbsolutePosition(utf8Offset: 19))
8184
XCTAssertEqual(singleClassif, classif[0])
8285
}
8386
}

0 commit comments

Comments
 (0)