Skip to content

Commit 4f1286f

Browse files
authored
Merge pull request #756 from liamrosenfeld/677-fix
Fix parsing attributes at the start of an accessor
2 parents 689eb41 + 450fd89 commit 4f1286f

File tree

2 files changed

+39
-14
lines changed

2 files changed

+39
-14
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,33 +1519,37 @@ extension Parser {
15191519
struct AccessorIntroducer {
15201520
var attributes: RawAttributeListSyntax?
15211521
var modifier: RawDeclModifierSyntax?
1522-
var introducer: (AccessorKind, RawTokenSyntax)?
1522+
var kind: AccessorKind
1523+
var token: RawTokenSyntax
15231524
}
15241525

1525-
mutating func parseAccessorIntroducer() -> AccessorIntroducer {
1526+
mutating func parseAccessorIntroducer() -> AccessorIntroducer? {
1527+
// Check there is an identifier before consuming
1528+
var look = self.lookahead()
1529+
let _ = look.consumeAttributeList()
1530+
let hasModifier = look.consume(ifAny: [], contextualKeywords: ["mutating", "nonmutating", "__consuming"]) != nil
1531+
guard let (kind, handle) = look.at(anyIn: AccessorKind.self) else {
1532+
return nil
1533+
}
1534+
15261535
let attrs = self.parseAttributeList()
15271536

15281537
// Parse the contextual keywords for 'mutating' and 'nonmutating' before
15291538
// get and set.
15301539
let modifier: RawDeclModifierSyntax?
1531-
if let name = self.consume(ifAny: [], contextualKeywords: ["mutating", "nonmutating", "__consuming"]) {
1540+
if hasModifier {
15321541
modifier = RawDeclModifierSyntax(
1533-
name: name,
1542+
name: self.consumeAnyToken(),
15341543
detail: nil,
15351544
arena: self.arena
15361545
)
15371546
} else {
15381547
modifier = nil
15391548
}
15401549

1541-
guard let (kind, handle) = self.at(anyIn: AccessorKind.self) else {
1542-
return AccessorIntroducer(
1543-
attributes: attrs, modifier: modifier, introducer: nil)
1544-
}
1545-
15461550
let introducer = self.eat(handle)
15471551
return AccessorIntroducer(
1548-
attributes: attrs, modifier: modifier, introducer: (kind, introducer))
1552+
attributes: attrs, modifier: modifier, kind: kind, token: introducer)
15491553
}
15501554

15511555
@_spi(RawSyntax)
@@ -1612,8 +1616,7 @@ extension Parser {
16121616
do {
16131617
var loopProgress = LoopProgressCondition()
16141618
while !self.at(any: [.eof, .rightBrace]) && loopProgress.evaluate(currentToken) {
1615-
let introducer = self.parseAccessorIntroducer()
1616-
guard let (kind, kindToken) = introducer.introducer else {
1619+
guard let introducer = self.parseAccessorIntroducer() else {
16171620
// There can only be an implicit getter if no other accessors were
16181621
// seen before this one.
16191622
guard elements.isEmpty else {
@@ -1649,7 +1652,7 @@ extension Parser {
16491652
//
16501653
// set-name ::= '(' identifier ')'
16511654
let parameter: RawAccessorParameterSyntax?
1652-
if [ AccessorKind.set, .willSet, .didSet ].contains(kind), let lparen = self.consume(if: .leftParen) {
1655+
if [ AccessorKind.set, .willSet, .didSet ].contains(introducer.kind), let lparen = self.consume(if: .leftParen) {
16531656
let (unexpectedBeforeName, name) = self.expectIdentifier()
16541657
let (unexpectedBeforeRParen, rparen) = self.expect(.rightParen)
16551658
parameter = RawAccessorParameterSyntax(
@@ -1681,7 +1684,7 @@ extension Parser {
16811684
elements.append(RawAccessorDeclSyntax(
16821685
attributes: introducer.attributes,
16831686
modifier: introducer.modifier,
1684-
accessorKind: kindToken,
1687+
accessorKind: introducer.token,
16851688
parameter: parameter,
16861689
asyncKeyword: asyncKeyword,
16871690
throwsKeyword: throwsKeyword,

Tests/SwiftParserTest/Declarations.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,28 @@ final class DeclarationTests: XCTestCase {
188188
async let theVeryLastPhotoWeWant = fetch("4.jpg")
189189
"""
190190
)
191+
192+
AssertParse(
193+
"""
194+
var foo: Int {
195+
@available(swift 5.0)
196+
func myFun() -> Int {
197+
return 42
198+
}
199+
return myFun()
200+
}
201+
"""
202+
)
203+
204+
AssertParse(
205+
"""
206+
var foo: Int {
207+
mutating set {
208+
test += 1
209+
}
210+
}
211+
"""
212+
)
191213
}
192214

193215
func testTypealias() {

0 commit comments

Comments
 (0)