Skip to content

Commit f577578

Browse files
committed
[CodeComplete] Handle assign expression in sequence completion
rdar://problem/41232519 rdar://problem/41159258
1 parent b6631ed commit f577578

File tree

2 files changed

+73
-23
lines changed

2 files changed

+73
-23
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3458,11 +3458,17 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
34583458
SE->setElement(SE->getNumElements() - 2, nullptr);
34593459
prepareForRetypechecking(SE);
34603460

3461-
// Reset any references to operators in types, so they are properly
3462-
// handled as operators by sequence folding.
3463-
//
3464-
// FIXME: Would be better to have some kind of 'OperatorRefExpr'?
34653461
for (auto &element : sequence.drop_back(2)) {
3462+
// Unfold AssignExpr for re-typechecking sequence.
3463+
if (auto *AE = dyn_cast_or_null<AssignExpr>(element)) {
3464+
AE->setSrc(nullptr);
3465+
AE->setDest(nullptr);
3466+
}
3467+
3468+
// Reset any references to operators in types, so they are properly
3469+
// handled as operators by sequence folding.
3470+
//
3471+
// FIXME: Would be better to have some kind of 'OperatorRefExpr'?
34663472
if (auto operatorRef = element->getMemberOperatorRef()) {
34673473
operatorRef->setType(nullptr);
34683474
element = operatorRef;
@@ -3496,20 +3502,20 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
34963502
}
34973503
}
34983504

3499-
void flattenBinaryExpr(BinaryExpr *expr, SmallVectorImpl<Expr *> &sequence) {
3500-
auto LHS = expr->getArg()->getElement(0);
3501-
if (auto binexpr = dyn_cast<BinaryExpr>(LHS))
3502-
flattenBinaryExpr(binexpr, sequence);
3503-
else
3504-
sequence.push_back(LHS);
3505-
3506-
sequence.push_back(expr->getFn());
3507-
3508-
auto RHS = expr->getArg()->getElement(1);
3509-
if (auto binexpr = dyn_cast<BinaryExpr>(RHS))
3510-
flattenBinaryExpr(binexpr, sequence);
3511-
else
3512-
sequence.push_back(RHS);
3505+
void flattenBinaryExpr(Expr *expr, SmallVectorImpl<Expr *> &sequence) {
3506+
if (auto binExpr = dyn_cast<BinaryExpr>(expr)) {
3507+
flattenBinaryExpr(binExpr->getArg()->getElement(0), sequence);
3508+
sequence.push_back(binExpr->getFn());
3509+
flattenBinaryExpr(binExpr->getArg()->getElement(1), sequence);
3510+
} else if (auto assignExpr = dyn_cast<AssignExpr>(expr)) {
3511+
flattenBinaryExpr(assignExpr->getDest(), sequence);
3512+
sequence.push_back(assignExpr);
3513+
flattenBinaryExpr(assignExpr->getSrc(), sequence);
3514+
assignExpr->setDest(nullptr);
3515+
assignExpr->setSrc(nullptr);
3516+
} else {
3517+
sequence.push_back(expr);
3518+
}
35133519
}
35143520

35153521
void typeCheckLeadingSequence(SmallVectorImpl<Expr *> &sequence) {
@@ -3519,10 +3525,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
35193525
// Take advantage of the fact the type-checker leaves the types on the AST.
35203526
if (!typeCheckExpression(const_cast<DeclContext *>(CurrDeclContext),
35213527
expr)) {
3522-
if (auto binexpr = dyn_cast<BinaryExpr>(expr)) {
3528+
if (isa<BinaryExpr>(expr) || isa<AssignExpr>(expr)) {
35233529
// Rebuild the sequence from the type-checked version.
35243530
sequence.clear();
3525-
flattenBinaryExpr(binexpr, sequence);
3531+
flattenBinaryExpr(expr, sequence);
35263532
return;
35273533
}
35283534
}
@@ -3548,6 +3554,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
35483554
if (sequence.size() > 1)
35493555
typeCheckLeadingSequence(sequence);
35503556

3557+
// Retrieve typechecked LHS.
3558+
LHS = sequence.back();
3559+
35513560
// Create a single sequence expression, which we will modify for each
35523561
// operator, filling in the operator and dummy right-hand side.
35533562
sequence.push_back(nullptr); // operator

test/IDE/complete_crashes.swift

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,9 @@ protocol Bar_38149042 {
220220
func foo_38149042(bar: Bar_38149042) {
221221
_ = bar.foo? #^RDAR_38149042^# .x
222222
}
223-
// RDAR_38149042: Begin completions, 3 items
223+
224+
// RDAR_38149042: Begin completions
224225
// RDAR_38149042-DAG: Decl[InstanceVar]/CurrNominal: .x[#Int#]; name=x
225-
// RDAR_38149042-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]: [' ']=== {#AnyObject?#}[#Bool#]; name==== AnyObject?
226-
// RDAR_38149042-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]: [' ']!== {#AnyObject?#}[#Bool#]; name=!== AnyObject?
227226
// RDAR_38149042: End completions
228227

229228
// rdar://problem/38272904
@@ -246,3 +245,45 @@ func foo_38272904(a: A_38272904) {
246245
bar_38272904(a: .foo() #^RDAR_38272904^#)
247246
}
248247
// RDAR_38272904: Begin completions
248+
249+
250+
// rdar://problem/41159258
251+
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41159258_1
252+
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41159258_2 | %FileCheck %s -check-prefix=RDAR_41159258
253+
public func ==(lhs: RDAR41159258_MyResult1, rhs: RDAR41159258_MyResult1) -> Bool {
254+
fatalError()
255+
}
256+
public func ==(lhs: RDAR41159258_MyResult2, rhs: RDAR41159258_MyResult2) -> Bool {
257+
fatalError()
258+
}
259+
public enum RDAR41159258_MyResult1 {
260+
case failure(Error)
261+
}
262+
public enum RDAR41159258_MyResult2 {
263+
case failure(Error)
264+
}
265+
266+
public struct RDAR41159258_MyError: Error {}
267+
268+
func foo(x: RDAR41159258_MyResult1) {
269+
let x: RDAR41159258_MyResult1
270+
x = .failure(RDAR41159258_MyError()) #^RDAR41159258_1^#
271+
let y: Bool
272+
y = .failure(RDAR41159258_MyError()) #^RDAR41159258_2^#
273+
}
274+
// RDAR_41159258: Begin completions
275+
276+
277+
// rdar://problem/41232519
278+
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41232519 | %FileCheck %s -check-prefix=RDAR_41232519
279+
public protocol IntProvider {
280+
func nextInt() -> Int
281+
}
282+
283+
public final class IntStore {
284+
public var myInt: Int = 0
285+
func readNextInt(from provider: IntProvider) {
286+
myInt = provider.nextInt() #^RDAR41232519^#
287+
}
288+
}
289+
// RDAR_41232519: Begin completions

0 commit comments

Comments
 (0)