Skip to content

Commit 9e8d0ae

Browse files
authored
libSyntax: create syntax node for closure capture list. (#13408)
1 parent 91d0162 commit 9e8d0ae

File tree

4 files changed

+58
-5
lines changed

4 files changed

+58
-5
lines changed

lib/Parse/ParseExpr.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/ADT/SmallString.h"
2626
#include "llvm/ADT/StringSwitch.h"
2727
#include "llvm/ADT/Twine.h"
28+
#include "swift/Basic/Defer.h"
2829
#include "swift/Basic/StringExtras.h"
2930
#include "llvm/Support/Compiler.h"
3031
#include "llvm/Support/SaveAndRestore.h"
@@ -2375,11 +2376,22 @@ parseClosureSignatureIfPresent(SmallVectorImpl<CaptureListEntry> &captureList,
23752376
return false;
23762377
}
23772378

2378-
// At this point, we know we have a closure signature. Parse the capture list
2379-
// and parameters.
2380-
if (consumeIf(tok::l_square) &&
2381-
!consumeIf(tok::r_square)) {
2379+
if (Tok.is(tok::l_square) && peekToken().is(tok::r_square)) {
2380+
SyntaxParsingContext CaptureCtx(SyntaxContext,
2381+
SyntaxKind::ClosureCaptureSignature);
2382+
consumeToken(tok::l_square);
2383+
consumeToken(tok::r_square);
2384+
} else if (Tok.is(tok::l_square) && !peekToken().is(tok::r_square)) {
2385+
SyntaxParsingContext CaptureCtx(SyntaxContext,
2386+
SyntaxKind::ClosureCaptureSignature);
2387+
consumeToken(tok::l_square);
2388+
// At this point, we know we have a closure signature. Parse the capture list
2389+
// and parameters.
2390+
bool HasNext;
23822391
do {
2392+
SyntaxParsingContext CapturedItemCtx(SyntaxContext,
2393+
SyntaxKind::ClosureCaptureItem);
2394+
SWIFT_DEFER { HasNext = consumeIf(tok::comma); };
23832395
// Check for the strength specifier: "weak", "unowned", or
23842396
// "unowned(safe/unsafe)".
23852397
SourceLoc loc;
@@ -2419,6 +2431,9 @@ parseClosureSignatureIfPresent(SmallVectorImpl<CaptureListEntry> &captureList,
24192431
continue;
24202432
}
24212433

2434+
// Squash all tokens, if any, as the specifier of the captured item.
2435+
CapturedItemCtx.collectNodesInPlace(SyntaxKind::TokenList);
2436+
24222437
// The thing being capture specified is an identifier, or as an identifier
24232438
// followed by an expression.
24242439
Expr *initializer;
@@ -2472,8 +2487,9 @@ parseClosureSignatureIfPresent(SmallVectorImpl<CaptureListEntry> &captureList,
24722487
CurDeclContext);
24732488

24742489
captureList.push_back(CaptureListEntry(VD, PBD));
2475-
} while (consumeIf(tok::comma));
2490+
} while (HasNext);
24762491

2492+
SyntaxContext->collectNodesInPlace(SyntaxKind::ClosureCaptureItemList);
24772493
// The capture list needs to be closed off with a ']'.
24782494
if (!consumeIf(tok::r_square)) {
24792495
diagnose(Tok, diag::expected_capture_list_end_rsquare);

test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,13 @@ func tryfoo<FunctionSignature>() </FunctionSignature><CodeBlock>{<TryExpr>
126126
try! <IdentifierExpr>foo</IdentifierExpr>()</TryExpr><TryExpr>
127127
try? <IdentifierExpr>foo</IdentifierExpr>()</TryExpr><TryExpr>
128128
try! <MemberAccessExpr><IdentifierExpr>foo</IdentifierExpr>().bar</MemberAccessExpr>().foo().bar()</TryExpr>
129+
}</CodeBlock></FunctionDecl><FunctionDecl>
130+
131+
func closure<FunctionSignature>() </FunctionSignature><CodeBlock>{
132+
{<ClosureCaptureSignature>[<ClosureCaptureItem>weak <IdentifierExpr>a</IdentifierExpr>,</ClosureCaptureItem><ClosureCaptureItem>
133+
unowned(safe) self,</ClosureCaptureItem><ClosureCaptureItem>
134+
b = <IntegerLiteralExpr>3</IntegerLiteralExpr>,</ClosureCaptureItem><ClosureCaptureItem>
135+
unowned(unsafe) c = <MemberAccessExpr><IdentifierExpr>foo</IdentifierExpr>().bar</MemberAccessExpr></ClosureCaptureItem>] </ClosureCaptureSignature>in
136+
}
137+
{<ClosureCaptureSignature>[] </ClosureCaptureSignature>in }
129138
}</CodeBlock></FunctionDecl>

test/Syntax/round_trip_parse_gen.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,12 @@ func tryfoo() {
127127
try? foo()
128128
try! foo().bar().foo().bar()
129129
}
130+
131+
func closure() {
132+
{[weak a,
133+
unowned(safe) self,
134+
b = 3,
135+
unowned(unsafe) c = foo().bar] in
136+
}
137+
{[] in }
138+
}

utils/gyb_syntax_support/ExprNodes.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,23 @@
263263
children=[
264264
Child('Type', kind='Type'),
265265
]),
266+
267+
Node('ClosureCaptureItem', kind='Syntax',
268+
children=[
269+
Child("Specifier", kind='TokenList', is_optional=True),
270+
Child("Name", kind='IdentifierToken', is_optional=True),
271+
Child('AssignToken', kind='EqualToken', is_optional=True),
272+
Child("Expression", kind='Expr'),
273+
Child('TrailingComma', kind='CommaToken', is_optional=True),
274+
]),
275+
276+
Node('ClosureCaptureItemList', kind='SyntaxCollection',
277+
element='ClosureCaptureItem'),
278+
279+
Node('ClosureCaptureSignature', kind='Syntax',
280+
children=[
281+
Child('LeftSquare', kind='LeftSquareToken'),
282+
Child('Items', kind='ClosureCaptureItemList', is_optional=True),
283+
Child('RightSquare', kind='RightSquareToken'),
284+
]),
266285
]

0 commit comments

Comments
 (0)