Skip to content

Commit 3d80635

Browse files
committed
[CodeCompletion] Fix completion for local decls in trailing closure
Previously, local decls in trailing closure didn't show up if the closure had preceding arguments and the completion was triggered at beginning position of expression context. like: funcName(x: arg1) { var localVar = 12 if <HERE> } The completion mode used to be overwritten in 'completeCallArg()' which is called from 'parseExprCallSuffix(). We should detect completion for immediate argument position in 'parseExprList()'. rdar://problem/41869885
1 parent 5db65bf commit 3d80635

File tree

4 files changed

+42
-47
lines changed

4 files changed

+42
-47
lines changed

include/swift/Parse/CodeCompletionCallbacks.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ class CodeCompletionCallbacks {
196196

197197
virtual void completeAssignmentRHS(AssignExpr *E) = 0;
198198

199-
virtual void completeCallArg(CallExpr *E) = 0;
199+
virtual void completeCallArg(CodeCompletionExpr *E) = 0;
200200

201201
virtual void completeReturnStmt(CodeCompletionExpr *E) = 0;
202202

lib/IDE/CodeCompletion.cpp

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,7 +1296,6 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
12961296
CodeCompletionConsumer &Consumer;
12971297
CodeCompletionExpr *CodeCompleteTokenExpr = nullptr;
12981298
AssignExpr *AssignmentExpr;
1299-
CallExpr *FuncCallExpr;
13001299
CompletionKind Kind = CompletionKind::None;
13011300
Expr *ParsedExpr = nullptr;
13021301
SourceLoc DotLoc;
@@ -1462,7 +1461,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
14621461
void completeUnresolvedMember(CodeCompletionExpr *E,
14631462
SourceLoc DotLoc) override;
14641463
void completeAssignmentRHS(AssignExpr *E) override;
1465-
void completeCallArg(CallExpr *E) override;
1464+
void completeCallArg(CodeCompletionExpr *E) override;
14661465
void completeReturnStmt(CodeCompletionExpr *E) override;
14671466
void completeYieldStmt(CodeCompletionExpr *E,
14681467
Optional<unsigned> yieldIndex) override;
@@ -3952,22 +3951,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
39523951
return !ExpectedTypes.empty() || !ExpectedNames.empty();
39533952
}
39543953

3955-
bool getCallArgCompletions(DeclContext &DC, CallExpr *CallE, Expr *CCExpr) {
3956-
std::vector<Type> ExpectedTypes;
3957-
std::vector<StringRef> ExpectedNames;
3958-
if (!collectArgumentExpectation(DC, CallE, CCExpr, ExpectedTypes,
3959-
ExpectedNames))
3960-
return false;
3961-
3962-
addArgNameCompletionResults(ExpectedNames);
3963-
if (!ExpectedTypes.empty()) {
3964-
setExpectedTypes(ExpectedTypes);
3965-
getValueCompletionsInDeclContext(CCExpr->getStartLoc(), DefaultFilter);
3966-
}
3967-
3968-
return true;
3969-
}
3970-
39713954
void getTypeContextEnumElementCompletions(SourceLoc Loc) {
39723955
llvm::SaveAndRestore<LookupKind> ChangeLookupKind(
39733956
Kind, LookupKind::EnumElement);
@@ -4654,14 +4637,10 @@ void CodeCompletionCallbacksImpl::completeAssignmentRHS(AssignExpr *E) {
46544637
Kind = CompletionKind::AssignmentRHS;
46554638
}
46564639

4657-
void CodeCompletionCallbacksImpl::completeCallArg(CallExpr *E) {
4658-
if (Kind == CompletionKind::PostfixExprBeginning ||
4659-
Kind == CompletionKind::None) {
4660-
CurDeclContext = P.CurDeclContext;
4661-
Kind = CompletionKind::CallArg;
4662-
FuncCallExpr = E;
4663-
ParsedExpr = E;
4664-
}
4640+
void CodeCompletionCallbacksImpl::completeCallArg(CodeCompletionExpr *E) {
4641+
CurDeclContext = P.CurDeclContext;
4642+
CodeCompleteTokenExpr = E;
4643+
Kind = CompletionKind::CallArg;
46654644
}
46664645

46674646
void CodeCompletionCallbacksImpl::completeReturnStmt(CodeCompletionExpr *E) {
@@ -5586,10 +5565,17 @@ void CodeCompletionCallbacksImpl::doneParsing() {
55865565
break;
55875566
}
55885567
case CompletionKind::CallArg : {
5589-
if (!CodeCompleteTokenExpr || !Lookup.getCallArgCompletions(*CurDeclContext,
5590-
FuncCallExpr,
5591-
CodeCompleteTokenExpr))
5592-
DoPostfixExprBeginning();
5568+
::CodeCompletionTypeContextAnalyzer Analyzer(CurDeclContext,
5569+
CodeCompleteTokenExpr);
5570+
SmallVector<Type, 2> PossibleTypes;
5571+
SmallVector<StringRef, 2> PossibleNames;
5572+
Analyzer.Analyze(PossibleTypes, PossibleNames);
5573+
if (!PossibleNames.empty()) {
5574+
Lookup.addArgNameCompletionResults(PossibleNames);
5575+
break;
5576+
}
5577+
Lookup.setExpectedTypes(PossibleTypes);
5578+
DoPostfixExprBeginning();
55935579
break;
55945580
}
55955581

lib/Parse/ParseExpr.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2921,6 +2921,15 @@ ParserStatus Parser::parseExprList(tok leftTok, tok rightTok,
29212921
SubExpr = new(Context) UnresolvedDeclRefExpr(OperName,
29222922
DeclRefKind::Ordinary,
29232923
DeclNameLoc(Loc));
2924+
} else if (Kind == SyntaxKind::FunctionCallArgumentList &&
2925+
Tok.is(tok::code_complete)) {
2926+
// Handle call arguments specially because it may need argument labels.
2927+
auto CCExpr = new (Context) CodeCompletionExpr(Tok.getLoc());
2928+
if (CodeCompletion)
2929+
CodeCompletion->completeCallArg(CCExpr);
2930+
consumeIf(tok::code_complete);
2931+
SubExpr = CCExpr;
2932+
Status.setHasCodeCompletion();
29242933
} else {
29252934
auto ParsedSubExpr = parseExpr(diag::expected_expr_in_expr_list);
29262935
SubExpr = ParsedSubExpr.getPtrOrNull();
@@ -3188,20 +3197,10 @@ Parser::parseExprCallSuffix(ParserResult<Expr> fn, bool isExprBasic) {
31883197
SyntaxKind::FunctionCallArgumentList);
31893198

31903199
// Form the call.
3191-
auto Result = makeParserResult(status | fn,
3192-
CallExpr::create(Context, fn.get(), lParenLoc,
3193-
args, argLabels, argLabelLocs,
3194-
rParenLoc, trailingClosure,
3195-
/*implicit=*/false));
3196-
3197-
if (status.hasCodeCompletion()) {
3198-
if (CodeCompletion) {
3199-
CodeCompletion->completeCallArg(Result.get());
3200-
}
3201-
Result.setHasCodeCompletion();
3202-
}
3203-
3204-
return Result;
3200+
return makeParserResult(
3201+
status | fn, CallExpr::create(Context, fn.get(), lParenLoc, args,
3202+
argLabels, argLabelLocs, rParenLoc,
3203+
trailingClosure, /*implicit=*/false));
32053204
}
32063205

32073206
/// parseExprCollection - Parse a collection literal expression.

test/IDE/complete_call_arg.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
// RUN-FIXME: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERLOAD1 | %FileCheck %s -check-prefix=OVERLOAD1
1111
// RUN-FIXME: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERLOAD2 | %FileCheck %s -check-prefix=OVERLOAD2
12-
// RUN-FIXME: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERLOAD3 | %FileCheck %s -check-prefix=OVERLOAD3
13-
// RUN-FIXME: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERLOAD4 | %FileCheck %s -check-prefix=OVERLOAD4
12+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERLOAD3 | %FileCheck %s -check-prefix=OVERLOAD3
13+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERLOAD4 | %FileCheck %s -check-prefix=OVERLOAD4
1414

1515
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MEMBER1 | %FileCheck %s -check-prefix=MEMBER1
1616
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MEMBER2 | %FileCheck %s -check-prefix=MEMBER2
@@ -425,3 +425,13 @@ func curry<T1, T2, R>(_ f: @escaping (T1, T2) -> R) -> (T1) -> (T2) -> R {
425425
// NESTED_CLOSURE: Decl[LocalVar]/Local: t2; name=t2
426426
// NESTED_CLOSURE: Decl[LocalVar]/Local: t1[#T1#]; name=t1
427427
}
428+
429+
func trailingClosureLocal(x: Int, fn: (Int) -> Void) {
430+
trailingClosureLocal(x: 1) { localArg in
431+
var localVar = 1
432+
if #^TRAILING_CLOSURE_LOCAL^#
433+
}
434+
// TRAILING_CLOSURE_LOCAL: Begin completions
435+
// TRAILING_CLOSURE_LOCAL: Decl[LocalVar]/Local: localArg[#Int#]; name=localArg
436+
// TRAILING_CLOSURE_LOCAL: Decl[LocalVar]/Local: localVar[#Int#]; name=localVar
437+
}

0 commit comments

Comments
 (0)