Skip to content

Commit cf949cb

Browse files
authored
Merge pull request #12982 from nkcsgexi/code-expand-fix
2 parents 4ded97b + 3160446 commit cf949cb

File tree

2 files changed

+31
-16
lines changed

2 files changed

+31
-16
lines changed

test/SourceKit/CodeExpand/code-expand.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,7 @@ if true {
8787
// CHECK: withtrail {
8888
// CHECK-NEXT: <#code#>
8989
}
90-
}
90+
}
91+
92+
foo(.foo(<#T##block: () -> Void##() -> Void#>))
93+
// CHECK: foo(.foo({

tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp

+27-15
Original file line numberDiff line numberDiff line change
@@ -1537,27 +1537,39 @@ class PlaceholderExpansionScanner {
15371537
/// For example, if the CallExpr is enclosed in another expression or statement
15381538
/// such as "outer(inner(<#closure#>))", or "if inner(<#closure#>)", then trailing
15391539
/// closure should not be applied to the inner call.
1540-
std::pair<CallExpr *, bool> enclosingCallExpr(SourceFile &SF, SourceLoc SL) {
1540+
std::pair<Expr*, bool> enclosingCallExprArg(SourceFile &SF, SourceLoc SL) {
15411541

15421542
class CallExprFinder : public SourceEntityWalker {
15431543
public:
15441544
const SourceManager &SM;
15451545
SourceLoc TargetLoc;
1546-
CallExpr *EnclosingCall;
1546+
std::pair<Expr *, Expr*> EnclosingCallAndArg;
15471547
Expr *OuterExpr;
15481548
Stmt *OuterStmt;
15491549
explicit CallExprFinder(const SourceManager &SM)
15501550
:SM(SM) { }
15511551

1552+
bool checkCallExpr(Expr *E) {
1553+
Expr* Arg = nullptr;
1554+
if (auto *CE = dyn_cast<CallExpr>(E)) {
1555+
// Call expression can have argument.
1556+
Arg = CE->getArg();
1557+
} else if (auto UME = dyn_cast<UnresolvedMemberExpr>(E)) {
1558+
// Unresolved member can have argument too.
1559+
Arg = UME->getArgument();
1560+
}
1561+
if (!Arg)
1562+
return false;
1563+
if (EnclosingCallAndArg.first)
1564+
OuterExpr = EnclosingCallAndArg.first;
1565+
EnclosingCallAndArg = {E, Arg};
1566+
return true;
1567+
}
1568+
15521569
bool walkToExprPre(Expr *E) override {
15531570
auto SR = E->getSourceRange();
15541571
if (SR.isValid() && SM.rangeContainsTokenLoc(SR, TargetLoc)) {
1555-
if (auto *CE = dyn_cast<CallExpr>(E)) {
1556-
if (EnclosingCall)
1557-
OuterExpr = EnclosingCall;
1558-
EnclosingCall = CE;
1559-
}
1560-
else if (!EnclosingCall)
1572+
if (!checkCallExpr(E) && !EnclosingCallAndArg.first)
15611573
OuterExpr = E;
15621574
}
15631575
return true;
@@ -1572,7 +1584,7 @@ class PlaceholderExpansionScanner {
15721584
bool walkToStmtPre(Stmt *S) override {
15731585
auto SR = S->getSourceRange();
15741586
if (SR.isValid() && SM.rangeContainsTokenLoc(SR, TargetLoc)) {
1575-
if (!EnclosingCall) {
1587+
if (!EnclosingCallAndArg.first) {
15761588
if (isa<BraceStmt>(S))
15771589
// In case OuterStmt is already set, we should clear it to nullptr.
15781590
OuterStmt = nullptr;
@@ -1583,18 +1595,18 @@ class PlaceholderExpansionScanner {
15831595
return true;
15841596
}
15851597

1586-
CallExpr *findEnclosingCall(SourceFile &SF, SourceLoc SL) {
1587-
EnclosingCall = nullptr;
1598+
Expr *findEnclosingCallArg(SourceFile &SF, SourceLoc SL) {
1599+
EnclosingCallAndArg = {nullptr, nullptr};
15881600
OuterExpr = nullptr;
15891601
OuterStmt = nullptr;
15901602
TargetLoc = SL;
15911603
walk(SF);
1592-
return EnclosingCall;
1604+
return EnclosingCallAndArg.second;
15931605
}
15941606
};
15951607

15961608
CallExprFinder CEFinder(SM);
1597-
auto *CE = CEFinder.findEnclosingCall(SF, SL);
1609+
auto *CE = CEFinder.findEnclosingCallArg(SF, SL);
15981610

15991611
if (!CE)
16001612
return std::make_pair(CE, false);
@@ -1647,8 +1659,8 @@ class PlaceholderExpansionScanner {
16471659
// and if the call parens can be removed in that case.
16481660
// We'll first find the enclosing CallExpr, and then do further analysis.
16491661
bool UseTrailingClosure = false;
1650-
std::pair<CallExpr*, bool> ECE = enclosingCallExpr(SF, PlaceholderStartLoc);
1651-
Expr *Args = ECE.first ? ECE.first->getArg() : nullptr;
1662+
auto ECE = enclosingCallExprArg(SF, PlaceholderStartLoc);
1663+
Expr *Args = ECE.first;
16521664
if (Args && ECE.second) {
16531665
if (isa<ParenExpr>(Args)) {
16541666
UseTrailingClosure = true;

0 commit comments

Comments
 (0)