Skip to content

Commit 5615b38

Browse files
committed
[CodeCompletion] Show 'return' completion by default when appropriate
Ideally we would have precise completion for all our keywords; for now, just imporove handling of 'return', which we can do by checking if the current context is a function/closure/init/subscript/etc. rdar://problem/26307555
1 parent 39e7c77 commit 5615b38

File tree

5 files changed

+91
-14
lines changed

5 files changed

+91
-14
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,7 +1361,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
13611361
void completeReturnStmt(CodeCompletionExpr *E) override;
13621362
void completeAfterPound(CodeCompletionExpr *E, StmtKind ParentKind) override;
13631363
void completeGenericParams(TypeLoc TL) override;
1364-
void addKeywords(CodeCompletionResultSink &Sink);
1364+
void addKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody);
13651365

13661366
void doneParsing() override;
13671367

@@ -4451,8 +4451,11 @@ static void addDeclKeywords(CodeCompletionResultSink &Sink) {
44514451
AddCSKeyword("convenience");
44524452
}
44534453

4454-
static void addStmtKeywords(CodeCompletionResultSink &Sink) {
4454+
static void addStmtKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody) {
44554455
auto AddKeyword = [&](StringRef Name, CodeCompletionKeywordKind Kind) {
4456+
if (!MaybeFuncBody && Kind == CodeCompletionKeywordKind::kw_return)
4457+
return;
4458+
44564459
CodeCompletionResultBuilder Builder(
44574460
Sink, CodeCompletionResult::ResultKind::Keyword,
44584461
SemanticContextKind::None, {});
@@ -4505,7 +4508,8 @@ static void addExprKeywords(CodeCompletionResultSink &Sink) {
45054508
}
45064509

45074510

4508-
void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink) {
4511+
void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
4512+
bool MaybeFuncBody) {
45094513
switch (Kind) {
45104514
case CompletionKind::None:
45114515
case CompletionKind::DotExpr:
@@ -4523,7 +4527,7 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink) {
45234527

45244528
case CompletionKind::StmtOrExpr:
45254529
addDeclKeywords(Sink);
4526-
addStmtKeywords(Sink);
4530+
addStmtKeywords(Sink, MaybeFuncBody);
45274531
SWIFT_FALLTHROUGH;
45284532
case CompletionKind::AssignmentRHS:
45294533
case CompletionKind::ReturnStmtExpr:
@@ -4778,8 +4782,15 @@ void CodeCompletionCallbacksImpl::doneParsing() {
47784782
return;
47794783
}
47804784

4785+
bool MaybeFuncBody = true;
4786+
if (CurDeclContext) {
4787+
auto *CD = CurDeclContext->getLocalContext();
4788+
if (!CD || CD->getContextKind() == DeclContextKind::Initializer ||
4789+
CD->getContextKind() == DeclContextKind::TopLevelCodeDecl)
4790+
MaybeFuncBody = false;
4791+
}
47814792
// Add keywords even if type checking fails completely.
4782-
addKeywords(CompletionContext.getResultSink());
4793+
addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);
47834794

47844795
if (!typecheckContext())
47854796
return;

test/IDE/complete_keywords.swift

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,47 @@
1-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_1 | FileCheck %s -check-prefix=KW_DECL_STMT
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_1 > %t.top1
2+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.top1
3+
// RUN: FileCheck %s -check-prefix=KW_NO_RETURN < %t.top1
24

3-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FUNC_BODY_1 | FileCheck %s -check-prefix=KW_DECL_STMT
4-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FUNC_BODY_2 | FileCheck %s -check-prefix=KW_DECL_STMT
5-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FUNC_BODY_3 | FileCheck %s -check-prefix=KW_DECL_STMT
6-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FUNC_BODY_4 | FileCheck %s -check-prefix=KW_DECL_STMT
7-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FUNC_BODY_5 | FileCheck %s -check-prefix=KW_DECL_STMT
5+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_2 > %t.top2
6+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.top2
7+
// RUN: FileCheck %s -check-prefix=KW_NO_RETURN < %t.top2
8+
9+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FUNC_BODY_1 > %t.func1
10+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.func1
11+
// RUN: FileCheck %s -check-prefix=KW_RETURN < %t.func1
12+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FUNC_BODY_2 > %t.func2
13+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.func2
14+
// RUN: FileCheck %s -check-prefix=KW_RETURN < %t.func2
15+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FUNC_BODY_3 > %t.func3
16+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.func3
17+
// RUN: FileCheck %s -check-prefix=KW_RETURN < %t.func3
18+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FUNC_BODY_4 > %t.func4
19+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.func4
20+
// RUN: FileCheck %s -check-prefix=KW_RETURN < %t.func4
21+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FUNC_BODY_5 > %t.func5
22+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.func5
23+
// RUN: FileCheck %s -check-prefix=KW_RETURN < %t.func5
24+
25+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_CLOSURE_1 > %t.clos1
26+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.clos1
27+
// RUN: FileCheck %s -check-prefix=KW_RETURN < %t.clos1
28+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_CLOSURE_2 > %t.clos2
29+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.clos2
30+
// RUN: FileCheck %s -check-prefix=KW_RETURN < %t.clos2
31+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_CLOSURE_3 > %t.clos3
32+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.clos3
33+
// RUN: FileCheck %s -check-prefix=KW_RETURN < %t.clos3
34+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_CLOSURE_4 > %t.clos4
35+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.clos4
36+
// RUN: FileCheck %s -check-prefix=KW_RETURN < %t.clos4
37+
38+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_SUBSCRIPT_1 > %t.subs
39+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.subs
40+
// RUN: FileCheck %s -check-prefix=KW_RETURN < %t.subs
41+
42+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_INIT_1 > %t.init
43+
// RUN: FileCheck %s -check-prefix=KW_DECL_STMT < %t.init
44+
// RUN: FileCheck %s -check-prefix=KW_RETURN < %t.init
845

946
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_NOMINAL_DECL_1 | FileCheck %s -check-prefix=KW_DECL
1047
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_NOMINAL_DECL_2 | FileCheck %s -check-prefix=KW_DECL
@@ -41,6 +78,9 @@
4178
// RUN: FileCheck %s -check-prefix=KW_EXPR < %t.expr6
4279
// RUN: FileCheck %s -check-prefix=KW_EXPR_NEG < %t.expr6
4380

81+
// KW_RETURN: Keyword[return]/None: return{{; name=.+$}}
82+
// KW_NO_RETURN-NOT: Keyword[return]
83+
4484
// KW_DECL: Begin completions
4585
// KW_DECL-DAG: Keyword[class]/None: class{{; name=.+$}}
4686
// KW_DECL-DAG: Keyword/None: convenience{{; name=.+$}}
@@ -121,7 +161,6 @@
121161
// KW_DECL_STMT-DAG: Keyword[for]/None: for{{; name=.+$}}
122162
// KW_DECL_STMT-DAG: Keyword[in]/None: in{{; name=.+$}}
123163
// KW_DECL_STMT-DAG: Keyword[while]/None: while{{; name=.+$}}
124-
// KW_DECL_STMT-DAG: Keyword[return]/None: return{{; name=.+$}}
125164
// KW_DECL_STMT-DAG: Keyword[break]/None: break{{; name=.+$}}
126165
// KW_DECL_STMT-DAG: Keyword[continue]/None: continue{{; name=.+$}}
127166
// KW_DECL_STMT-DAG: Keyword[fallthrough]/None: fallthrough{{; name=.+$}}
@@ -194,6 +233,10 @@
194233

195234
#^TOP_LEVEL_1^#
196235

236+
for _ in 1...10 {
237+
#^TOP_LEVEL_2^#
238+
}
239+
197240
func testInFuncBody1() {
198241
#^IN_FUNC_BODY_1^#
199242
}
@@ -224,6 +267,25 @@ class InClassFunc {
224267
}
225268
}
226269

270+
func testInClosure1() {
271+
{ #^IN_CLOSURE_1^# }
272+
}
273+
func testInClosure2() {
274+
{ #^IN_CLOSURE_2^#
275+
}
276+
struct InVarClosureInit {
277+
let x = { #^IN_CLOSURE_3^# }()
278+
}
279+
280+
{ #^IN_CLOSURE_4^# }
281+
282+
struct InSubscript {
283+
subscript(x: Int) -> Int { #^IN_SUBSCRIPT_1^# }
284+
}
285+
286+
struct InInit {
287+
init?() { #^IN_INIT_1^# }
288+
}
227289

228290
struct InStruct {
229291
#^IN_NOMINAL_DECL_1^#

test/SourceKit/CodeComplete/complete_requestlimit.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func test001() {
2323
// TOP_LEVEL_0_ALL-NEXT: if
2424
// TOP_LEVEL_0_ALL-NEXT: for
2525
// TOP_LEVEL_0_ALL-NEXT: while
26+
// TOP_LEVEL_0_ALL-NEXT: return
2627
// TOP_LEVEL_0_ALL-NEXT: func
2728
// TOP_LEVEL_0_ALL-NEXT: x
2829
// TOP_LEVEL_0_ALL-NEXT: y

test/SourceKit/CodeComplete/complete_sort_order.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ func test1() {
5252
// STMT: if
5353
// STMT: for
5454
// STMT: while
55+
// STMT: return
5556
// STMT: func
5657
// STMT: foo(a: Int)
5758

@@ -61,14 +62,14 @@ func test5() {
6162
#^STMT_1,r,ret,retur,return^#
6263
}
6364
// STMT_1-LABEL: Results for filterText: r [
65+
// STMT_1-NEXT: return
6466
// STMT_1-NEXT: retLocal
6567
// STMT_1-NEXT: repeat
66-
// STMT_1-NEXT: return
6768
// STMT_1-NEXT: required
6869
// STMT_1: ]
6970
// STMT_1-LABEL: Results for filterText: ret [
70-
// STMT_1-NEXT: retLocal
7171
// STMT_1-NEXT: return
72+
// STMT_1-NEXT: retLocal
7273
// STMT_1-NEXT: repeat
7374
// STMT_1: ]
7475
// STMT_1-LABEL: Results for filterText: retur [

tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ static bool isHighPriorityKeyword(CodeCompletionKeywordKind kind) {
439439
case CodeCompletionKeywordKind::kw_if:
440440
case CodeCompletionKeywordKind::kw_for:
441441
case CodeCompletionKeywordKind::kw_while:
442+
case CodeCompletionKeywordKind::kw_return:
442443
case CodeCompletionKeywordKind::kw_func:
443444
return true;
444445
default:
@@ -739,6 +740,7 @@ static int compareHighPriorityKeywords(Item &a_, Item &b_) {
739740
CodeCompletionKeywordKind::kw_if,
740741
CodeCompletionKeywordKind::kw_for,
741742
CodeCompletionKeywordKind::kw_while,
743+
CodeCompletionKeywordKind::kw_return,
742744
CodeCompletionKeywordKind::kw_func,
743745
};
744746
auto size = sizeof(order) / sizeof(order[0]);

0 commit comments

Comments
 (0)