Skip to content

Commit 40bb7a9

Browse files
committed
Fix wrong diagnostic parse typed pattern
1 parent 61cc73e commit 40bb7a9

File tree

3 files changed

+68
-10
lines changed

3 files changed

+68
-10
lines changed

Sources/SwiftParser/Patterns.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,12 @@ extension Parser {
175175
&& !self.currentToken.isAtStartOfLine
176176
&& lookahead.canParseType()
177177
{
178-
// Recovery if the user forgot to add ':'
179-
let result = self.parseResultType()
178+
let (unexpectedBeforeColon, colon) = self.expect(.colon)
179+
let result = self.parseType()
180+
180181
type = RawTypeAnnotationSyntax(
181-
colon: self.missingToken(.colon),
182+
unexpectedBeforeColon,
183+
colon: colon,
182184
type: result,
183185
arena: self.arena
184186
)

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,36 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
14141414
return .visitChildren
14151415
}
14161416

1417+
public override func visit(_ node: PatternBindingSyntax) -> SyntaxVisitorContinueKind {
1418+
if shouldSkip(node) {
1419+
return .skipChildren
1420+
}
1421+
1422+
if let identifierPattern = node.pattern.as(IdentifierPatternSyntax.self),
1423+
let unexpectedBeforeColon = node.typeAnnotation?.unexpectedBeforeColon,
1424+
let token = unexpectedBeforeColon.onlyToken(where: { $0.tokenKind.isIdentifier })
1425+
{
1426+
addDiagnostic(
1427+
unexpectedBeforeColon,
1428+
SpaceSeparatedIdentifiersError(
1429+
firstToken: identifierPattern.identifier,
1430+
additionalTokens: [token]
1431+
),
1432+
fixIts: [
1433+
FixIt(
1434+
message: .joinIdentifiers,
1435+
changes: [
1436+
FixIt.MultiNodeChange(.replaceTrailingTrivia(token: identifierPattern.identifier, newTrivia: []))
1437+
]
1438+
)
1439+
],
1440+
handledNodes: [unexpectedBeforeColon.id]
1441+
)
1442+
}
1443+
1444+
return .visitChildren
1445+
}
1446+
14171447
//==========================================================================//
14181448
// IMPORTANT: If you are tempted to add a `visit` method here, please //
14191449
// insert it in alphabetical order above //

Tests/SwiftParserTest/translated/RecoveryTests.swift

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -813,9 +813,9 @@ final class RecoveryTests: XCTestCase {
813813
assertParse(
814814
#"""
815815
struct SS 1️⃣SS : Multi {
816-
private var a 2️⃣b 3️⃣: Int = ""
816+
private var a 2️⃣b : Int = ""
817817
func f() {
818-
var c 4️⃣d = 5
818+
var c 3️⃣d = 5
819819
let _ = 0
820820
}
821821
}
@@ -828,16 +828,24 @@ final class RecoveryTests: XCTestCase {
828828
),
829829
DiagnosticSpec(
830830
locationMarker: "2️⃣",
831-
message: "expected ':' in type annotation",
832-
fixIts: ["insert ':'"]
831+
message: "found an unexpected second identifier in pattern; is there an accidental break?",
832+
fixIts: ["join the identifiers together"]
833833
),
834-
DiagnosticSpec(locationMarker: "3️⃣", message: #"unexpected code ': Int = ""' before function"#),
835834
DiagnosticSpec(
836-
locationMarker: "4️⃣",
835+
locationMarker: "3️⃣",
837836
message: "expected ':' in type annotation",
838837
fixIts: ["insert ':'"]
839838
),
840-
]
839+
],
840+
fixedSource: #"""
841+
struct SSSS : Multi {
842+
private var ab : Int = ""
843+
func f() {
844+
var c: d = 5
845+
let _ = 0
846+
}
847+
}
848+
"""#
841849
)
842850
}
843851

@@ -869,6 +877,24 @@ final class RecoveryTests: XCTestCase {
869877
)
870878
}
871879

880+
func testRecovery64c() {
881+
assertParse(
882+
"""
883+
private var a 1️⃣b : Int = ""
884+
""",
885+
diagnostics: [
886+
DiagnosticSpec(
887+
locationMarker: "1️⃣",
888+
message: "found an unexpected second identifier in pattern; is there an accidental break?",
889+
fixIts: ["join the identifiers together"]
890+
)
891+
],
892+
fixedSource: """
893+
private var ab : Int = ""
894+
"""
895+
)
896+
}
897+
872898
func testRecovery65() {
873899
assertParse(
874900
"""

0 commit comments

Comments
 (0)