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 {
25672567 mutating func canParseClosureSignature( ) -> Bool {
25682568 // Consume attributes.
25692569 var lookahead = self . lookahead ( )
2570+ var sawTopLevelArrowInLookahead = false
25702571 var attributesProgress = LoopProgressCondition ( )
25712572 while lookahead. consume ( if: . atSign) != nil , lookahead. hasProgressed ( & attributesProgress) {
25722573 guard lookahead. at ( . identifier) else {
@@ -2630,15 +2631,21 @@ extension Parser.Lookahead {
26302631 return false
26312632 }
26322633
2634+ sawTopLevelArrowInLookahead = true
2635+
26332636 lookahead. consumeEffectsSpecifiers ( )
26342637 }
26352638
26362639 // 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
26392643 }
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
26422649 }
26432650}
26442651
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 {
24472447 ) ,
24482448 DiagnosticSpec (
24492449 locationMarker: " 4️⃣ " ,
2450- message: " unexpected code ') -> Int {}' in closure "
2450+ message: " expected 'in' in closure signature " ,
2451+ fixIts: [ " insert 'in' " ]
24512452 ) ,
2453+ DiagnosticSpec (
2454+ locationMarker: " 4️⃣ " ,
2455+ message: " unexpected code ') -> Int {}' in closure "
2456+ )
24522457 ] ,
24532458 fixedSource: """
24542459 #if true
24552460 struct Foo19605164 {
2456- func a(s: S) [{{g) -> Int {}
2461+ func a(s: S) [{{g in ) -> Int {}
24572462 }}}
24582463 #endif
24592464 """
You can’t perform that action at this time.
0 commit comments