Skip to content

Commit 3990932

Browse files
authored
Merge pull request #18245 from rintaro/4.2-ide-compilation-rdar42452085
[4.2][CodeComplete] Strip out try and optional eval expr in operator completion
2 parents 7085923 + df5c4b5 commit 3990932

File tree

3 files changed

+71
-18
lines changed

3 files changed

+71
-18
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3468,10 +3468,13 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
34683468
prepareForRetypechecking(SE);
34693469

34703470
for (auto &element : sequence.drop_back(2)) {
3471-
// Unfold AssignExpr for re-typechecking sequence.
3472-
if (auto *AE = dyn_cast_or_null<AssignExpr>(element)) {
3473-
AE->setSrc(nullptr);
3474-
AE->setDest(nullptr);
3471+
// Unfold expressions for re-typechecking sequence.
3472+
if (auto *assignExpr = dyn_cast_or_null<AssignExpr>(element)) {
3473+
assignExpr->setSrc(nullptr);
3474+
assignExpr->setDest(nullptr);
3475+
} else if (auto *ifExpr = dyn_cast_or_null<IfExpr>(element)) {
3476+
ifExpr->setCondExpr(nullptr);
3477+
ifExpr->setElseExpr(nullptr);
34753478
}
34763479

34773480
// Reset any references to operators in types, so they are properly
@@ -3522,24 +3525,44 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
35223525
flattenBinaryExpr(assignExpr->getSrc(), sequence);
35233526
assignExpr->setDest(nullptr);
35243527
assignExpr->setSrc(nullptr);
3528+
} else if (auto ifExpr = dyn_cast<IfExpr>(expr)) {
3529+
flattenBinaryExpr(ifExpr->getCondExpr(), sequence);
3530+
sequence.push_back(ifExpr);
3531+
flattenBinaryExpr(ifExpr->getElseExpr(), sequence);
3532+
ifExpr->setCondExpr(nullptr);
3533+
ifExpr->setElseExpr(nullptr);
3534+
} else if (auto tryExpr = dyn_cast<AnyTryExpr>(expr)) {
3535+
// Strip out try expression. It doesn't affect completion.
3536+
flattenBinaryExpr(tryExpr->getSubExpr(), sequence);
3537+
} else if (auto optEval = dyn_cast<OptionalEvaluationExpr>(expr)){
3538+
// Strip out optional evaluation expression. It doesn't affect completion.
3539+
flattenBinaryExpr(optEval->getSubExpr(), sequence);
35253540
} else {
35263541
sequence.push_back(expr);
35273542
}
35283543
}
35293544

35303545
void typeCheckLeadingSequence(SmallVectorImpl<Expr *> &sequence) {
3546+
3547+
// Strip out try and optional evaluation expr because foldSequence() mutates
3548+
// hierarchy of these expressions. They don't affect completion anyway.
3549+
for (auto &element : sequence) {
3550+
if (auto *tryExpr = dyn_cast<AnyTryExpr>(element))
3551+
element = tryExpr->getSubExpr();
3552+
if (auto *optEval = dyn_cast<OptionalEvaluationExpr>(element))
3553+
element = optEval->getSubExpr();
3554+
}
3555+
35313556
Expr *expr =
35323557
SequenceExpr::create(CurrDeclContext->getASTContext(), sequence);
35333558
prepareForRetypechecking(expr);
35343559
// Take advantage of the fact the type-checker leaves the types on the AST.
35353560
if (!typeCheckExpression(const_cast<DeclContext *>(CurrDeclContext),
35363561
expr)) {
3537-
if (isa<BinaryExpr>(expr) || isa<AssignExpr>(expr)) {
3538-
// Rebuild the sequence from the type-checked version.
3539-
sequence.clear();
3540-
flattenBinaryExpr(expr, sequence);
3541-
return;
3542-
}
3562+
// Rebuild the sequence from the type-checked version.
3563+
sequence.clear();
3564+
flattenBinaryExpr(expr, sequence);
3565+
return;
35433566
}
35443567

35453568
// Fall back to just using the immediate LHS.

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,11 +2106,20 @@ bool TypeChecker::typeCheckCompletionSequence(Expr *&expr, DeclContext *DC) {
21062106
expr = foldSequence(SE, DC);
21072107

21082108
// Find the code-completion expression and operator again.
2109-
BinaryExpr *exprAsBinOp = nullptr;
2110-
while (auto *binExpr = dyn_cast<BinaryExpr>(expr)) {
2111-
auto *RHS = binExpr->getArg()->getElement(1);
2109+
Expr *exprAsBinOp = nullptr;
2110+
while (true) {
2111+
Expr *RHS;
2112+
if (auto *binExpr = dyn_cast<BinaryExpr>(expr))
2113+
RHS = binExpr->getArg()->getElement(1);
2114+
else if (auto *assignExpr = dyn_cast<AssignExpr>(expr))
2115+
RHS = assignExpr->getSrc();
2116+
else if (auto *ifExpr = dyn_cast<IfExpr>(expr))
2117+
RHS = ifExpr->getElseExpr();
2118+
else
2119+
break;
2120+
21122121
if (RHS == CCE) {
2113-
exprAsBinOp = binExpr;
2122+
exprAsBinOp = expr;
21142123
break;
21152124
}
21162125
expr = RHS;
@@ -2119,7 +2128,7 @@ bool TypeChecker::typeCheckCompletionSequence(Expr *&expr, DeclContext *DC) {
21192128
return true;
21202129

21212130
// Ensure the output expression is up to date.
2122-
assert(exprAsBinOp == expr && "found wrong expr?");
2131+
assert(exprAsBinOp == expr && isa<BinaryExpr>(expr) && "found wrong expr?");
21232132

21242133
// Add type variable for the code-completion expression.
21252134
auto tvRHS =

test/IDE/complete_crashes.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,10 @@ protocol Bar_38149042 {
220220
func foo_38149042(bar: Bar_38149042) {
221221
_ = bar.foo? #^RDAR_38149042^# .x
222222
}
223-
224223
// RDAR_38149042: Begin completions
225224
// 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?
226227
// RDAR_38149042: End completions
227228

228229
// rdar://problem/38272904
@@ -274,18 +275,22 @@ func foo(x: RDAR41159258_MyResult1) {
274275

275276

276277
// rdar://problem/41232519
277-
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41232519 | %FileCheck %s -check-prefix=RDAR_41232519
278+
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41232519_1 | %FileCheck %s -check-prefix=RDAR_41232519
279+
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41232519_2 | %FileCheck %s -check-prefix=RDAR_41232519
278280
public protocol IntProvider {
279281
func nextInt() -> Int
280282
}
281283

282284
public final class IntStore {
283285
public var myInt: Int = 0
284286
func readNextInt(from provider: IntProvider) {
285-
myInt = provider.nextInt() #^RDAR41232519^#
287+
myInt = provider.nextInt() #^RDAR41232519_1^#
288+
_ = true ? 1 : provider.nextInt() #^RDAR41232519_2^#
286289
}
287290
}
288291
// RDAR_41232519: Begin completions
292+
// RDAR_41232519: Decl[InfixOperatorFunction]/OtherModule[Swift]: [' ']+ {#Int#}[#Int#]; name=+ Int
293+
// RDAR_41232519: End completions
289294

290295
// rdar://problem/28188259
291296
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_28188259 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_28188259
@@ -312,3 +317,19 @@ func test_40956846(
312317
// RDAR_40956846-DAG: Decl[LocalVar]/Local: arg_40956846_3[#(() -> Int)!#]; name=arg_40956846_3
313318
// RDAR_40956846-DAG: Decl[LocalVar]/Local: arg_40956846_4[#inout ((Int) -> Int)!#]; name=arg_40956846_4
314319
// RDAR_40956846: End completions
320+
321+
// rdar://problem/42452085
322+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_42452085_1 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_42452085
323+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_42452085_2 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_42452085
324+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_42452085_3 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_42452085
325+
class cls_42452085 {
326+
var value: Any
327+
func canThrow() throws -> Int { return 1 }
328+
}
329+
func test_42452085(any: Any, obj: cls_42452085?) throws {
330+
var object: Any? = nil
331+
object = (any as? String) #^RDAR_42452085_1^#
332+
obj?.value = any #^RDAR_42452085_2^#
333+
_ = try obj?.canThrow() #^RDAR_42452085_3^#
334+
}
335+
// RDAR_42452085: found code completion token

0 commit comments

Comments
 (0)