Skip to content

Commit ebf79c3

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

File tree

2 files changed

+25
-17
lines changed

2 files changed

+25
-17
lines changed

Sources/SwiftParser/Statements.swift

Lines changed: 23 additions & 12 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)
@@ -1068,9 +1072,16 @@ extension Parser.Lookahead {
10681072
// with a closure pattern.
10691073
return self.peek().rawTokenKind == .leftBrace
10701074
case .yield?, .discard?:
1071-
return atContextualKeywordPrefixedSyntax(exprFlavor: .basic, preferPostfixExpr: true)
1075+
return atContextualKeywordPrefixedSyntax(
1076+
exprFlavor: .basic,
1077+
preferPostfixExpr: true
1078+
)
10721079
case .then?:
1073-
return atContextualKeywordPrefixedSyntax(exprFlavor: .basic, preferPostfixExpr: false)
1080+
return atContextualKeywordPrefixedSyntax(
1081+
exprFlavor: .basic,
1082+
preferPostfixExpr: false,
1083+
allowNextLineOperand: !preferExpr
1084+
)
10741085

10751086
case nil:
10761087
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)