[CodeComplete] Handle assign expression in sequence completion

rdar://problem/41232519
rdar://problem/41159258
This commit is contained in:
Rintaro Ishizaki
2018-06-27 18:41:00 +09:00
parent b6631edabb
commit f577578a6a
2 changed files with 73 additions and 23 deletions

View File

@@ -3458,11 +3458,17 @@ public:
SE->setElement(SE->getNumElements() - 2, nullptr);
prepareForRetypechecking(SE);
// Reset any references to operators in types, so they are properly
// handled as operators by sequence folding.
//
// FIXME: Would be better to have some kind of 'OperatorRefExpr'?
for (auto &element : sequence.drop_back(2)) {
// Unfold AssignExpr for re-typechecking sequence.
if (auto *AE = dyn_cast_or_null<AssignExpr>(element)) {
AE->setSrc(nullptr);
AE->setDest(nullptr);
}
// Reset any references to operators in types, so they are properly
// handled as operators by sequence folding.
//
// FIXME: Would be better to have some kind of 'OperatorRefExpr'?
if (auto operatorRef = element->getMemberOperatorRef()) {
operatorRef->setType(nullptr);
element = operatorRef;
@@ -3496,20 +3502,20 @@ public:
}
}
void flattenBinaryExpr(BinaryExpr *expr, SmallVectorImpl<Expr *> &sequence) {
auto LHS = expr->getArg()->getElement(0);
if (auto binexpr = dyn_cast<BinaryExpr>(LHS))
flattenBinaryExpr(binexpr, sequence);
else
sequence.push_back(LHS);
sequence.push_back(expr->getFn());
auto RHS = expr->getArg()->getElement(1);
if (auto binexpr = dyn_cast<BinaryExpr>(RHS))
flattenBinaryExpr(binexpr, sequence);
else
sequence.push_back(RHS);
void flattenBinaryExpr(Expr *expr, SmallVectorImpl<Expr *> &sequence) {
if (auto binExpr = dyn_cast<BinaryExpr>(expr)) {
flattenBinaryExpr(binExpr->getArg()->getElement(0), sequence);
sequence.push_back(binExpr->getFn());
flattenBinaryExpr(binExpr->getArg()->getElement(1), sequence);
} else if (auto assignExpr = dyn_cast<AssignExpr>(expr)) {
flattenBinaryExpr(assignExpr->getDest(), sequence);
sequence.push_back(assignExpr);
flattenBinaryExpr(assignExpr->getSrc(), sequence);
assignExpr->setDest(nullptr);
assignExpr->setSrc(nullptr);
} else {
sequence.push_back(expr);
}
}
void typeCheckLeadingSequence(SmallVectorImpl<Expr *> &sequence) {
@@ -3519,10 +3525,10 @@ public:
// Take advantage of the fact the type-checker leaves the types on the AST.
if (!typeCheckExpression(const_cast<DeclContext *>(CurrDeclContext),
expr)) {
if (auto binexpr = dyn_cast<BinaryExpr>(expr)) {
if (isa<BinaryExpr>(expr) || isa<AssignExpr>(expr)) {
// Rebuild the sequence from the type-checked version.
sequence.clear();
flattenBinaryExpr(binexpr, sequence);
flattenBinaryExpr(expr, sequence);
return;
}
}
@@ -3548,6 +3554,9 @@ public:
if (sequence.size() > 1)
typeCheckLeadingSequence(sequence);
// Retrieve typechecked LHS.
LHS = sequence.back();
// Create a single sequence expression, which we will modify for each
// operator, filling in the operator and dummy right-hand side.
sequence.push_back(nullptr); // operator

View File

@@ -220,10 +220,9 @@ protocol Bar_38149042 {
func foo_38149042(bar: Bar_38149042) {
_ = bar.foo? #^RDAR_38149042^# .x
}
// RDAR_38149042: Begin completions, 3 items
// RDAR_38149042: Begin completions
// RDAR_38149042-DAG: Decl[InstanceVar]/CurrNominal: .x[#Int#]; name=x
// RDAR_38149042-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]: [' ']=== {#AnyObject?#}[#Bool#]; name==== AnyObject?
// RDAR_38149042-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]: [' ']!== {#AnyObject?#}[#Bool#]; name=!== AnyObject?
// RDAR_38149042: End completions
// rdar://problem/38272904
@@ -246,3 +245,45 @@ func foo_38272904(a: A_38272904) {
bar_38272904(a: .foo() #^RDAR_38272904^#)
}
// RDAR_38272904: Begin completions
// rdar://problem/41159258
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41159258_1
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41159258_2 | %FileCheck %s -check-prefix=RDAR_41159258
public func ==(lhs: RDAR41159258_MyResult1, rhs: RDAR41159258_MyResult1) -> Bool {
fatalError()
}
public func ==(lhs: RDAR41159258_MyResult2, rhs: RDAR41159258_MyResult2) -> Bool {
fatalError()
}
public enum RDAR41159258_MyResult1 {
case failure(Error)
}
public enum RDAR41159258_MyResult2 {
case failure(Error)
}
public struct RDAR41159258_MyError: Error {}
func foo(x: RDAR41159258_MyResult1) {
let x: RDAR41159258_MyResult1
x = .failure(RDAR41159258_MyError()) #^RDAR41159258_1^#
let y: Bool
y = .failure(RDAR41159258_MyError()) #^RDAR41159258_2^#
}
// RDAR_41159258: Begin completions
// rdar://problem/41232519
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41232519 | %FileCheck %s -check-prefix=RDAR_41232519
public protocol IntProvider {
func nextInt() -> Int
}
public final class IntStore {
public var myInt: Int = 0
func readNextInt(from provider: IntProvider) {
myInt = provider.nextInt() #^RDAR41232519^#
}
}
// RDAR_41232519: Begin completions