Skip to content

Commit cdccc72

Browse files
committed
In nodesDescription only merge tokens if they occur consecutively in the source code
This was motiviated by the following discussion, where the issue becomes more apparent: #1643 (comment).
1 parent b36fbc3 commit cdccc72

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

Sources/SwiftParserDiagnostics/MissingNodesError.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,12 @@ fileprivate enum NodesDescriptionPart {
6767
}
6868

6969
static func descriptionParts(for nodes: some Sequence<Syntax>) -> [NodesDescriptionPart] {
70+
// For each token that we modified (e.g. made it present), map to the original token in `nodes`
71+
var originalTokens: [TokenSyntax: TokenSyntax] = [:]
72+
73+
// Accumulates the result
7074
var parts: [NodesDescriptionPart] = []
75+
7176
for missingNode in nodes {
7277
if let token = missingNode.as(TokenSyntax.self) {
7378
let newPart: NodesDescriptionPart
@@ -77,10 +82,12 @@ fileprivate enum NodesDescriptionPart {
7782
let (rawKind, text) = token.tokenKind.decomposeToRaw()
7883
if let text = text, !text.isEmpty {
7984
let presentToken = token.with(\.presence, .present)
85+
originalTokens[presentToken] = token
8086
newPart = .tokensWithDefaultText([presentToken])
8187
} else if let defaultText = rawKind.defaultText {
8288
let newKind = TokenKind.fromRaw(kind: rawKind, text: String(syntaxText: defaultText))
8389
let presentToken = token.with(\.tokenKind, newKind).with(\.presence, .present)
90+
originalTokens[presentToken] = token
8491
newPart = .tokensWithDefaultText([presentToken])
8592
} else {
8693
newPart = .tokenWithoutDefaultText(token)
@@ -89,7 +96,15 @@ fileprivate enum NodesDescriptionPart {
8996

9097
switch (parts.last, newPart) {
9198
case (.tokensWithDefaultText(let previousTokens), .tokensWithDefaultText(let newTokens)):
92-
parts[parts.count - 1] = .tokensWithDefaultText(previousTokens + newTokens)
99+
// Merge `tokensWithDefaultText` if they occur consecutively in the tree
100+
if let lastPrevious = previousTokens.last,
101+
let firstNew = newTokens.first,
102+
originalTokens[lastPrevious, default: lastPrevious].nextToken(viewMode: .all) == originalTokens[firstNew, default: firstNew]
103+
{
104+
parts[parts.count - 1] = .tokensWithDefaultText(previousTokens + newTokens)
105+
} else {
106+
parts.append(newPart)
107+
}
93108
default:
94109
parts.append(newPart)
95110
}

Tests/SwiftParserTest/translated/RecoveryTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,7 +1989,7 @@ final class RecoveryTests: XCTestCase {
19891989
diagnostics: [
19901990
DiagnosticSpec(
19911991
message: "expected ':' to begin inheritance clause",
1992-
fixIts: ["replace '()' with ':'"]
1992+
fixIts: ["replace '(' and ')' with ':'"]
19931993
)
19941994
],
19951995
fixedSource: """
@@ -2006,7 +2006,7 @@ final class RecoveryTests: XCTestCase {
20062006
diagnostics: [
20072007
DiagnosticSpec(
20082008
message: "expected ':' to begin inheritance clause",
2009-
fixIts: ["replace '()' with ':'"]
2009+
fixIts: ["replace '(' and ')' with ':'"]
20102010
)
20112011
],
20122012
fixedSource: """
@@ -2023,7 +2023,7 @@ final class RecoveryTests: XCTestCase {
20232023
diagnostics: [
20242024
DiagnosticSpec(
20252025
message: "expected ':' to begin inheritance clause",
2026-
fixIts: ["replace '()' with ':'"]
2026+
fixIts: ["replace '(' and ')' with ':'"]
20272027
)
20282028
],
20292029
fixedSource: """
@@ -2040,7 +2040,7 @@ final class RecoveryTests: XCTestCase {
20402040
diagnostics: [
20412041
DiagnosticSpec(
20422042
message: "expected ':' to begin inheritance clause",
2043-
fixIts: ["replace '()' with ':'"]
2043+
fixIts: ["replace '(' and ')' with ':'"]
20442044
)
20452045
],
20462046
fixedSource: """
@@ -2057,7 +2057,7 @@ final class RecoveryTests: XCTestCase {
20572057
diagnostics: [
20582058
DiagnosticSpec(
20592059
message: "expected ':' to begin inheritance clause",
2060-
fixIts: ["replace '()' with ':'"]
2060+
fixIts: ["replace '(' and ')' with ':'"]
20612061
)
20622062
],
20632063
fixedSource: """

0 commit comments

Comments
 (0)