File tree Expand file tree Collapse file tree 3 files changed +121
-6
lines changed Expand file tree Collapse file tree 3 files changed +121
-6
lines changed Original file line number Diff line number Diff line change @@ -2567,6 +2567,7 @@ extension Parser.Lookahead {
2567
2567
mutating func canParseClosureSignature( ) -> Bool {
2568
2568
// Consume attributes.
2569
2569
var lookahead = self . lookahead ( )
2570
+ var sawTopLevelArrowInLookahead = false
2570
2571
var attributesProgress = LoopProgressCondition ( )
2571
2572
while lookahead. consume ( if: . atSign) != nil , lookahead. hasProgressed ( & attributesProgress) {
2572
2573
guard lookahead. at ( . identifier) else {
@@ -2630,15 +2631,21 @@ extension Parser.Lookahead {
2630
2631
return false
2631
2632
}
2632
2633
2634
+ sawTopLevelArrowInLookahead = true
2635
+
2633
2636
lookahead. consumeEffectsSpecifiers ( )
2634
2637
}
2635
2638
2636
2639
// Parse the 'in' at the end.
2637
- guard lookahead. at ( . keyword( . in) ) else {
2638
- return false
2640
+ if lookahead. at ( . keyword( . in) ) {
2641
+ // Okay, we have a closure signature.
2642
+ return true
2639
2643
}
2640
- // Okay, we have a closure signature.
2641
- return true
2644
+
2645
+ // Even if 'in' is missing, the presence of a top-level '->' makes this look like a
2646
+ // closure signature. There's no other valid syntax that could legally
2647
+ // contain '->' at this position.
2648
+ return sawTopLevelArrowInLookahead
2642
2649
}
2643
2650
}
2644
2651
Original file line number Diff line number Diff line change
1
+ @_spi ( ExperimentalLanguageFeatures) @_spi ( RawSyntax) import SwiftParser
2
+ @_spi ( ExperimentalLanguageFeatures) @_spi ( RawSyntax) import SwiftSyntax
3
+ import XCTest
4
+
5
+ final class ClosureMissingInTests : ParserTestCase {
6
+
7
+ func testMissingInAfterSignature( ) {
8
+ assertParse (
9
+ """
10
+ _ = { (x: Int) -> Int 1️⃣0 }
11
+ """ ,
12
+ diagnostics: [
13
+ DiagnosticSpec (
14
+ locationMarker: " 1️⃣ " ,
15
+ message: " expected 'in' in closure signature " ,
16
+ fixIts: [ " insert 'in' " ]
17
+ )
18
+ ] ,
19
+ fixedSource: """
20
+ _ = { (x: Int) -> Int in 0 }
21
+ """
22
+ )
23
+ }
24
+
25
+ func testArrayLiteralNotMisparsedAsSignature( ) {
26
+ assertParse (
27
+ """
28
+ _ = { [x, y] }
29
+ """
30
+ )
31
+ }
32
+
33
+ func testAsyncIsNotASignatureGate( ) {
34
+ assertParse (
35
+ """
36
+ _ = { async }
37
+ """
38
+ )
39
+ }
40
+
41
+ func testShorthandParamsWithReturnType( ) {
42
+ assertParse (
43
+ """
44
+ _ = { x, _ -> Int 1️⃣x }
45
+ """ ,
46
+ diagnostics: [
47
+ DiagnosticSpec (
48
+ locationMarker: " 1️⃣ " ,
49
+ message: " expected 'in' in closure signature " ,
50
+ fixIts: [ " insert 'in' " ]
51
+ )
52
+ ] ,
53
+ fixedSource: """
54
+ _ = { x, _ -> Int in x }
55
+ """
56
+ )
57
+ }
58
+
59
+ func testResyncTokensBeforeIn( ) {
60
+ assertParse (
61
+ """
62
+ _ = { () -> Int
63
+ 1️⃣0
64
+ in
65
+ 1
66
+ }
67
+ """ ,
68
+ diagnostics: [
69
+ DiagnosticSpec (
70
+ locationMarker: " 1️⃣ " ,
71
+ message: " unexpected code '0' in closure signature "
72
+ ) ,
73
+ ]
74
+ )
75
+ }
76
+
77
+ func testMissingInInFunctionArgument( ) {
78
+ assertParse (
79
+ """
80
+ test(make: { () -> [Int] 1️⃣
81
+ return [3]
82
+ }, consume: { _ in
83
+ print( " Test " )
84
+ })
85
+ """ ,
86
+ diagnostics: [
87
+ DiagnosticSpec (
88
+ locationMarker: " 1️⃣ " ,
89
+ message: " expected 'in' in closure signature " ,
90
+ fixIts: [ " insert 'in' " ]
91
+ )
92
+ ] ,
93
+ fixedSource:
94
+ """
95
+ test(make: { () -> [Int] in
96
+ return [3]
97
+ }, consume: { _ in
98
+ print( " Test " )
99
+ })
100
+ """
101
+ )
102
+ }
103
+ }
Original file line number Diff line number Diff line change @@ -2447,13 +2447,18 @@ final class RecoveryTests: ParserTestCase {
2447
2447
) ,
2448
2448
DiagnosticSpec (
2449
2449
locationMarker: " 4️⃣ " ,
2450
- message: " unexpected code ') -> Int {}' in closure "
2450
+ message: " expected 'in' in closure signature " ,
2451
+ fixIts: [ " insert 'in' " ]
2451
2452
) ,
2453
+ DiagnosticSpec (
2454
+ locationMarker: " 4️⃣ " ,
2455
+ message: " unexpected code ') -> Int {}' in closure "
2456
+ )
2452
2457
] ,
2453
2458
fixedSource: """
2454
2459
#if true
2455
2460
struct Foo19605164 {
2456
- func a(s: S) [{{g) -> Int {}
2461
+ func a(s: S) [{{g in ) -> Int {}
2457
2462
}}}
2458
2463
#endif
2459
2464
"""
You can’t perform that action at this time.
0 commit comments