Skip to content

Commit 0547f1b

Browse files
authored
Merge pull request #18209 from rintaro/ide-compilation-rdar42452085
[CodeComplete] Strip out try and optional eval expo in operator completion
2 parents 19fa128 + 2babbc3 commit 0547f1b

File tree

3 files changed

+72
-18
lines changed

3 files changed

+72
-18
lines changed

lib/IDE/CodeCompletion.cpp

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

33913391
for (auto &element : sequence.drop_back(2)) {
3392-
// Unfold AssignExpr for re-typechecking sequence.
3393-
if (auto *AE = dyn_cast_or_null<AssignExpr>(element)) {
3394-
AE->setSrc(nullptr);
3395-
AE->setDest(nullptr);
3392+
// Unfold expressions for re-typechecking sequence.
3393+
if (auto *assignExpr = dyn_cast_or_null<AssignExpr>(element)) {
3394+
assignExpr->setSrc(nullptr);
3395+
assignExpr->setDest(nullptr);
3396+
} else if (auto *ifExpr = dyn_cast_or_null<IfExpr>(element)) {
3397+
ifExpr->setCondExpr(nullptr);
3398+
ifExpr->setElseExpr(nullptr);
33963399
}
33973400

33983401
// Reset any references to operators in types, so they are properly
@@ -3443,24 +3446,44 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
34433446
flattenBinaryExpr(assignExpr->getSrc(), sequence);
34443447
assignExpr->setDest(nullptr);
34453448
assignExpr->setSrc(nullptr);
3449+
} else if (auto ifExpr = dyn_cast<IfExpr>(expr)) {
3450+
flattenBinaryExpr(ifExpr->getCondExpr(), sequence);
3451+
sequence.push_back(ifExpr);
3452+
flattenBinaryExpr(ifExpr->getElseExpr(), sequence);
3453+
ifExpr->setCondExpr(nullptr);
3454+
ifExpr->setElseExpr(nullptr);
3455+
} else if (auto tryExpr = dyn_cast<AnyTryExpr>(expr)) {
3456+
// Strip out try expression. It doesn't affect completion.
3457+
flattenBinaryExpr(tryExpr->getSubExpr(), sequence);
3458+
} else if (auto optEval = dyn_cast<OptionalEvaluationExpr>(expr)){
3459+
// Strip out optional evaluation expression. It doesn't affect completion.
3460+
flattenBinaryExpr(optEval->getSubExpr(), sequence);
34463461
} else {
34473462
sequence.push_back(expr);
34483463
}
34493464
}
34503465

34513466
void typeCheckLeadingSequence(SmallVectorImpl<Expr *> &sequence) {
3467+
3468+
// Strip out try and optional evaluation expr because foldSequence() mutates
3469+
// hierarchy of these expressions. They don't affect completion anyway.
3470+
for (auto &element : sequence) {
3471+
if (auto *tryExpr = dyn_cast<AnyTryExpr>(element))
3472+
element = tryExpr->getSubExpr();
3473+
if (auto *optEval = dyn_cast<OptionalEvaluationExpr>(element))
3474+
element = optEval->getSubExpr();
3475+
}
3476+
34523477
Expr *expr =
34533478
SequenceExpr::create(CurrDeclContext->getASTContext(), sequence);
34543479
prepareForRetypechecking(expr);
34553480
// Take advantage of the fact the type-checker leaves the types on the AST.
34563481
if (!typeCheckExpression(const_cast<DeclContext *>(CurrDeclContext),
34573482
expr)) {
3458-
if (isa<BinaryExpr>(expr) || isa<AssignExpr>(expr)) {
3459-
// Rebuild the sequence from the type-checked version.
3460-
sequence.clear();
3461-
flattenBinaryExpr(expr, sequence);
3462-
return;
3463-
}
3483+
// Rebuild the sequence from the type-checked version.
3484+
sequence.clear();
3485+
flattenBinaryExpr(expr, sequence);
3486+
return;
34643487
}
34653488

34663489
// 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
@@ -2247,11 +2247,20 @@ bool TypeChecker::typeCheckCompletionSequence(Expr *&expr, DeclContext *DC) {
22472247
expr = foldSequence(SE, DC);
22482248

22492249
// Find the code-completion expression and operator again.
2250-
BinaryExpr *exprAsBinOp = nullptr;
2251-
while (auto *binExpr = dyn_cast<BinaryExpr>(expr)) {
2252-
auto *RHS = binExpr->getArg()->getElement(1);
2250+
Expr *exprAsBinOp = nullptr;
2251+
while (true) {
2252+
Expr *RHS;
2253+
if (auto *binExpr = dyn_cast<BinaryExpr>(expr))
2254+
RHS = binExpr->getArg()->getElement(1);
2255+
else if (auto *assignExpr = dyn_cast<AssignExpr>(expr))
2256+
RHS = assignExpr->getSrc();
2257+
else if (auto *ifExpr = dyn_cast<IfExpr>(expr))
2258+
RHS = ifExpr->getElseExpr();
2259+
else
2260+
break;
2261+
22532262
if (RHS == CCE) {
2254-
exprAsBinOp = binExpr;
2263+
exprAsBinOp = expr;
22552264
break;
22562265
}
22572266
expr = RHS;
@@ -2260,7 +2269,7 @@ bool TypeChecker::typeCheckCompletionSequence(Expr *&expr, DeclContext *DC) {
22602269
return true;
22612270

22622271
// Ensure the output expression is up to date.
2263-
assert(exprAsBinOp == expr && "found wrong expr?");
2272+
assert(exprAsBinOp == expr && isa<BinaryExpr>(expr) && "found wrong expr?");
22642273

22652274
// Add type variable for the code-completion expression.
22662275
CCE->setActivated();

test/IDE/complete_crashes.swift

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,11 @@ protocol Bar_38149042 {
220220
func foo_38149042(bar: Bar_38149042) {
221221
_ = bar.foo? #^RDAR_38149042^# .x
222222
}
223-
// RDAR_38149042: Begin completions, 2 items
223+
// RDAR_38149042: Begin completions
224224
// RDAR_38149042-DAG: Decl[InstanceVar]/CurrNominal: .x[#Int#]; name=x
225225
// RDAR_38149042-DAG: Keyword[self]/CurrNominal: .self[#Baz_38149042#]; name=self
226+
// RDAR_38149042-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]: [' ']=== {#AnyObject?#}[#Bool#]; name==== AnyObject?
227+
// RDAR_38149042-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]: [' ']!== {#AnyObject?#}[#Bool#]; name=!== AnyObject?
226228
// RDAR_38149042: End completions
227229

228230
// rdar://problem/38272904
@@ -274,18 +276,22 @@ func foo(x: RDAR41159258_MyResult1) {
274276

275277

276278
// rdar://problem/41232519
277-
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41232519 | %FileCheck %s -check-prefix=RDAR_41232519
279+
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41232519_1 | %FileCheck %s -check-prefix=RDAR_41232519
280+
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41232519_2 | %FileCheck %s -check-prefix=RDAR_41232519
278281
public protocol IntProvider {
279282
func nextInt() -> Int
280283
}
281284

282285
public final class IntStore {
283286
public var myInt: Int = 0
284287
func readNextInt(from provider: IntProvider) {
285-
myInt = provider.nextInt() #^RDAR41232519^#
288+
myInt = provider.nextInt() #^RDAR41232519_1^#
289+
_ = true ? 1 : provider.nextInt() #^RDAR41232519_2^#
286290
}
287291
}
288292
// RDAR_41232519: Begin completions
293+
// RDAR_41232519: Decl[InfixOperatorFunction]/OtherModule[Swift]: [' ']+ {#Int#}[#Int#]; name=+ Int
294+
// RDAR_41232519: End completions
289295

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

0 commit comments

Comments
 (0)