Skip to content

Commit f17b126

Browse files
committed
Add diagnostic for missing conditions for while statement
1 parent 2e5283b commit f17b126

File tree

3 files changed

+40
-16
lines changed

3 files changed

+40
-16
lines changed

Sources/SwiftParser/Statements.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,22 @@ extension Parser {
539539
@_spi(RawSyntax)
540540
public mutating func parseWhileStatement(whileHandle: RecoveryConsumptionHandle) -> RawWhileStmtSyntax {
541541
let (unexpectedBeforeWhileKeyword, whileKeyword) = self.eat(whileHandle)
542-
let conditions = self.parseConditionList()
542+
let conditions: RawConditionElementListSyntax
543+
544+
if self.at(.leftBrace) {
545+
conditions = RawConditionElementListSyntax(
546+
elements: [
547+
RawConditionElementSyntax(
548+
condition: .expression(RawExprSyntax(RawMissingExprSyntax(arena: self.arena))),
549+
trailingComma: nil,
550+
arena: self.arena
551+
)
552+
],
553+
arena: self.arena
554+
)
555+
} else {
556+
conditions = self.parseConditionList()
557+
}
543558
let body = self.parseCodeBlock(introducer: whileKeyword)
544559
return RawWhileStmtSyntax(
545560
unexpectedBeforeWhileKeyword,

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,18 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
12201220
return .visitChildren
12211221
}
12221222

1223+
public override func visit(_ node: WhileStmtSyntax) -> SyntaxVisitorContinueKind {
1224+
if shouldSkip(node) {
1225+
return .skipChildren
1226+
}
1227+
1228+
if node.conditions.count == 1, node.conditions.first?.as(ConditionElementSyntax.self)?.condition.is(MissingExprSyntax.self) == true, !node.body.leftBrace.isMissingAllTokens {
1229+
addDiagnostic(node.conditions, MissingConditionInStatement(firstToken: node.whileKeyword), handledNodes: [node.conditions.id])
1230+
}
1231+
1232+
return .visitChildren
1233+
}
1234+
12231235
//==========================================================================//
12241236
// IMPORTANT: If you are tempted to add a `visit` method here, please //
12251237
// insert it in alphabetical order above //

Tests/SwiftParserTest/translated/RecoveryTests.swift

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -268,26 +268,24 @@ final class RecoveryTests: XCTestCase {
268268
func testRecovery21() {
269269
assertParse(
270270
"""
271-
while {
272-
}1️⃣
271+
while 1️⃣{
272+
}
273273
""",
274274
diagnostics: [
275-
// TODO: Old parser expected error on line 1: missing condition in 'while' statement
276-
DiagnosticSpec(message: "expected code block in 'while' statement")
275+
DiagnosticSpec(message: "missing condition in 'while' statement")
277276
]
278277
)
279278
}
280279

281280
func testRecovery22() {
282281
assertParse(
283282
"""
284-
while
283+
while 1️⃣
285284
{
286-
}1️⃣
285+
}
287286
""",
288287
diagnostics: [
289-
// TODO: Old parser expected error on line 1: missing condition in 'while' statement
290-
DiagnosticSpec(message: "expected code block in 'while' statement")
288+
DiagnosticSpec(message: "missing condition in 'while' statement")
291289
]
292290
)
293291
}
@@ -297,11 +295,11 @@ final class RecoveryTests: XCTestCase {
297295
"""
298296
// It is debatable if we should do recovery here and parse { true } as the
299297
// body, but the error message should be sensible.
300-
while { true } {
298+
while 1️⃣{ true } {
301299
}
302300
""",
303301
diagnostics: [
304-
// TODO: Old parser expected error on line 3: missing condition in 'while' statement
302+
DiagnosticSpec(message: "missing condition in 'while' statement")
305303
// TODO: Old parser expected error on line 3: consecutive statements on a line must be separated by ';', Fix-It replacements: 17 - 17 = ';'
306304
// TODO: Old parser expected error on line 3: closure expression is unused
307305
// TODO: Old parser expected note on line 3: did you mean to use a 'do' statement?, Fix-It replacements: 18 - 18 = 'do '
@@ -313,11 +311,11 @@ final class RecoveryTests: XCTestCase {
313311
func testRecovery24() {
314312
assertParse(
315313
"""
316-
while { true }() { // expected-error 2 {{consecutive statements on a line must be separated by ';'}} expected-error {{closure expression is unused}} expected-note {{did you mean to use a 'do' statement?}} {{20-20=do }} expected-warning {{boolean literal is unused}}
314+
while 1️⃣{ true }() {
317315
}
318316
""",
319317
diagnostics: [
320-
// TODO: Old parser expected error on line 1: missing condition in 'while' statement
318+
DiagnosticSpec(message: "missing condition in 'while' statement")
321319
]
322320
)
323321
}
@@ -326,13 +324,12 @@ final class RecoveryTests: XCTestCase {
326324
assertParse(
327325
"""
328326
// <rdar://problem/18940198>
329-
while { { } }1️⃣
327+
while 1️⃣{ { } }
330328
""",
331329
diagnostics: [
332-
// TODO: Old parser expected error on line 2: missing condition in 'while' statement
330+
DiagnosticSpec(message: "missing condition in 'while' statement")
333331
// TODO: Old parser expected error on line 2: closure expression is unused
334332
// TODO: Old parser expected note on line 2: did you mean to use a 'do' statement?, Fix-It replacements: 11 - 11 = 'do '
335-
DiagnosticSpec(message: "expected code block in 'while' statement")
336333
]
337334
)
338335
}

0 commit comments

Comments
 (0)