Skip to content

Commit 2f77f68

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

File tree

2 files changed

+16
-16
lines changed

2 files changed

+16
-16
lines changed

Sources/SwiftParser/Statements.swift

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -912,12 +912,13 @@ extension TokenConsumer {
912912
mutating func atContextualKeywordPrefixedSyntax(
913913
exprFlavor: Parser.ExprFlavor,
914914
acceptClosure: Bool = false,
915-
preferPostfixExpr: Bool = true
915+
preferPostfixExpr: Bool = true,
916+
allowNextLineOperand: Bool = false
916917
) -> Bool {
917918
let next = peek()
918919

919920
// The next token must be at the same line.
920-
if next.isAtStartOfLine {
921+
if next.isAtStartOfLine && !allowNextLineOperand {
921922
return false
922923
}
923924

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

10001002
case .leftBrace:
10011003
// E.g. <word> { ... }
10021004
// Trailing closure is also ambiguous:
10031005
//
10041006
// - Trailing closure vs. immediately-invoked closure
10051007
//
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 { ... }()'
10101008
if !acceptClosure {
10111009
return false
10121010
}
1011+
1012+
// Checking whitespace between the word cannot help this because people
1013+
// usually put a space before trailing closures. Even though that is source
1014+
// breaking, we prefer parsing it as a keyword if the syntax accepts
1015+
// expressions starting with a closure. E.g. 'unsafe { ... }()'
10131016
return self.withLookahead {
10141017
$0.consumeAnyToken()
10151018
return $0.atValidTrailingClosure(flavor: exprFlavor)
@@ -1070,7 +1073,7 @@ extension Parser.Lookahead {
10701073
case .yield?, .discard?:
10711074
return atContextualKeywordPrefixedSyntax(exprFlavor: .basic, preferPostfixExpr: true)
10721075
case .then?:
1073-
return atContextualKeywordPrefixedSyntax(exprFlavor: .basic, preferPostfixExpr: false)
1076+
return atContextualKeywordPrefixedSyntax(exprFlavor: .basic, preferPostfixExpr: false, allowNextLineOperand: !preferExpr)
10741077

10751078
case nil:
10761079
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)