8000 Merge pull request #2313 from bnbarham/literal-expr-parsing · art-divin/swift-syntax@ebd7026 · GitHub
[go: up one dir, main page]

Skip to content

Commit ebd7026

Browse files
authored
Merge pull request swiftlang#2313 from bnbarham/literal-expr-parsing
Skip parsing trailing closures after literals
2 parents e5962c4 + efbfbab commit ebd7026

File tree

5 files changed

+129
-16
lines changed

5 files changed

+129
-16
lines changed

Sources/SwiftParser/Expressions.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ extension Parser {
790790
}
791791

792792
// Check for a trailing closure, if allowed.
793-
if self.at(.leftBrace) && self.withLookahead({ $0.atValidTrailingClosure(flavor: flavor) }) {
793+
if self.at(.leftBrace) && !leadingExpr.raw.kind.isLiteral && self.withLookahead({ $0.atValidTrailingClosure(flavor: flavor) }) {
794794
// FIXME: if Result has a trailing closure, break out.
795795
// Add dummy blank argument list to the call expression syntax.
796796
let list = RawLabeledExprListSyntax(elements: [], arena: self.arena)
@@ -2543,3 +2543,14 @@ extension Parser.Lookahead {
25432543
}
25442544
}
25452545
}
2546+
2547+
extension SyntaxKind {
2548+
fileprivate var isLiteral: Bool {
2549+
switch self {
2550+
case .arrayExpr, .booleanLiteralExpr, .dictionaryExpr, .floatLiteralExpr, .integerLiteralExpr, .nilLiteralExpr, .regexLiteralExpr, .stringLiteralExpr:
2551+
return true
2552+
default:
2553+
return false
2554+
}
2555+
}
2556+
}

Tests/SwiftParserTest/DeclarationTests.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3072,4 +3072,11 @@ final class DeclarationTests: ParserTestCase {
30723072
"""
30733073
)
30743074
}
3075+
3076+
func testLiteralInitializerWithTrailingClosure() {
3077+
assertParse(
3078+
"let foo = 1 { return 1 }",
3079+
substructure: AccessorBlockSyntax(accessors: .getter([CodeBlockItemSyntax("return 1")]))
3080+
)
3081+
}
30753082
}

Tests/SwiftParserTest/ExpressionTests.swift

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,12 +1463,86 @@ final class ExpressionTests: ParserTestCase {
14631463
)
14641464
}
14651465

1466-
func testNulCharacterInSourceFile() {
1466+
func testLiteralWithTrailingClosure() {
1467+
let expectedDiagnostics = [
1468+
DiagnosticSpec(
1469+
message: "consecutive statements on a line must be separated by newline or ';'",
1470+
fixIts: ["insert newline", "insert ';'"]
1471+
)
1472+
]
1473+
14671474
assertParse(
1468-
"let a = 1️⃣\u{0}1",
1469-
diagnostics: [
1470-
DiagnosticSpec(message: "nul character embedded in middle of file", severity: .warning)
1471-
]
1475+
"_ = true1️⃣ { return true }",
1476+
diagnostics: expectedDiagnostics,
1477+
fixedSource: """
1478+
_ = true
1479+
{ return true }
1480+
"""
1481+
)
1482+
assertParse(
1483+
"_ = nil1️⃣ { return nil }",
1484+
diagnostics: expectedDiagnostics,
1485+
fixedSource: """
1486+
_ = nil
1487+
{ return nil }
1488+
"""
1489+
)
1490+
assertParse(
1491+
"_ = 11️⃣ { return 1 }",
1492+
diagnostics: expectedDiagnostics,
1493+
fixedSource: """
1494+
_ = 1
1495+
{ return 1 }
1496+
"""
1497+
)
1498+
assertParse(
1499+
"_ = 1.01️⃣ { return 1.0 }",
1500+
diagnostics: expectedDiagnostics,
1501+
fixedSource: """
1502+
_ = 1.0
1503+
{ return 1.0 }
1504+
"""
1505+
)
1506+
assertParse(
1507+
#"_ = "foo"1️⃣ { return "foo" }"#,
1508+
diagnostics: expectedDiagnostics,
1509+
fixedSource: """
1510+
_ = "foo"
1511+
{ return "foo" }
1512+
"""
1513+
)
1514+
assertParse(
1515+
"_ = /foo/1️⃣ { return /foo/ }",
1516+
diagnostics: expectedDiagnostics,
1517+
fixedSource: """
1518+
_ = /foo/
1519+
{ return /foo/ }
1520+
"""
1521+
)
1522+
assertParse(
1523+
"_ = [1]1️⃣ { return [1] }",
1524+
diagnostics: expectedDiagnostics,
1525+
fixedSource: """
1526+
_ = [1]
1527+
{ return [1] }
1528+
"""
1529+
)
1530+
assertParse(
1531+
"_ = [1: 1]1️⃣ { return [1: 1] }",
1532+
diagnostics: expectedDiagnostics,
1533+
fixedSource: """
1534+
_ = [1: 1]
1535+
{ return [1: 1] }
1536+
"""
1537+
)
1538+
1539+
assertParse(
1540+
"_ = 1 + 11️⃣ { return 1 }",
1541+
diagnostics: expectedDiagnostics,
1542+
fixedSource: """
1543+
_ = 1 + 1
1544+
{ return 1 }
1545+
"""
14721546
)
14731547
}
14741548
}

Tests/SwiftParserTest/LexerTests.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,4 +1495,13 @@ public class LexerTests: ParserTestCase {
14951495
]
14961496
)
14971497
}
1498+
1499+
func testNulCharacterInSourceFile() {
1500+
assertParse(
1501+
"let a = 1️⃣\u{0}1",
1502+
diagnostics: [
1503+
DiagnosticSpec(message: "nul character embedded in middle of file", severity: .warning)
1504+
]
1505+
)
1506+
}
14981507
}

Tests/SwiftParserTest/translated/RecoveryTests.swift

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,14 +1810,14 @@ final class RecoveryTests: ParserTestCase {
18101810
assertParse(
18111811
"""
18121812
struct ErrorInFunctionSignatureResultArrayType2 1️⃣{
1813-
func foo() -> Int2️⃣[0 {
1813+
func foo() -> Int2️⃣[0 3️⃣{
18141814
return [0]
1815-
}3️⃣
1816-
4️⃣}
1815+
}4️⃣
1816+
5️⃣}
18171817
""",
18181818
diagnostics: [
1819-
// TODO: Old parser expected error on line 2: expected ']' in array type
1820-
// TODO: Old parser expected note on line 2: to match this opening '['
1819+
// TODO: Old parser expected error to add `]` on line 2, but we should just recover to
1820+
// `{` with `[0` becoming unexpected.
18211821
DiagnosticSpec(
18221822
locationMarker: "2️⃣",
18231823
message: "expected '}' to end struct",
@@ -1826,19 +1826,24 @@ final class RecoveryTests: ParserTestCase {
18261826
),
18271827
DiagnosticSpec(
18281828
locationMarker: "3️⃣",
1829+
message: "expected ',' in array element",
1830+
fixIts: ["insert ','"]
1831+
),
1832+
DiagnosticSpec(
1833+
locationMarker: "4️⃣",
18291834
message: "expected ']' to end array",
18301835
notes: [NoteSpec(locationMarker: "2️⃣", message: "to match this opening '['")],
18311836
fixIts: ["insert ']'"]
18321837
),
18331838
DiagnosticSpec(
1834-
locationMarker: "4️⃣",
1839+
locationMarker: "5️⃣",
18351840
message: "extraneous brace at top level"
18361841
),
18371842
],
18381843
fixedSource: """
18391844
struct ErrorInFunctionSignatureResultArrayType2 {
18401845
func foo() -> Int
1841-
}[0 {
1846+
}[0, {
18421847
return [0]
18431848
}]
18441849
}
@@ -1895,11 +1900,12 @@ final class RecoveryTests: ParserTestCase {
18951900
assertParse(
18961901
"""
18971902
struct ErrorInFunctionSignatureResultArrayType11 ℹ️{
1898-
func foo() -> Int1️⃣[(a){a++}] {
1903+
func foo() -> Int1️⃣[(a){a++}]2️⃣ {
18991904
}
1900-
2️⃣}
1905+
3️⃣}
19011906
""",
19021907
diagnostics: [
1908+
// TODO: We should just recover to `{` with `[(a){a++}]` becoming unexpected.
19031909
DiagnosticSpec(
19041910
locationMarker: "1️⃣",
19051911
message: "expected '}' to end struct",
@@ -1908,13 +1914,19 @@ final class RecoveryTests: ParserTestCase {
19081914
),
19091915
DiagnosticSpec(
19101916
locationMarker: "2️⃣",
1917+
message: "consecutive statements on a line must be separated by newline or ';'",
1918+
fixIts: ["insert newline", "insert ';'"]
1919+
),
1920+
DiagnosticSpec(
1921+
locationMarker: "3️⃣",
19111922
message: "extraneous brace at top level"
19121923
),
19131924
],
19141925
fixedSource: """
19151926
struct ErrorInFunctionSignatureResultArrayType11 {
19161927
func foo() -> Int
1917-
}[(a){a++}] {
1928+
}[(a){a++}]
1929+
{
19181930
}
19191931
}
19201932
"""

0 commit comments

Comments
 (0)
0