Skip to content

Commit dee5110

Browse files
committed
[codecomplete] Add completion of if after else
At some point we stopped completing keywords after `else` in an if statement. Bring back the completion of `if`, which is the only valid continuation other than a brace. rdar://37467474
1 parent 8ab8888 commit dee5110

File tree

5 files changed

+56
-0
lines changed

5 files changed

+56
-0
lines changed

include/swift/IDE/CodeCompletion.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ enum class CompletionKind {
503503
ReturnStmtExpr,
504504
ForEachSequence,
505505
AfterPound,
506+
AfterIfStmtElse,
506507
GenericParams,
507508
SwiftKeyPath,
508509
};

include/swift/Parse/CodeCompletionCallbacks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ class CodeCompletionCallbacks {
202202

203203
virtual void completeAfterPound(CodeCompletionExpr *E, StmtKind ParentKind) = 0;
204204

205+
virtual void completeAfterIfStmt(bool hasElse) = 0;
206+
205207
virtual void completeGenericParams(TypeLoc TL) = 0;
206208

207209
/// \brief Signals that the AST for the all the delayed-parsed code was

lib/IDE/CodeCompletion.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
14611461
void completeReturnStmt(CodeCompletionExpr *E) override;
14621462
void completeAfterPound(CodeCompletionExpr *E, StmtKind ParentKind) override;
14631463
void completeGenericParams(TypeLoc TL) override;
1464+
void completeAfterIfStmt(bool hasElse) override;
14641465
void addKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody);
14651466

14661467
void doneParsing() override;
@@ -4844,6 +4845,15 @@ void CodeCompletionCallbacksImpl::completeAfterPound(CodeCompletionExpr *E,
48444845
ParentStmtKind = ParentKind;
48454846
}
48464847

4848+
void CodeCompletionCallbacksImpl::completeAfterIfStmt(bool hasElse) {
4849+
CurDeclContext = P.CurDeclContext;
4850+
if (hasElse) {
4851+
Kind = CompletionKind::AfterIfStmtElse;
4852+
} else {
4853+
Kind = CompletionKind::StmtOrExpr;
4854+
}
4855+
}
4856+
48474857
void CodeCompletionCallbacksImpl::completeGenericParams(TypeLoc TL) {
48484858
CurDeclContext = P.CurDeclContext;
48494859
Kind = CompletionKind::GenericParams;
@@ -5000,6 +5010,10 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
50005010
addDeclKeywords(Sink);
50015011
addLetVarKeywords(Sink);
50025012
break;
5013+
5014+
case CompletionKind::AfterIfStmtElse:
5015+
addKeyword(Sink, "if", CodeCompletionKeywordKind::kw_if);
5016+
break;
50035017
}
50045018
}
50055019

@@ -5558,6 +5572,9 @@ void CodeCompletionCallbacksImpl::doneParsing() {
55585572
}
55595573
}
55605574
break;
5575+
case CompletionKind::AfterIfStmtElse:
5576+
// Handled earlier by keyword completions.
5577+
break;
55615578
}
55625579

55635580
if (Lookup.RequestedCachedResults) {

lib/Parse/ParseStmt.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,10 +1538,20 @@ ParserResult<Stmt> Parser::parseStmtIf(LabeledStmtInfo LabelInfo) {
15381538
if (Tok.is(tok::kw_if)) {
15391539
SyntaxParsingContext ElseIfCtxt(SyntaxContext, SyntaxKind::IfStmt);
15401540
ElseBody = parseStmtIf(LabeledStmtInfo());
1541+
} else if (Tok.is(tok::code_complete)) {
1542+
if (CodeCompletion)
1543+
CodeCompletion->completeAfterIfStmt(/*hasElse*/true);
1544+
Status.setHasCodeCompletion();
1545+
consumeToken(tok::code_complete);
15411546
} else {
15421547
ElseBody = parseBraceItemList(diag::expected_lbrace_after_else);
15431548
}
15441549
Status |= ElseBody;
1550+
} else if (Tok.is(tok::code_complete)) {
1551+
if (CodeCompletion)
1552+
CodeCompletion->completeAfterIfStmt(/*hasElse*/false);
1553+
Status.setHasCodeCompletion();
1554+
consumeToken(tok::code_complete);
15451555
}
15461556

15471557
return makeParserResult(

test/IDE/complete_keywords.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@
66
// RUN: %FileCheck %s -check-prefix=KW_DECL_STMT < %t.top2
77
// RUN: %FileCheck %s -check-prefix=KW_NO_RETURN < %t.top2
88

9+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_AFTER_IF_1 > %t.top3
10+
// RUN: %FileCheck %s -check-prefix=KW_DECL_STMT < %t.top3
11+
// RUN: %FileCheck %s -check-prefix=KW_NO_RETURN < %t.top3
12+
13+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_AFTER_IF_ELSE_1 | %FileCheck %s -check-prefix=AFTER_IF_ELSE
14+
15+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=AFTER_IF_1 > %t.if1
16+
// RUN: %FileCheck %s -check-prefix=KW_DECL_STMT < %t.if1
17+
// RUN: %FileCheck %s -check-prefix=KW_RETURN < %t.if1
18+
19+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=AFTER_IF_ELSE_1 | %FileCheck %s -check-prefix=AFTER_IF_ELSE
20+
921
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IN_FUNC_BODY_1 > %t.func1
1022
// RUN: %FileCheck %s -check-prefix=KW_DECL_STMT < %t.func1
1123
// RUN: %FileCheck %s -check-prefix=KW_RETURN < %t.func1
@@ -237,6 +249,20 @@ for _ in 1...10 {
237249
#^TOP_LEVEL_2^#
238250
}
239251

252+
if true {} #^TOP_LEVEL_AFTER_IF_1^#
253+
254+
if true {} else #^TOP_LEVEL_AFTER_IF_ELSE_1^# {}
255+
256+
// AFTER_IF_ELSE: Begin completions, 1 items
257+
// AFTER_IF_ELSE: Keyword[if]/None: if;
258+
259+
func testAfterIf1() {
260+
if true {} #^AFTER_IF_1^#
261+
}
262+
func testAfterIfElse1() {
263+
if true {} else #^AFTER_IF_ELSE_1^# {}
264+
}
265+
240266
func testInFuncBody1() {
241267
#^IN_FUNC_BODY_1^#
242268
}

0 commit comments

Comments
 (0)