@@ -1547,12 +1547,14 @@ extension Parser {
1547
1547
var token : RawTokenSyntax
1548
1548
}
1549
1549
1550
- mutating func parseAccessorIntroducer( ) -> AccessorIntroducer ? {
1550
+ mutating func parseAccessorIntroducer(
1551
+ forcedKind: ( AccessorKind , TokenConsumptionHandle ) ? = nil
1552
+ ) -> AccessorIntroducer ? {
1551
1553
// Check there is an identifier before consuming
1552
1554
var look = self . lookahead ( )
1553
1555
let _ = look. consumeAttributeList ( )
1554
1556
let hasModifier = look. consume ( ifAny: [ . contextualKeyword( . mutating) , . contextualKeyword( . nonmutating) , . contextualKeyword( . __consuming) ] ) != nil
1555
- guard let ( kind, handle) = look. at ( anyIn: AccessorKind . self) else {
1557
+ guard let ( kind, handle) = look. at ( anyIn: AccessorKind . self) ?? forcedKind else {
1556
1558
return nil
1557
1559
}
1558
1560
@@ -1615,15 +1617,17 @@ extension Parser {
1615
1617
return specifiers
1616
1618
}
1617
1619
1618
- /// Parse the body of a variable declaration. This can include explicit
1619
- /// getters, setters, and observers, or the body of a computed property.
1620
+ /// Parse an accessor.
1621
+ mutating func parseAccessorDecl( ) -> RawAccessorDeclSyntax {
1622
+ let introducer = parseAccessorIntroducer ( forcedKind: ( . get, TokenConsumptionHandle ( tokenKind: . contextualKeyword, missing: true ) ) ) !
1623
+ return parseAccessorDecl ( introducer: introducer)
1624
+ }
1625
+
1626
+ /// Parse an accessor once we know we have an introducer
1620
1627
///
1621
1628
/// Grammar
1622
1629
/// =======
1623
1630
///
1624
- /// getter-setter-block → code-block
1625
- /// getter-setter-block → { getter-clause setter-clause opt }
1626
- /// getter-setter-block → { setter-clause getter-clause }
1627
1631
/// getter-clause → attributes opt mutation-modifier opt get code-block
1628
1632
/// setter-clause → attributes opt mutation-modifier opt set setter-name opt code-block
1629
1633
/// setter-name → ( identifier )
@@ -1635,6 +1639,63 @@ extension Parser {
1635
1639
/// willSet-didSet-block → { didSet-clause willSet-clause opt }
1636
1640
/// willSet-clause → attributes opt willSet setter-name opt code-block
1637
1641
/// didSet-clause → attributes opt didSet setter-name opt code-block
1642
+ private mutating func parseAccessorDecl(
1643
+ introducer: AccessorIntroducer
1644
+ ) -> RawAccessorDeclSyntax {
1645
+ // 'set' and 'willSet' can have an optional name. This isn't valid in a
1646
+ // protocol, but we parse and then reject it for better QoI.
1647
+ //
1648
+ // set-name ::= '(' identifier ')'
1649
+ let parameter : RawAccessorParameterSyntax ?
1650
+ if [ AccessorKind . set, . willSet, . didSet] . contains ( introducer. kind) , let lparen = self . consume ( if: . leftParen) {
1651
+ let ( unexpectedBeforeName, name) = self . expectIdentifier ( )
1652
+ let ( unexpectedBeforeRParen, rparen) = self . expect ( . rightParen)
1653
+ parameter = RawAccessorParameterSyntax (
1654
+ leftParen: lparen,
1655
+ unexpectedBeforeName,
1656
+ name: name,
1657
+ unexpectedBeforeRParen,
1658
+ rightParen: rparen,
1659
+ arena: self . arena
1660
+ )
1661
+ } else {
1662
+ parameter = nil
1663
+ }
1664
+
1665
+ // Next, parse effects specifiers. While it's only valid to have them
1666
+ // on 'get' accessors, we also emit diagnostics if they show up on others.
1667
+ let asyncKeyword : RawTokenSyntax ?
1668
+ let throwsKeyword : RawTokenSyntax ?
1669
+ if self . at ( anyIn: EffectsSpecifier . self) != nil {
1670
+ asyncKeyword = self . parseEffectsSpecifier ( )
1671
+ throwsKeyword = self . parseEffectsSpecifier ( )
1672
+ } else {
1673
+ asyncKeyword = nil
1674
+ throwsKeyword = nil
1675
+ }
1676
+
1677
+ let body = self . parseOptionalCodeBlock ( )
1678
+ return RawAccessorDeclSyntax (
1679
+ attributes: introducer. attributes,
1680
+ modifier: introducer. modifier,
1681
+ accessorKind: introducer. token,
1682
+ parameter: parameter,
1683
+ asyncKeyword: asyncKeyword,
1684
+ throwsKeyword: throwsKeyword,
1685
+ body: body,
1686
+ arena: self . arena
1687
+ )
1688
+ }
1689
+
1690
+ /// Parse the body of a variable declaration. This can include explicit
1691
+ /// getters, setters, and observers, or the body of a computed property.
1692
+ ///
1693
+ /// Grammar
1694
+ /// =======
1695
+ ///
1696
+ /// getter-setter-block → code-block
1697
+ /// getter-setter-block → { getter-clause setter-clause opt }
1698
+ /// getter-setter-block → { setter-clause getter-clause }
1638
1699
@_spi ( RawSyntax)
1639
1700
public mutating func parseGetSet( ) -> RawSubscriptDeclSyntax . Accessor {
1640
1701
// Parse getter and setter.
@@ -1689,52 +1750,7 @@ extension Parser {
1689
1750
)
1690
1751
}
1691
1752
1692
- // 'set' and 'willSet' can have an optional name. This isn't valid in a
1693
- // protocol, but we parse and then reject it for better QoI.
1694
- //
1695
- // set-name ::= '(' identifier ')'
1696
- let parameter : RawAccessorParameterSyntax ?
1697
- if [ AccessorKind . set, . willSet, . didSet] . contains ( introducer. kind) , let lparen = self . consume ( if: . leftParen) {
1698
- let ( unexpectedBeforeName, name) = self . expectIdentifier ( )
1699
- let ( unexpectedBeforeRParen, rparen) = self . expect ( . rightParen)
1700
- parameter = RawAccessorParameterSyntax (
1701
- leftParen: lparen,
1702
- unexpectedBeforeName,
1703
- name: name,
1704
- unexpectedBeforeRParen,
1705
- rightParen: rparen,
1706
- arena: self . arena
1707
- )
1708
- } else {
1709
- parameter = nil
1710
- }
1711
-
1712
- // Next, parse effects specifiers. While it's only valid to have them
1713
- // on 'get' accessors, we also emit diagnostics if they show up on others.
1714
- let asyncKeyword : RawTokenSyntax ?
1715
- let throwsKeyword : RawTokenSyntax ?
1716
- if self . at ( anyIn: EffectsSpecifier . self) != nil {
1717
- asyncKeyword = self . parseEffectsSpecifier ( )
1718
- throwsKeyword = self . parseEffectsSpecifier ( )
1719
- } else {
1720
- asyncKeyword = nil
1721
- throwsKeyword = nil
1722
- }
1723
-
1724
- let body = self . parseOptionalCodeBlock ( )
1725
-
1726
- elements. append (
1727
- RawAccessorDeclSyntax (
1728
- attributes: introducer. attributes,
1729
- modifier: introducer. modifier,
1730
- accessorKind: introducer. token,
1731
- parameter: parameter,
1732
- asyncKeyword: asyncKeyword,
1733
- throwsKeyword: throwsKeyword,
1734
- body: body,
1735
- arena: self . arena
1736
- )
1737
- )
1753
+ elements. append ( parseAccessorDecl ( introducer: introducer) )
1738
1754
}
1739
1755
}
1740
1756
0 commit comments