Skip to content

Commit a633470

Browse files
committed
Improve diagnostic message if unexpected tokens are found at the start of a layout node
This helps us produce better error messages once we implement recovery in front of declarations.
1 parent f905feb commit a633470

File tree

5 files changed

+39
-31
lines changed

5 files changed

+39
-31
lines changed

Sources/SwiftParser/Diagnostics/ParserDiagnosticMessages.swift

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,20 @@ import SwiftSyntax
1616
let diagnosticDomain: String = "SwiftParser"
1717

1818
extension SyntaxProtocol {
19-
var nodeTypeNameForDiagnostics: String? {
19+
/// Return a name of this syntax node that can be used to describe it in
20+
/// diagnostics.
21+
/// Nodes that mostly exist for the syntax tree's structure and don't have a
22+
/// correspondence in the source code that's meeingful to the user by default
23+
/// use the name of the parent node that encloses it. Pass `false` to `inherit`
24+
/// to prevent this name inheritance.
25+
func nodeTypeNameForDiagnostics(inherit: Bool = true) -> String? {
2026
if let name = Syntax(self).as(SyntaxEnum.self).nameForDiagnostics {
2127
return name
2228
}
23-
if let parent = self.parent {
24-
return parent.nodeTypeNameForDiagnostics
29+
if inherit {
30+
if let parent = self.parent {
31+
return parent.nodeTypeNameForDiagnostics(inherit: inherit)
32+
}
2533
}
2634
return nil
2735
}
@@ -118,7 +126,7 @@ public struct MissingTokenError: ParserError {
118126
public let missingToken: TokenSyntax
119127

120128
public var message: String {
121-
guard let parent = missingToken.parent, let parentTypeName = parent.nodeTypeNameForDiagnostics else {
129+
guard let parent = missingToken.parent, let parentTypeName = parent.nodeTypeNameForDiagnostics() else {
122130
return "Expected '\(missingToken.text)'"
123131
}
124132
switch missingToken.tokenKind {
@@ -141,17 +149,17 @@ public struct UnexpectedNodesError: ParserError {
141149
public let unexpectedNodes: UnexpectedNodesSyntax
142150

143151
public var message: String {
144-
let parentTypeName = unexpectedNodes.parent?.nodeTypeNameForDiagnostics
145-
let shortContent = unexpectedNodes.contentForDiagnosticsIfShortSingleLine
146-
switch (parentTypeName, shortContent) {
147-
case (let parentTypeName?, let shortContent?):
148-
return "Unexpected text '\(shortContent)' found in \(parentTypeName)"
149-
case (let parentTypeName?, nil):
150-
return "Unexpected text found in \(parentTypeName)"
151-
case (nil, let shortContent?):
152-
return "Unexpected text '\(shortContent)'"
153-
case (nil, nil):
154-
return "Unexpected text"
152+
var message = "Unexpected text"
153+
if let shortContent = unexpectedNodes.contentForDiagnosticsIfShortSingleLine {
154+
message += " '\(shortContent)'"
155+
}
156+
if let parent = unexpectedNodes.parent {
157+
if let parentTypeName = parent.nodeTypeNameForDiagnostics(inherit: false), parent.children(viewMode: .sourceAccurate).first?.id == unexpectedNodes.id {
158+
message += " before \(parentTypeName)"
159+
} else if let parentTypeName = parent.nodeTypeNameForDiagnostics() {
160+
message += " in \(parentTypeName)"
161+
}
155162
}
163+
return message
156164
}
157165
}

Tests/SwiftParserTest/Declarations.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ final class DeclarationTests: XCTestCase {
381381
"(first second #^DIAG^#third fourth: Int)",
382382
{ $0.parseFunctionSignature() },
383383
diagnostics: [
384-
DiagnosticSpec(message: "Unexpected text 'third fourth' found in function parameter")
384+
DiagnosticSpec(message: "Unexpected text 'third fourth' in function parameter")
385385
]
386386
)
387387
}
@@ -523,7 +523,7 @@ final class DeclarationTests: XCTestCase {
523523
diagnostics: [
524524
DiagnosticSpec(
525525
message: """
526-
Unexpected text '/ ###line 25 "line-directive.swift"' found in struct
526+
Unexpected text '/ ###line 25 "line-directive.swift"' in struct
527527
"""
528528
)
529529
]
@@ -538,7 +538,7 @@ final class DeclarationTests: XCTestCase {
538538
}
539539
""",
540540
diagnostics: [
541-
DiagnosticSpec(message: "Unexpected text 'bogus rethrows set' found in variable")
541+
DiagnosticSpec(message: "Unexpected text 'bogus rethrows set' in variable")
542542
]
543543
)
544544
}
@@ -570,7 +570,7 @@ final class DeclarationTests: XCTestCase {
570570
trailingComma: nil
571571
)),
572572
diagnostics: [
573-
DiagnosticSpec(message: "Unexpected text 'third' found in function parameter")
573+
DiagnosticSpec(message: "Unexpected text 'third' in function parameter")
574574
]
575575
)
576576
}
@@ -591,7 +591,7 @@ final class DeclarationTests: XCTestCase {
591591
trailingComma: nil
592592
)),
593593
diagnostics: [
594-
DiagnosticSpec(message: "Unexpected text 'third fourth' found in function parameter")
594+
DiagnosticSpec(message: "Unexpected text 'third fourth' in function parameter")
595595
]
596596
)
597597
}
@@ -642,7 +642,7 @@ final class DeclarationTests: XCTestCase {
642642
trailingComma: nil
643643
)),
644644
diagnostics: [
645-
DiagnosticSpec(message: "Unexpected text '[third fourth]' found in function parameter")
645+
DiagnosticSpec(message: "Unexpected text '[third fourth]' in function parameter")
646646
]
647647
)
648648
}
@@ -667,7 +667,7 @@ final class DeclarationTests: XCTestCase {
667667
diagnostics: [
668668
DiagnosticSpec(locationMarker: "COLON", message: "Expected ':' in function parameter"),
669669
DiagnosticSpec(locationMarker: "END_ARRAY" , message: "Expected ']' to end array type"),
670-
DiagnosticSpec(locationMarker: "END_ARRAY", message: "Unexpected text 'fourth: Int' found in parameter clause")
670+
DiagnosticSpec(locationMarker: "END_ARRAY", message: "Unexpected text 'fourth: Int' in parameter clause")
671671
]
672672
)
673673
}

Tests/SwiftParserTest/Expressions.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ final class ExpressionTests: XCTestCase {
202202
" >> \( abc #^DIAG^#} ) << "
203203
"""#,
204204
diagnostics: [
205-
DiagnosticSpec(message: "Unexpected text '}' found in string literal")
205+
DiagnosticSpec(message: "Unexpected text '}' in string literal")
206206
]
207207
)
208208

@@ -419,7 +419,7 @@ final class ExpressionTests: XCTestCase {
419419
"[(Int) -> #^DIAG^#throws Int]()",
420420
diagnostics: [
421421
// FIXME: We should suggest to move 'throws' in front of '->'
422-
DiagnosticSpec(message: "Unexpected text 'throws Int' found in array")
422+
DiagnosticSpec(message: "Unexpected text 'throws Int' in array")
423423
]
424424
)
425425

@@ -449,7 +449,7 @@ final class ExpressionTests: XCTestCase {
449449
let :(#^DIAG_1^#..)->
450450
""",
451451
diagnostics: [
452-
DiagnosticSpec(locationMarker: "DIAG_1", message: "Unexpected text '..' found in function type"),
452+
DiagnosticSpec(locationMarker: "DIAG_1", message: "Unexpected text '..' in function type"),
453453
]
454454
)
455455
}

Tests/SwiftParserTest/Statements.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ final class StatementTests: XCTestCase {
1414
""",
1515
diagnostics: [
1616
DiagnosticSpec(message: "Expected '=' in pattern matching"),
17-
DiagnosticSpec(message: "Unexpected text '* ! = x' found in 'if' statement"),
17+
DiagnosticSpec(message: "Unexpected text '* ! = x' in 'if' statement"),
1818
]
1919
)
2020
}
@@ -158,8 +158,8 @@ final class StatementTests: XCTestCase {
158158
}
159159
""",
160160
diagnostics: [
161-
DiagnosticSpec(locationMarker: "TEST_1", message: "Unexpected text '@s return' found in function"),
162-
DiagnosticSpec(locationMarker: "TEST_2", message: "Unexpected text '@unknown return' found in function")
161+
DiagnosticSpec(locationMarker: "TEST_1", message: "Unexpected text '@s return' in function"),
162+
DiagnosticSpec(locationMarker: "TEST_2", message: "Unexpected text '@unknown return' in function")
163163
]
164164
)
165165
}
@@ -177,7 +177,7 @@ final class StatementTests: XCTestCase {
177177
}
178178
""",
179179
diagnostics: [
180-
DiagnosticSpec(message: "Unexpected text found in 'switch' statement"),
180+
DiagnosticSpec(message: "Unexpected text in 'switch' statement"),
181181

182182
]
183183
)
@@ -197,7 +197,7 @@ final class StatementTests: XCTestCase {
197197
}
198198
""",
199199
diagnostics: [
200-
DiagnosticSpec(message: "Unexpected text found in 'switch' statement")
200+
DiagnosticSpec(message: "Unexpected text in 'switch' statement")
201201
]
202202
)
203203
}

Tests/SwiftParserTest/Types.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ final class TypeTests: XCTestCase {
2929

3030
func testFunctionTypes() throws {
3131
AssertParse("t as(#^DIAG^#..)->", diagnostics: [
32-
DiagnosticSpec(message: "Unexpected text '..' found in function type")
32+
DiagnosticSpec(message: "Unexpected text '..' in function type")
3333
])
3434
}
3535
}

0 commit comments

Comments
 (0)