Skip to content

Commit b394e35

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 2ace212 commit b394e35

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
@@ -1467,6 +1467,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
14671467
void completeReturnStmt(CodeCompletionExpr *E) override;
14681468
void completeAfterPound(CodeCompletionExpr *E, StmtKind ParentKind) override;
14691469
void completeGenericParams(TypeLoc TL) override;
1470+
void completeAfterIfStmt(bool hasElse) override;
14701471
void addKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody);
14711472

14721473
void doneParsing() override;
@@ -4745,6 +4746,15 @@ void CodeCompletionCallbacksImpl::completeAfterPound(CodeCompletionExpr *E,
47454746
ParentStmtKind = ParentKind;
47464747
}
47474748

4749+
void CodeCompletionCallbacksImpl::completeAfterIfStmt(bool hasElse) {
4750+
CurDeclContext = P.CurDeclContext;
4751+
if (hasElse) {
4752+
Kind = CompletionKind::AfterIfStmtElse;
4753+
} else {
4754+
Kind = CompletionKind::StmtOrExpr;
4755+
}
4756+
}
4757+
47484758
void CodeCompletionCallbacksImpl::completeGenericParams(TypeLoc TL) {
47494759
CurDeclContext = P.CurDeclContext;
47504760
Kind = CompletionKind::GenericParams;
@@ -4898,6 +4908,10 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
48984908
addDeclKeywords(Sink);
48994909
addLetVarKeywords(Sink);
49004910
break;
4911+
4912+
case CompletionKind::AfterIfStmtElse:
4913+
addKeyword(Sink, "if", CodeCompletionKeywordKind::kw_if);
4914+
break;
49014915
}
49024916
}
49034917

@@ -5474,6 +5488,9 @@ void CodeCompletionCallbacksImpl::doneParsing() {
54745488
}
54755489
}
54765490
break;
5491+
case CompletionKind::AfterIfStmtElse:
5492+
// Handled earlier by keyword completions.
5493+
break;
54775494
}
54785495

54795496
if (Lookup.RequestedCachedResults) {

lib/Parse/ParseStmt.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,10 +1545,20 @@ ParserResult<Stmt> Parser::parseStmtIf(LabeledStmtInfo LabelInfo) {
15451545
if (Tok.is(tok::kw_if)) {
15461546
SyntaxParsingContext ElseIfCtxt(SyntaxContext, SyntaxKind::IfStmt);
15471547
ElseBody = parseStmtIf(LabeledStmtInfo());
1548+
} else if (Tok.is(tok::code_complete)) {
1549+
if (CodeCompletion)
1550+
CodeCompletion->completeAfterIfStmt(/*hasElse*/true);
1551+
Status.setHasCodeCompletion();
1552+
consumeToken(tok::code_complete);
15481553
} else {
15491554
ElseBody = parseBraceItemList(diag::expected_lbrace_after_else);
15501555
}
15511556
Status |= ElseBody;
1557+
} else if (Tok.is(tok::code_complete)) {
1558+
if (CodeCompletion)
1559+
CodeCompletion->completeAfterIfStmt(/*hasElse*/false);
1560+
Status.setHasCodeCompletion();
1561+
consumeToken(tok::code_complete);
15521562
}
15531563

15541564
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)