Skip to content

Commit d6e54c8

Browse files
authored
Merge pull request #1513 from kimdv/kimdv/add-diagnostic-for-testRecovery177
Add diagnostic for wrong where requirements separation
2 parents 5ebe104 + f317af1 commit d6e54c8

File tree

4 files changed

+53
-4
lines changed

4 files changed

+53
-4
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,9 +759,21 @@ extension Parser {
759759
}
760760

761761
keepGoing = self.consume(if: .comma)
762+
let unexpectedBetweenBodyAndTrailingComma: RawUnexpectedNodesSyntax?
763+
764+
// If there's a comma, keep parsing the list.
765+
// If there's a "&&", diagnose replace with a comma and keep parsing
766+
if let token = self.consumeIfContextualPunctuator("&&") {
767+
keepGoing = self.missingToken(.comma)
768+
unexpectedBetweenBodyAndTrailingComma = RawUnexpectedNodesSyntax([token], arena: self.arena)
769+
} else {
770+
unexpectedBetweenBodyAndTrailingComma = nil
771+
}
772+
762773
elements.append(
763774
RawGenericRequirementSyntax(
764775
body: requirement,
776+
unexpectedBetweenBodyAndTrailingComma,
765777
trailingComma: keepGoing,
766778
arena: self.arena
767779
)

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,38 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
542542
return handleEffectSpecifiers(node)
543543
}
544544

545+
public override func visit(_ node: GenericRequirementSyntax) -> SyntaxVisitorContinueKind {
546+
if shouldSkip(node) {
547+
return .skipChildren
548+
}
549+
550+
if let unexpected = node.unexpectedBetweenBodyAndTrailingComma,
551+
let token = unexpected.tokens(satisfying: { $0.tokenKind == .binaryOperator("&&") }).first,
552+
let trailingComma = node.trailingComma,
553+
trailingComma.presence == .missing,
554+
let previous = node.unexpectedBetweenBodyAndTrailingComma?.previousToken(viewMode: .sourceAccurate)
555+
{
556+
557+
addDiagnostic(
558+
unexpected,
559+
.expectedCommaInWhereClause,
560+
fixIts: [
561+
FixIt(
562+
message: ReplaceTokensFixIt(replaceTokens: [token], replacement: .commaToken()),
563+
changes: [
564+
.makeMissing(token),
565+
.makePresent(trailingComma),
566+
FixIt.MultiNodeChange(.replaceTrailingTrivia(token: previous, newTrivia: [])),
567+
]
568+
)
569+
],
570+
handledNodes: [unexpected.id, trailingComma.id]
571+
)
572+
}
573+
574+
return .visitChildren
575+
}
576+
545577
public override func visit(_ node: DeinitializerDeclSyntax) -> SyntaxVisitorContinueKind {
546578
if shouldSkip(node) {
547579
return .skipChildren

Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ extension DiagnosticMessage where Self == StaticParserError {
131131
public static var expectedAssignmentInsteadOfComparisonOperator: Self {
132132
.init("expected '=' instead of '==' to assign default value for parameter")
133133
}
134+
public static var expectedCommaInWhereClause: Self {
135+
.init("expected ',' to separate the requirements of this 'where' clause")
136+
}
134137
public static var expectedLeftBraceOrIfAfterElse: Self {
135138
.init("expected '{' or 'if' after 'else'")
136139
}

Tests/SwiftParserTest/translated/RecoveryTests.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,15 +2209,17 @@ final class RecoveryTests: XCTestCase {
22092209
}
22102210

22112211
func testRecovery177() {
2212+
// rdar://38225184
22122213
assertParse(
22132214
"""
2214-
// rdar://38225184
22152215
extension Collection where Element == Int 1️⃣&& Index == Int {}
22162216
""",
22172217
diagnostics: [
2218-
DiagnosticSpec(message: "unexpected code '&& Index == Int' in extension")
2219-
// TODO: Old parser expected error on line 1: expected ',' to separate the requirements of this 'where' clause, Fix-It replacements: 43 - 45 = ','
2220-
]
2218+
DiagnosticSpec(message: "expected ',' to separate the requirements of this 'where' clause", fixIts: ["replace '&&' with ','"])
2219+
],
2220+
fixedSource: """
2221+
extension Collection where Element == Int, Index == Int {}
2222+
"""
22212223
)
22222224
}
22232225

0 commit comments

Comments
 (0)