Skip to content

Commit 1e8c644

Browse files
committed
[CodeCompletion] Don't discard parsed expression in incomplete ternary
If we are code-completion, we need to keep the parsed expression in the AST. Don't discard the parsed expression if the middle expression in a ternary expression has code-completion token. This improves the completions for: let _: MyEnum = condition ? .<HERE> let _: MyEnum = condition ? .<HERE> : rdar://problem/54132682
1 parent 82a4e4f commit 1e8c644

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

lib/Parse/ParseExpr.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,13 @@ ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
189189
if (CodeCompletion)
190190
CodeCompletion->setLeadingSequenceExprs(SequencedExprs);
191191
}
192-
if (Primary.isNull())
192+
if (Primary.isNull()) {
193+
if (HasCodeCompletion) {
194+
SequencedExprs.push_back(new (Context) CodeCompletionExpr(PreviousLoc));
195+
break;
196+
}
193197
return Primary;
198+
}
194199

195200
SequencedExprs.push_back(Primary.get());
196201

@@ -242,16 +247,23 @@ ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
242247
HasCodeCompletion = true;
243248
if (middle.isNull())
244249
return nullptr;
245-
250+
246251
// Make sure there's a matching ':' after the middle expr.
247252
if (!Tok.is(tok::colon)) {
253+
if (middle.hasCodeCompletion()) {
254+
SequencedExprs.push_back(new (Context) IfExpr(questionLoc,
255+
middle.get(),
256+
PreviousLoc));
257+
SequencedExprs.push_back(new (Context) CodeCompletionExpr(PreviousLoc));
258+
goto done;
259+
}
260+
248261
diagnose(questionLoc, diag::expected_colon_after_if_question);
249-
250-
Status.setIsParseError();
251-
return makeParserResult(Status, new (Context) ErrorExpr(
252-
{startLoc, middle.get()->getSourceRange().End}));
262+
Status.setIsParseError();
263+
return makeParserResult(Status, new (Context) ErrorExpr(
264+
{startLoc, middle.get()->getSourceRange().End}));
253265
}
254-
266+
255267
SourceLoc colonLoc = consumeToken();
256268

257269
auto *unresolvedIf

test/IDE/complete_unresolved_members.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@
115115

116116
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TYPEPARAM_IN_CONTEXTTYPE_1 | %FileCheck %s -check-prefix=TYPEPARAM_IN_CONTEXTTYPE_1
117117

118+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TERNARY_1 | %FileCheck %s -check-prefix=UNRESOLVED_3
119+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TERNARY_2 | %FileCheck %s -check-prefix=UNRESOLVED_3
120+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TERNARY_3 | %FileCheck %s -check-prefix=UNRESOLVED_3
121+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TERNARY_4 | %FileCheck %s -check-prefix=UNRESOLVED_3
122+
118123
enum SomeEnum1 {
119124
case South
120125
case North
@@ -732,3 +737,13 @@ func testTypeParamInContextType() {
732737
// TYPEPARAM_IN_CONTEXTTYPE_1-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Convertible]: myProtocolOption[#MyStruct<ConcreteMyProtocol>#];
733738
// TYPEPARAM_IN_CONTEXTTYPE_1: End completions
734739
}
740+
741+
func testTernaryOperator() {
742+
let _: SomeEnum1 = true ? .#^TERNARY_1^#
743+
func sync(){}
744+
let _: SomeEnum1 = true ? .#^TERNARY_2^# :
745+
func sync(){}
746+
let _: SomeEnum1 = true ? .#^TERNARY_3^# : .South
747+
func sync(){}
748+
let _: SomeEnum1 = true ? .South : .#^TERNARY_4^#
749+
}

0 commit comments

Comments
 (0)