Skip to content

Commit 91fe7db

Browse files
authored
Merge pull request #29343 from rintaro/ide-completion-ternary-rdar54132682
[CodeCompletion] Don't discard parsed expression in incomplete ternary
2 parents 1ed5794 + afd3be9 commit 91fe7db

File tree

3 files changed

+61
-8
lines changed

3 files changed

+61
-8
lines changed

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,18 @@ class ExprContextAnalyzer {
645645
}
646646
break;
647647
}
648+
case ExprKind::If: {
649+
auto *IE = cast<IfExpr>(Parent);
650+
if (SM.rangeContains(IE->getCondExpr()->getSourceRange(),
651+
ParsedExpr->getSourceRange())) {
652+
recordPossibleType(Context.getBoolDecl()->getDeclaredInterfaceType());
653+
break;
654+
}
655+
ExprContextInfo ternaryCtxtInfo(DC, Parent);
656+
for (auto ternaryT : ternaryCtxtInfo.getPossibleTypes())
657+
recordPossibleType(ternaryT);
658+
break;
659+
}
648660
case ExprKind::Assign: {
649661
auto *AE = cast<AssignExpr>(Parent);
650662

@@ -861,7 +873,7 @@ class ExprContextAnalyzer {
861873
case ExprKind::Assign:
862874
case ExprKind::Array:
863875
case ExprKind::Dictionary:
864-
return true;
876+
case ExprKind::If:
865877
case ExprKind::UnresolvedMember:
866878
return true;
867879
case ExprKind::Tuple: {

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: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,14 @@
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+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TERNARY_5 | %FileCheck %s -check-prefix=UNRESOLVED_3
123+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TERNARY_6 | %FileCheck %s -check-prefix=UNRESOLVED_3
124+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TERNARY_CONDITION | %FileCheck %s -check-prefix=TERNARY_CONDITION
125+
118126
enum SomeEnum1 {
119127
case South
120128
case North
@@ -732,3 +740,24 @@ func testTypeParamInContextType() {
732740
// TYPEPARAM_IN_CONTEXTTYPE_1-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Convertible]: myProtocolOption[#MyStruct<ConcreteMyProtocol>#];
733741
// TYPEPARAM_IN_CONTEXTTYPE_1: End completions
734742
}
743+
744+
func testTernaryOperator(cond: Bool) {
745+
let _: SomeEnum1 = cond ? .#^TERNARY_1^#
746+
func sync(){}
747+
let _: SomeEnum1 = cond ? .#^TERNARY_2^# :
748+
func sync(){}
749+
let _: SomeEnum1 = cond ? .#^TERNARY_3^# : .South
750+
func sync(){}
751+
let _: SomeEnum1 = cond ? .South : .#^TERNARY_4^#
752+
}
753+
754+
func testTernaryOperator2(cond: Bool) {
755+
let _: SomeEnum1 = cond ? .#^TERNARY_5^# : .bogus
756+
func sync(){}
757+
let _: SomeEnum1 = cond ? .bogus : .#^TERNARY_6^#
758+
func sync(){}
759+
let _: SomeEnum1 = .#^TERNARY_CONDITION^# ? .bogus : .bogus
760+
// TERNARY_CONDITION: Begin completions
761+
// TERNARY_CONDITION-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Identical]: init()[#Bool#]; name=init()
762+
// TERNARY_CONDITION: End completions
763+
}

0 commit comments

Comments
 (0)