Skip to content

Commit 4e8d98d

Browse files
committed
[CodeCompletion] Completion inside closure capture list
1 parent 5cf87d3 commit 4e8d98d

File tree

3 files changed

+42
-7
lines changed

3 files changed

+42
-7
lines changed

lib/Parse/ParseExpr.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2575,7 +2575,7 @@ ParserStatus Parser::parseClosureSignatureIfPresent(
25752575
if (!consumeIf(tok::r_paren, ownershipLocEnd))
25762576
diagnose(Tok, diag::attr_unowned_expected_rparen);
25772577
}
2578-
} else if (Tok.isAny(tok::identifier, tok::kw_self) &&
2578+
} else if (Tok.isAny(tok::identifier, tok::kw_self, tok::code_complete) &&
25792579
peekToken().isAny(tok::equal, tok::comma, tok::r_square)) {
25802580
// "x = 42", "x," and "x]" are all strong captures of x.
25812581
} else {
@@ -2584,7 +2584,7 @@ ParserStatus Parser::parseClosureSignatureIfPresent(
25842584
continue;
25852585
}
25862586

2587-
if (Tok.isNot(tok::identifier, tok::kw_self)) {
2587+
if (Tok.isNot(tok::identifier, tok::kw_self, tok::code_complete)) {
25882588
diagnose(Tok, diag::expected_capture_specifier_name);
25892589
skipUntil(tok::comma, tok::r_square);
25902590
continue;
@@ -2602,10 +2602,20 @@ ParserStatus Parser::parseClosureSignatureIfPresent(
26022602
if (peekToken().isNot(tok::equal)) {
26032603
// If this is the simple case, then the identifier is both the name and
26042604
// the expression to capture.
2605-
name = Context.getIdentifier(Tok.getText());
2606-
auto initializerResult = parseExprIdentifier();
2607-
status |= initializerResult;
2608-
initializer = initializerResult.get();
2605+
if (!Tok.is(tok::code_complete)) {
2606+
name = Context.getIdentifier(Tok.getText());
2607+
auto initializerResult = parseExprIdentifier();
2608+
status |= initializerResult;
2609+
initializer = initializerResult.get();
2610+
} else {
2611+
auto CCE = new (Context) CodeCompletionExpr(Tok.getLoc());
2612+
if (CodeCompletion)
2613+
CodeCompletion->completePostfixExprBeginning(CCE);
2614+
name = Identifier();
2615+
initializer = CCE;
2616+
consumeToken();
2617+
status.setHasCodeCompletion();
2618+
}
26092619

26102620
// It is a common error to try to capture a nested field instead of just
26112621
// a local name, reject it with a specific error message.
@@ -2617,7 +2627,13 @@ ParserStatus Parser::parseClosureSignatureIfPresent(
26172627

26182628
} else {
26192629
// Otherwise, the name is a new declaration.
2620-
consumeIdentifier(name, /*diagnoseDollarPrefix=*/true);
2630+
if (!Tok.is(tok::code_complete)) {
2631+
consumeIdentifier(name, /*diagnoseDollarPrefix=*/true);
2632+
} else {
2633+
// Ignore completion token because it's a new declaration.
2634+
name = Identifier();
2635+
consumeToken(tok::code_complete);
2636+
}
26212637
equalLoc = consumeToken(tok::equal);
26222638

26232639
auto ExprResult = parseExpr(diag::expected_init_capture_specifier);

test/IDE/complete_concurrency_specifier.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,12 @@ _ = { () #^CLOSURE_WITHARROW?check=SPECIFIER^# -> Void in }
4343
_ = { () async #^CLOSURE_WITHASYNCARROW?check=SPECIFIER_WITHASYNC^# -> Void in }
4444
_ = { () throws #^CLOSURE_WITHTHROWSARROW?check=SPECIFIER_WITHTHROWS^# -> Void in }
4545
_ = { () async throws #^CLOSURE_WITHASYNCTHROWSARROW?check=SPECIFIER_WITHASYNCTHROWS^# -> Void in }
46+
47+
_ = { arg #^CLOSURE2?check=SPECIFIER^# in }
48+
_ = { arg async #^CLOSURE2_WITHASYNC?check=SPECIFIER_WITHASYNC^# in }
49+
_ = { arg throws #^CLOSURE2_WITHTHROWS?check=SPECIFIER_WITHTHROWS^# in }
50+
_ = { arg async throws #^CLOSURE2_WITHAASYNCTHROWS?check=SPECIFIER_WITHASYNCTHROWS^# in }
51+
_ = { arg #^CLOSURE2_WITHARROW?check=SPECIFIER^# -> Void in }
52+
_ = { arg async #^CLOSURE2_WITHASYNCARROW?check=SPECIFIER_WITHASYNC^# -> Void in }
53+
_ = { arg throws #^CLOSURE2_WITHTHROWSARROW?check=SPECIFIER_WITHTHROWS^# -> Void in }
54+
_ = { arg async throws #^CLOSURE2_WITHASYNCTHROWSARROW?check=SPECIFIER_WITHASYNCTHROWS^# -> Void in }

test/IDE/complete_in_closures.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,4 +385,14 @@ func testSignature() {
385385

386386
accept { (arg1: #^PARAMTYPE_1?check=WITH_GLOBAL_DECLS^#) in }
387387
accept { (arg1: Int, arg2: #^PARAMTYPE_2?check=WITH_GLOBAL_DECLS^#) in }
388+
389+
accept { [#^CAPTURE_1?check=WITH_GLOBAL_DECLS^#] in }
390+
accept { [weak #^CAPTURE_2?check=WITH_GLOBAL_DECLS^#] in }
391+
accept { [#^CAPTURE_3?check=EMPTY^# = capture] in }
392+
accept { [weak #^CAPTURE_4?check=EMPTY^# = capture] in }
393+
394+
accept { () -> #^RESULTTYPE_1?check=WITH_GLOBAL_DECLS^# in }
395+
accept { arg1, arg2 -> #^RESULTTYPE_2?check=WITH_GLOBAL_DECLS^# in }
396+
397+
// NOTE: For effects specifiers completion (e.g. '() <HERE> -> Void') see test/IDE/complete_concurrency_specifier.swift
388398
}

0 commit comments

Comments
 (0)