Skip to content

Commit 745922f

Browse files
authored
Merge pull request #727 from CodaFi/closure
2 parents 6cd32e4 + 3b255d6 commit 745922f

File tree

4 files changed

+53
-9
lines changed

4 files changed

+53
-9
lines changed

Sources/SwiftParser/Expressions.swift

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,12 +1668,18 @@ extension Parser {
16681668
arena: self.arena))
16691669
} while keepGoing != nil && loopProgress.evaluate(currentToken)
16701670
}
1671+
// We were promised a right square bracket, so we're going to get it.
1672+
var unexpectedNodes = [RawSyntax]()
1673+
while !self.at(.eof) && !self.at(.rightSquareBracket) && !self.at(.inKeyword) {
1674+
unexpectedNodes.append(RawSyntax(self.consumeAnyToken()))
1675+
}
16711676
let (unexpectedBeforeRSquare, rsquare) = self.expect(.rightSquareBracket)
1677+
unexpectedNodes.append(contentsOf: unexpectedBeforeRSquare?.elements ?? [])
16721678

16731679
captures = RawClosureCaptureSignatureSyntax(
16741680
leftSquare: lsquare,
16751681
items: elements.isEmpty ? nil : RawClosureCaptureItemListSyntax(elements: elements, arena: self.arena),
1676-
unexpectedBeforeRSquare,
1682+
unexpectedNodes.isEmpty ? nil : RawUnexpectedNodesSyntax(elements: unexpectedNodes, arena: self.arena),
16771683
rightSquare: rsquare, arena: self.arena)
16781684
} else {
16791685
captures = nil
@@ -1694,15 +1700,17 @@ extension Parser {
16941700
// Parse identifier (',' identifier)*
16951701
var keepGoing: RawTokenSyntax? = nil
16961702
repeat {
1703+
let unexpected: RawUnexpectedNodesSyntax?
16971704
let name: RawTokenSyntax
16981705
if self.currentToken.isIdentifier {
1706+
unexpected = nil
16991707
name = self.consumeIdentifier()
17001708
} else {
1701-
name = self.eat(.wildcardKeyword)
1709+
(unexpected, name) = self.expect(.wildcardKeyword)
17021710
}
17031711
keepGoing = consume(if: .comma)
17041712
params.append(RawClosureParamSyntax(
1705-
name: name, trailingComma: keepGoing, arena: self.arena))
1713+
unexpected, name: name, trailingComma: keepGoing, arena: self.arena))
17061714
} while keepGoing != nil && loopProgress.evaluate(currentToken)
17071715
}
17081716

@@ -1751,10 +1759,14 @@ extension Parser {
17511759
specifiers.append(self.consumeIdentifier())
17521760
if let lparen = self.consume(if: .leftParen) {
17531761
specifiers.append(lparen)
1754-
specifiers.append(self.expectWithoutLookahead(.identifier, "unsafe"))
1762+
if self.currentToken.tokenText == "safe" {
1763+
specifiers.append(self.expectWithoutLookahead(.identifier, "safe"))
1764+
} else {
1765+
specifiers.append(self.expectWithoutLookahead(.identifier, "unsafe"))
1766+
}
17551767
specifiers.append(self.expectWithoutLookahead(.rightParen))
17561768
}
1757-
} else if (self.currentToken.isIdentifier || self.at(.selfKeyword)) {
1769+
} else if self.currentToken.isIdentifier || self.at(.selfKeyword) {
17581770
let next = self.peek()
17591771
// "x = 42", "x," and "x]" are all strong captures of x.
17601772
guard next.tokenKind == .equal || next.tokenKind == .comma
@@ -1991,7 +2003,6 @@ extension Parser.Lookahead {
19912003
mutating func consumeEffectsSpecifiers() {
19922004
var loopProgress = LoopProgressCondition()
19932005
while self.currentToken.isEffectsSpecifier
1994-
&& !self.currentToken.isAtStartOfLine
19952006
&& loopProgress.evaluate(currentToken) {
19962007
self.consumeAnyToken()
19972008
}

Tests/SwiftParserTest/Assertions.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,25 @@ struct DiagnosticSpec {
6464
/// If not `nil`, assert that the diagnostic contains fix-its with these messages.
6565
/// Use the `fixedSource` parameter on `AssertParse` to check that applying the Fix-It yields the expected result.
6666
let fixIts: [String]?
67+
let file: StaticString
68+
let line: UInt
6769

68-
init(locationMarker: String = "DIAG", id: MessageID? = nil, message: String?, highlight: String? = nil, fixIts: [String]? = nil) {
70+
init(
71+
locationMarker: String = "DIAG",
72+
id: MessageID? = nil,
73+
message: String?,
74+
highlight: String? = nil,
75+
fixIts: [String]? = nil,
76+
file: StaticString = #file,
77+
line: UInt = #line
78+
) {
6979
self.locationMarker = locationMarker
7080
self.id = id
7181
self.message = message
7282
self.highlight = highlight
7383
self.fixIts = fixIts
84+
self.file = file
85+
self.line = line
7486
}
7587
}
7688

@@ -232,7 +244,7 @@ func AssertParse<Node: RawSyntaxNodeProtocol>(
232244
""", file: file, line: line)
233245
}
234246
for (diag, expectedDiag) in zip(diags, expectedDiagnostics) {
235-
AssertDiagnostic(diag, in: tree, markerLocations: markerLocations, expected: expectedDiag, file: file, line: line)
247+
AssertDiagnostic(diag, in: tree, markerLocations: markerLocations, expected: expectedDiag, file: expectedDiag.file, line: expectedDiag.line)
236248
}
237249

238250
// Applying Fix-Its

Tests/SwiftParserTest/Expressions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ final class ExpressionTests: XCTestCase {
443443
)
444444
}
445445

446-
func testClouserExpression() {
446+
func testClosureExpression() {
447447
AssertParse(
448448
"""
449449
let :(#^DIAG_1^#..)->

Tests/SwiftParserTest/Types.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,25 @@ final class TypeTests: XCTestCase {
3232
DiagnosticSpec(message: "Unexpected text '..' found in function type")
3333
])
3434
}
35+
36+
func testClosureSignatures() throws {
37+
AssertParse("""
38+
{ ()
39+
throws -> Void in }
40+
""",
41+
{ $0.parseClosureExpression() })
42+
43+
AssertParse("""
44+
{ [weak a, unowned(safe) self, b = 3] (a: Int, b: Int, _: Int) -> Int in }
45+
""",
46+
{ $0.parseClosureExpression() })
47+
48+
AssertParse("{[#^DIAG_1^#class]in#^DIAG_2^#",
49+
{ $0.parseClosureExpression() },
50+
diagnostics: [
51+
DiagnosticSpec(locationMarker: "DIAG_1", message: "Expected '' in closure capture item"),
52+
DiagnosticSpec(locationMarker: "DIAG_1", message: "Unexpected text 'class' found in closure capture signature"),
53+
DiagnosticSpec(locationMarker: "DIAG_2", message: "Expected '}' to end closure"),
54+
])
55+
}
3556
}

0 commit comments

Comments
 (0)