@@ -1440,26 +1440,18 @@ extension Parser {
1440
1440
arena: self . arena)
1441
1441
}
1442
1442
1443
- /// If a `throws` keyword appears right in front of the `arrow`, it is returned as `misplacedThrowsKeyword` so it can be synthesized in front of the arrow.
1444
- @_spi ( RawSyntax)
1445
- public mutating func parseFunctionReturnClause( ) -> ( returnClause: RawReturnClauseSyntax , misplacedThrowsKeyword: RawTokenSyntax ? ) {
1446
- let ( unexpectedBeforeArrow, arrow) = self . expect ( . arrow)
1447
- var misplacedThrowsKeyword : RawTokenSyntax ? = nil
1448
- let unexpectedBeforeReturnType : RawUnexpectedNodesSyntax ?
1449
- if let throwsKeyword = self . consume ( ifAny: [ . rethrowsKeyword, . throwsKeyword] ) {
1450
- misplacedThrowsKeyword = throwsKeyword
1451
- unexpectedBeforeReturnType = RawUnexpectedNodesSyntax ( elements: [ RawSyntax ( throwsKeyword) ] , arena: self . arena)
1452
- } else {
1453
- unexpectedBeforeReturnType = nil
1454
- }
1443
+ /// If effect specifiers appear in front of the `arrow` or after the return type, they are returned so that they can be synthesized in front of the arrow.
1444
+ mutating func parseReturnClause( _ handle: RecoveryConsumptionHandle ) -> ( returnClause: RawReturnClauseSyntax , misplacedSpecifiers: [ SpecifierWithToken ] ) {
1445
+ let ( unexpectedBeforeArrow, arrow) = self . eat ( handle)
1446
+ let misplacedSpecifiers = parseAllEffectsSpecifiers ( )
1455
1447
let result = self . parseResultType ( )
1456
1448
let returnClause = RawReturnClauseSyntax (
1457
1449
unexpectedBeforeArrow,
1458
1450
arrow: arrow,
1459
- unexpectedBeforeReturnType ,
1451
+ RawUnexpectedNodesSyntax ( misplacedSpecifiers , arena : self . arena ) ,
1460
1452
returnType: result,
1461
1453
arena: self . arena)
1462
- return ( returnClause, misplacedThrowsKeyword )
1454
+ return ( returnClause, misplacedSpecifiers )
1463
1455
}
1464
1456
}
1465
1457
@@ -1544,33 +1536,27 @@ extension Parser {
1544
1536
public mutating func parseFunctionSignature( ) -> RawFunctionSignatureSyntax {
1545
1537
let input = self . parseParameterClause ( for: . functionParameters)
1546
1538
1547
- let async : RawTokenSyntax ?
1548
- if let asyncTok = self . consumeIfContextualKeyword ( " async " ) {
1549
- async = asyncTok
1550
- } else if let reasync = self . consumeIfContextualKeyword ( " reasync " ) {
1551
- async = reasync
1552
- } else {
1553
- async = nil
1554
- }
1555
-
1556
- var throwsKeyword = self . consume ( ifAny: [ . throwsKeyword, . rethrowsKeyword] )
1539
+ var ( asyncOrReasync, throwsOrRethrows, specifiersAfterThrows) = parseEffectsSpecifiers ( atDecl: true )
1557
1540
1558
1541
let output : RawReturnClauseSyntax ?
1559
- if self . at ( . arrow) {
1560
- let result = self . parseFunctionReturnClause ( )
1561
- output = result. returnClause
1562
- if let misplacedThrowsKeyword = result. misplacedThrowsKeyword, throwsKeyword == nil {
1563
- throwsKeyword = RawTokenSyntax ( missing: misplacedThrowsKeyword. tokenKind, arena: self . arena)
1564
- }
1542
+ if let handle = self . canRecoverTo ( . arrow) {
1543
+ let ( returnClause, misplacedSpecifiers) = parseReturnClause ( handle)
1544
+ addMissingEffectsSpecifiers ( atDecl: true , from: misplacedSpecifiers, asyncOrReasync: & asyncOrReasync, throwsOrRethrows: & throwsOrRethrows)
1545
+ output = returnClause
1565
1546
} else {
1566
1547
output = nil
1567
1548
}
1568
1549
1550
+ let specifiersAfterReturn = parseAllEffectsSpecifiers ( )
1551
+ addMissingEffectsSpecifiers ( atDecl: true , from: specifiersAfterReturn, asyncOrReasync: & asyncOrReasync, throwsOrRethrows: & throwsOrRethrows)
1552
+
1569
1553
return RawFunctionSignatureSyntax (
1570
1554
input: input,
1571
- asyncOrReasyncKeyword: async ,
1572
- throwsOrRethrowsKeyword: throwsKeyword,
1555
+ asyncOrReasyncKeyword: asyncOrReasync,
1556
+ throwsOrRethrowsKeyword: throwsOrRethrows,
1557
+ RawUnexpectedNodesSyntax ( specifiersAfterThrows, arena: self . arena) ,
1573
1558
output: output,
1559
+ RawUnexpectedNodesSyntax ( specifiersAfterReturn, arena: self . arena) ,
1574
1560
arena: self . arena)
1575
1561
}
1576
1562
}
@@ -1601,9 +1587,11 @@ extension Parser {
1601
1587
1602
1588
let indices = self . parseParameterClause ( for: . indices)
1603
1589
1590
+ let unexpectedBeforeArrow = RawUnexpectedNodesSyntax ( parseAllEffectsSpecifiers ( ) , arena: self . arena)
1591
+
1604
1592
let result : RawReturnClauseSyntax
1605
- if self . at ( . arrow) {
1606
- result = self . parseFunctionReturnClause ( ) . returnClause
1593
+ if let handle = self . canRecoverTo ( . arrow) {
1594
+ result = self . parseReturnClause ( handle ) . returnClause
1607
1595
} else {
1608
1596
result = RawReturnClauseSyntax (
1609
1597
arrow: RawTokenSyntax ( missing: . arrow, arena: self . arena) ,
@@ -1635,6 +1623,7 @@ extension Parser {
1635
1623
subscriptKeyword: subscriptKeyword,
1636
1624
genericParameterClause: genericParameterClause,
1637
1625
indices: indices,
1626
+ unexpectedBeforeArrow,
1638
1627
result: result,
1639
1628
genericWhereClause: genericWhereClause,
1640
1629
accessor: accessor,
@@ -1767,41 +1756,6 @@ extension Parser {
1767
1756
attributes: attrs, modifier: modifier, kind: kind, token: introducer)
1768
1757
}
1769
1758
1770
- @_spi ( RawSyntax)
1771
- public mutating func parseEffectsSpecifier( ) -> RawTokenSyntax ? {
1772
- // 'async'
1773
- if let async = self . consumeIfContextualKeyword ( " async " ) {
1774
- return async
1775
- }
1776
-
1777
- // 'reasync'
1778
- if let reasync = self . consumeIfContextualKeyword ( " reasync " ) {
1779
- return reasync
1780
- }
1781
-
1782
- // 'throws'/'rethrows'
1783
- if let throwsRethrows = self . consume ( ifAny: [ . throwsKeyword, . rethrowsKeyword] ) {
1784
- return throwsRethrows
1785
- }
1786
-
1787
- // diagnose 'throw'/'try'.
1788
- if let throwTry = self . consume ( ifAny: [ . throwKeyword, . tryKeyword] , where: { !$0. isAtStartOfLine } ) {
1789
- return throwTry
1790
- }
1791
-
1792
- return nil
1793
- }
1794
-
1795
- @_spi ( RawSyntax)
1796
- public mutating func parseEffectsSpecifiers( ) -> [ RawTokenSyntax ] {
1797
- var specifiers = [ RawTokenSyntax] ( )
1798
- var loopProgress = LoopProgressCondition ( )
1799
- while let specifier = self . parseEffectsSpecifier ( ) , loopProgress. evaluate ( currentToken) {
1800
- specifiers. append ( specifier)
1801
- }
1802
- return specifiers
1803
- }
1804
-
1805
1759
/// Parse the body of a variable declaration. This can include explicit
1806
1760
/// getters, setters, and observers, or the body of a computed property.
1807
1761
///
@@ -1884,14 +1838,15 @@ extension Parser {
1884
1838
1885
1839
// Next, parse effects specifiers. While it's only valid to have them
1886
1840
// on 'get' accessors, we also emit diagnostics if they show up on others.
1887
- let asyncKeyword : RawTokenSyntax ?
1888
- let throwsKeyword : RawTokenSyntax ?
1889
- if self . at ( anyIn : EffectsSpecifier . self ) != nil {
1890
- asyncKeyword = self . parseEffectsSpecifier ( )
1891
- throwsKeyword = self . parseEffectsSpecifier ( )
1841
+ var asyncOrReasync : RawTokenSyntax ? = nil
1842
+ var throwsOrRethrows : RawTokenSyntax ? = nil
1843
+ let unexpectedAfterThrows : [ SpecifierWithToken ]
1844
+ if introducer . kind == . get {
1845
+ ( asyncOrReasync , throwsOrRethrows , unexpectedAfterThrows ) = parseEffectsSpecifiers ( atDecl : true )
1892
1846
} else {
1893
- asyncKeyword = nil
1894
- throwsKeyword = nil
1847
+ asyncOrReasync = nil
1848
+ throwsOrRethrows = nil
1849
+ unexpectedAfterThrows = parseAllEffectsSpecifiers ( )
1895
1850
}
1896
1851
1897
1852
let body = self . parseOptionalCodeBlock ( )
@@ -1901,8 +1856,9 @@ extension Parser {
1901
1856
modifier: introducer. modifier,
1902
1857
accessorKind: introducer. token,
1903
1858
parameter: parameter,
1904
- asyncKeyword: asyncKeyword,
1905
- throwsKeyword: throwsKeyword,
1859
+ asyncKeyword: asyncOrReasync,
1860
+ throwsKeyword: throwsOrRethrows,
1861
+ RawUnexpectedNodesSyntax ( unexpectedAfterThrows, arena: self . arena) ,
1906
1862
body: body,
1907
1863
arena: self . arena) )
1908
1864
}
@@ -2233,3 +2189,59 @@ extension Parser {
2233
2189
}
2234
2190
}
2235
2191
}
2192
+
2193
+ extension Parser {
2194
+ mutating func parseAllEffectsSpecifiers( ) -> [ SpecifierWithToken ] {
2195
+ var specifiers = [ SpecifierWithToken] ( )
2196
+ var loopProgress = LoopProgressCondition ( )
2197
+ while let ( specifier, handle) = self . canRecoverTo ( anyIn: EffectsSpecifier . self) , loopProgress. evaluate ( currentToken) {
2198
+ let ( unexpected, token) = self . eatKeepUnexpected ( handle)
2199
+ specifiers. append ( contentsOf: unexpected. map { SpecifierWithToken ( specifier: nil , token: $0) } )
2200
+ specifiers. append ( SpecifierWithToken ( specifier: specifier, token: token) )
2201
+ }
2202
+ return specifiers
2203
+ }
2204
+
2205
+ func addMissingEffectsSpecifiers( atDecl: Bool , from unexpectedSpecifiers: [ SpecifierWithToken ] , asyncOrReasync: inout RawTokenSyntax ? , throwsOrRethrows: inout RawTokenSyntax ? ) {
2206
+ for unexpected in unexpectedSpecifiers {
2207
+ guard asyncOrReasync == nil || throwsOrRethrows == nil else {
2208
+ break
2209
+ }
2210
+
2211
+ if asyncOrReasync == nil , unexpected. specifier == . asyncContextualKeyword || ( atDecl && unexpected. specifier == . reasyncContextualKeyword) {
2212
+ asyncOrReasync = RawTokenSyntax ( missing: unexpected. token. tokenKind, text: unexpected. token. tokenText, arena: self . arena)
2213
+ }
2214
+
2215
+ if throwsOrRethrows == nil , unexpected. specifier == . throwKeyword || ( atDecl && unexpected. specifier == . rethrowsKeyword) {
2216
+ throwsOrRethrows = RawTokenSyntax ( missing: unexpected. token. tokenKind, arena: self . arena)
2217
+ }
2218
+ }
2219
+ }
2220
+
2221
+ mutating func parseEffectsSpecifiers( atDecl: Bool ) -> ( asyncOrReasync: RawTokenSyntax ? ,
2222
+ throwsOrRethrows: RawTokenSyntax ? ,
2223
+ specifiersAfterThrows: [ SpecifierWithToken ] ) {
2224
+ var initialSpecifiers = parseAllEffectsSpecifiers ( )
2225
+
2226
+ var asyncOrReasync : RawTokenSyntax ?
2227
+ var throwsOrRethrows : RawTokenSyntax ?
2228
+ if !initialSpecifiers. isEmpty {
2229
+ let first = initialSpecifiers. removeFirst ( )
2230
+ if first. specifier == . asyncContextualKeyword || atDecl && first. specifier == . reasyncContextualKeyword {
2231
+ asyncOrReasync = first. token
2232
+
2233
+ if !initialSpecifiers. isEmpty {
2234
+ let second = initialSpecifiers. removeFirst ( )
2235
+ if second. specifier == . throwsKeyword || atDecl && second. specifier == . rethrowsKeyword {
2236
+ throwsOrRethrows = second. token
2237
+ }
2238
+ }
2239
+ } else if first. specifier == . throwsKeyword || atDecl && first. specifier == . rethrowsKeyword {
2240
+ throwsOrRethrows = first. token
2241
+ }
2242
+ addMissingEffectsSpecifiers ( atDecl: atDecl, from: initialSpecifiers, asyncOrReasync: & asyncOrReasync, throwsOrRethrows: & throwsOrRethrows)
2243
+ }
2244
+
2245
+ return ( asyncOrReasync, throwsOrRethrows, initialSpecifiers)
2246
+ }
2247
+ }
0 commit comments