[CodeCompletion] Suggest 'in' after expression in closure

func test(value: [Int]) {
    value.map { value <HERE> }
  }

In this case 'value' in the closure is ambiguous between an expression
referring the outer function parameter, or a parameter declaration in
the closure. Previously, code completion only considered the former and
suggest the members of '[Int]', but not 'in' keyword. As a result, when
the user actually want to type 'in' here, they needed to hit 'esc' to
cancel the code completion.

In this change, suggest 'in' keyword even without a newline, as long as
the current decl context is a closure and it doesn't have 'in' in it.

Also previously 'in' was suggested even outside the closure and even it
already had the explict 'in'. This PR limit suggesting 'in' inside
closures without explicit 'in'.

rdar://80489548
This commit is contained in:
Rintaro Ishizaki
2022-04-29 16:39:09 -07:00
parent 88b81de9e5
commit 1e018989c8
4 changed files with 70 additions and 20 deletions

View File

@@ -816,6 +816,12 @@ static void addStmtKeywords(CodeCompletionResultSink &Sink, DeclContext *DC,
auto AddStmtKeyword = [&](StringRef Name, CodeCompletionKeywordKind Kind) {
if (!MaybeFuncBody && Kind == CodeCompletionKeywordKind::kw_return)
return;
// 'in' keyword is added in 'addClosureSignatureKeywordsIfApplicable' if
// needed.
if (Kind == CodeCompletionKeywordKind::kw_in)
return;
addKeyword(Sink, Name, Kind, "", flair);
};
#define STMT_KEYWORD(kw) AddStmtKeyword(#kw, CodeCompletionKeywordKind::kw_##kw);
@@ -896,6 +902,18 @@ static void addAnyTypeKeyword(CodeCompletionResultSink &Sink, Type T) {
Builder.addTypeAnnotation(T, PrintOptions());
}
static void
addClosureSignatureKeywordsIfApplicable(CodeCompletionResultSink &Sink,
DeclContext *DC) {
ClosureExpr *closure = dyn_cast<ClosureExpr>(DC);
if (!closure)
return;
if (closure->getInLoc().isValid())
return;
addKeyword(Sink, "in", CodeCompletionKeywordKind::kw_in);
}
void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
bool MaybeFuncBody) {
switch (Kind) {
@@ -950,6 +968,8 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
addDeclKeywords(Sink, CurDeclContext,
Context.LangOpts.EnableExperimentalConcurrency);
addStmtKeywords(Sink, CurDeclContext, MaybeFuncBody);
addClosureSignatureKeywordsIfApplicable(Sink, CurDeclContext);
LLVM_FALLTHROUGH;
case CompletionKind::ReturnStmtExpr:
case CompletionKind::YieldStmtExpr:
@@ -974,6 +994,11 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
break;
case CompletionKind::PostfixExpr:
// Suggest 'in' for '{ value <HERE>'.
if (HasSpace)
addClosureSignatureKeywordsIfApplicable(Sink, CurDeclContext);
break;
case CompletionKind::CaseStmtBeginning:
case CompletionKind::TypeIdentifierWithDot:
case CompletionKind::TypeIdentifierWithoutDot: