@@ -1522,12 +1522,14 @@ extension Parser {
1522
1522
var token : RawTokenSyntax
1523
1523
}
1524
1524
1525
- mutating func parseAccessorIntroducer( ) -> AccessorIntroducer ? {
1525
+ mutating func parseAccessorIntroducer(
1526
+ forcedKind: ( AccessorKind , TokenConsumptionHandle ) ? = nil
1527
+ ) -> AccessorIntroducer ? {
1526
1528
// Check there is an identifier before consuming
1527
1529
var look = self . lookahead ( )
1528
1530
let _ = look. consumeAttributeList ( )
1529
1531
let hasModifier = look. consume ( ifAny: [ ] , contextualKeywords: [ " mutating " , " nonmutating " , " __consuming " ] ) != nil
1530
- guard let ( kind, handle) = look. at ( anyIn: AccessorKind . self) else {
1532
+ guard let ( kind, handle) = look. at ( anyIn: AccessorKind . self) ?? forcedKind else {
1531
1533
return nil
1532
1534
}
1533
1535
@@ -1590,15 +1592,17 @@ extension Parser {
1590
1592
return specifiers
1591
1593
}
1592
1594
1593
- /// Parse the body of a variable declaration. This can include explicit
1594
- /// getters, setters, and observers, or the body of a computed property.
1595
+ /// Parse an accessor.
1596
+ mutating func parseAccessorDecl( ) -> RawAccessorDeclSyntax {
1597
+ let introducer = parseAccessorIntroducer ( forcedKind: ( . get, TokenConsumptionHandle ( tokenKind: . contextualKeyword, missing: true ) ) ) !
1598
+ return parseAccessorDecl ( introducer: introducer)
1599
+ }
1600
+
1601
+ /// Parse an accessor once we know we have an introducer
1595
1602
///
1596
1603
/// Grammar
1597
1604
/// =======
1598
1605
///
1599
- /// getter-setter-block → code-block
1600
- /// getter-setter-block → { getter-clause setter-clause opt }
1601
- /// getter-setter-block → { setter-clause getter-clause }
1602
1606
/// getter-clause → attributes opt mutation-modifier opt get code-block
1603
1607
/// setter-clause → attributes opt mutation-modifier opt set setter-name opt code-block
1604
1608
/// setter-name → ( identifier )
@@ -1610,6 +1614,63 @@ extension Parser {
1610
1614
/// willSet-didSet-block → { didSet-clause willSet-clause opt }
1611
1615
/// willSet-clause → attributes opt willSet setter-name opt code-block
1612
1616
/// didSet-clause → attributes opt didSet setter-name opt code-block
1617
+ private mutating func parseAccessorDecl(
1618
+ introducer: AccessorIntroducer
1619
+ ) -> RawAccessorDeclSyntax {
1620
+ // 'set' and 'willSet' can have an optional name. This isn't valid in a
1621
+ // protocol, but we parse and then reject it for better QoI.
1622
+ //
1623
+ // set-name ::= '(' identifier ')'
1624
+ let parameter : RawAccessorParameterSyntax ?
1625
+ if [ AccessorKind . set, . willSet, . didSet] . contains ( introducer. kind) , let lparen = self . consume ( if: . leftParen) {
1626
+ let ( unexpectedBeforeName, name) = self . expectIdentifier ( )
1627
+ let ( unexpectedBeforeRParen, rparen) = self . expect ( . rightParen)
1628
+ parameter = RawAccessorParameterSyntax (
1629
+ leftParen: lparen,
1630
+ unexpectedBeforeName,
1631
+ name: name,
1632
+ unexpectedBeforeRParen,
1633
+ rightParen: rparen,
1634
+ arena: self . arena
1635
+ )
1636
+ } else {
1637
+ parameter = nil
1638
+ }
1639
+
1640
+ // Next, parse effects specifiers. While it's only valid to have them
1641
+ // on 'get' accessors, we also emit diagnostics if they show up on others.
1642
+ let asyncKeyword : RawTokenSyntax ?
1643
+ let throwsKeyword : RawTokenSyntax ?
1644
+ if self . at ( anyIn: EffectsSpecifier . self) != nil {
1645
+ asyncKeyword = self . parseEffectsSpecifier ( )
1646
+ throwsKeyword = self . parseEffectsSpecifier ( )
1647
+ } else {
1648
+ asyncKeyword = nil
1649
+ throwsKeyword = nil
1650
+ }
1651
+
1652
+ let body = self . parseOptionalCodeBlock ( )
1653
+ return RawAccessorDeclSyntax (
1654
+ attributes: introducer. attributes,
1655
+ modifier: introducer. modifier,
1656
+ accessorKind: introducer. token,
1657
+ parameter: parameter,
1658
+ asyncKeyword: asyncKeyword,
1659
+ throwsKeyword: throwsKeyword,
1660
+ body: body,
1661
+ arena: self . arena
1662
+ )
1663
+ }
1664
+
1665
+ /// Parse the body of a variable declaration. This can include explicit
1666
+ /// getters, setters, and observers, or the body of a computed property.
1667
+ ///
1668
+ /// Grammar
1669
+ /// =======
1670
+ ///
1671
+ /// getter-setter-block → code-block
1672
+ /// getter-setter-block → { getter-clause setter-clause opt }
1673
+ /// getter-setter-block → { setter-clause getter-clause }
1613
1674
@_spi ( RawSyntax)
1614
1675
public mutating func parseGetSet( ) -> RawSubscriptDeclSyntax . Accessor {
1615
1676
// Parse getter and setter.
@@ -1664,52 +1725,7 @@ extension Parser {
1664
1725
)
1665
1726
}
1666
1727
1667
- // 'set' and 'willSet' can have an optional name. This isn't valid in a
1668
- // protocol, but we parse and then reject it for better QoI.
1669
- //
1670
- // set-name ::= '(' identifier ')'
1671
- let parameter : RawAccessorParameterSyntax ?
1672
- if [ AccessorKind . set, . willSet, . didSet] . contains ( introducer. kind) , let lparen = self . consume ( if: . leftParen) {
1673
- let ( unexpectedBeforeName, name) = self . expectIdentifier ( )
1674
- let ( unexpectedBeforeRParen, rparen) = self . expect ( . rightParen)
1675
- parameter = RawAccessorParameterSyntax (
1676
- leftParen: lparen,
1677
- unexpectedBeforeName,
1678
- name: name,
1679
- unexpectedBeforeRParen,
1680
- rightParen: rparen,
1681
- arena: self . arena
1682
- )
1683
- } else {
1684
- parameter = nil
1685
- }
1686
-
1687
- // Next, parse effects specifiers. While it's only valid to have them
1688
- // on 'get' accessors, we also emit diagnostics if they show up on others.
1689
- let asyncKeyword : RawTokenSyntax ?
1690
- let throwsKeyword : RawTokenSyntax ?
1691
- if self . at ( anyIn: EffectsSpecifier . self) != nil {
1692
- asyncKeyword = self . parseEffectsSpecifier ( )
1693
- throwsKeyword = self . parseEffectsSpecifier ( )
1694
- } else {
1695
- asyncKeyword = nil
1696
- throwsKeyword = nil
1697
- }
1698
-
1699
- let body = self . parseOptionalCodeBlock ( )
1700
-
1701
- elements. append (
1702
- RawAccessorDeclSyntax (
1703
- attributes: introducer. attributes,
1704
- modifier: introducer. modifier,
1705
- accessorKind: introducer. token,
1706
- parameter: parameter,
1707
- asyncKeyword: asyncKeyword,
1708
- throwsKeyword: throwsKeyword,
1709
- body: body,
1710
- arena: self . arena
1711
- )
1712
- )
1728
+ elements. append ( parseAccessorDecl ( introducer: introducer) )
1713
1729
}
1714
1730
}
1715
1731
0 commit comments