Skip to content

Commit 2a45ef7

Browse files
committed
[Parser] Add 'allowNextLineOperand' to atContextualKeywordPrefixedSyntax
Just like 'return', 'then' statement should accept operand on the next line.
1 parent 5bf4217 commit 2a45ef7

File tree

2 files changed

+17
-16
lines changed

2 files changed

+17
-16
lines changed

Sources/SwiftParser/Statements.swift

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -909,15 +909,17 @@ extension TokenConsumer {
909909
/// - acceptClosure: When the next token is '{' and it looks like a closure, use this value as the result.
910910
/// - preferPostfixExpr: When the next token is '.', '(', or '[' and there is a space between the word,
911911
/// use `!preferPostfixExpr` as the result.
912+
/// - allowNextLineOperand: Whether the keyword-prefixed syntax accepts the operand on the next line.
912913
mutating func atContextualKeywordPrefixedSyntax(
913914
exprFlavor: Parser.ExprFlavor,
914915
acceptClosure: Bool = false,
915-
preferPostfixExpr: Bool = true
916+
preferPostfixExpr: Bool = true,
917+
allowNextLineOperand: Bool = false
916918
) -> Bool {
917919
let next = peek()
918920

919921
// The next token must be at the same line.
920-
if next.isAtStartOfLine {
922+
if next.isAtStartOfLine && !allowNextLineOperand {
921923
return false
922924
}
923925

@@ -990,26 +992,28 @@ extension TokenConsumer {
990992
// - Call vs. tuple expression
991993
// - Subscript vs. collection literal
992994
//
993-
let hasSpace = (next.leadingTriviaByteLength + currentToken.trailingTriviaByteLength) != 0
994-
if !hasSpace {
995-
// No space, the word is an decl-ref expression
995+
if preferPostfixExpr {
996996
return false
997997
}
998-
return !preferPostfixExpr
998+
999+
// If there's no space between the tokens, consider it's an expression.
1000+
// Otherwise, it looks like a keyword followed by an expression.
1001+
return (next.leadingTriviaByteLength + currentToken.trailingTriviaByteLength) != 0
9991002

10001003
case .leftBrace:
10011004
// E.g. <word> { ... }
10021005
// Trailing closure is also ambiguous:
10031006
//
10041007
// - Trailing closure vs. immediately-invoked closure
10051008
//
1006-
// Checking whitespace between the word cannot help this because people
1007-
// usually put a space before trailing closures. Even though that is source
1008-
// breaking, we prefer parsing it as a keyword if the syntax accepts
1009-
// immediately-invoked closure patterns. E.g. 'unsafe { ... }()'
10101009
if !acceptClosure {
10111010
return false
10121011
}
1012+
1013+
// Checking whitespace between the word cannot help this because people
1014+
// usually put a space before trailing closures. Even though that is source
1015+
// breaking, we prefer parsing it as a keyword if the syntax accepts
1016+
// expressions starting with a closure. E.g. 'unsafe { ... }()'
10131017
return self.withLookahead {
10141018
$0.consumeAnyToken()
10151019
return $0.atValidTrailingClosure(flavor: exprFlavor)
@@ -1070,7 +1074,7 @@ extension Parser.Lookahead {
10701074
case .yield?, .discard?:
10711075
return atContextualKeywordPrefixedSyntax(exprFlavor: .basic, preferPostfixExpr: true)
10721076
case .then?:
1073-
return atContextualKeywordPrefixedSyntax(exprFlavor: .basic, preferPostfixExpr: false)
1077+
return atContextualKeywordPrefixedSyntax(exprFlavor: .basic, preferPostfixExpr: false, allowNextLineOperand: !preferExpr)
10741078

10751079
case nil:
10761080
return false

Tests/SwiftParserTest/ThenStatementTests.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ final class ThenStatementTests: ParserTestCase {
330330
then
331331
0
332332
""",
333-
substructure: DeclReferenceExprSyntax(baseName: .identifier("then"))
333+
substructure: ThenStmtSyntax(expression: IntegerLiteralExprSyntax(0))
334334
)
335335
}
336336

@@ -673,10 +673,7 @@ final class ThenStatementTests: ParserTestCase {
673673
then
674674
.foo
675675
""",
676-
substructure: MemberAccessExprSyntax(
677-
base: DeclReferenceExprSyntax(baseName: .identifier("then")),
678-
name: .identifier("foo")
679-
)
676+
substructure: ThenStmtSyntax(expression: MemberAccessExprSyntax(name: .identifier("foo")))
680677
)
681678
}
682679

0 commit comments

Comments
 (0)