mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[SourceKit] Handle macro arguments in placeholder expansion
Allow macro argument placeholders to expand into trailing closures. rdar://150550747
This commit is contained in:
@@ -1679,34 +1679,65 @@ private:
|
||||
public:
|
||||
const SourceManager &SM;
|
||||
SourceLoc TargetLoc;
|
||||
std::pair<Expr *, ArgumentList *> EnclosingCallAndArg;
|
||||
std::pair<ASTNode, ArgumentList *> EnclosingCallAndArg;
|
||||
Expr *OuterExpr;
|
||||
Stmt *OuterStmt;
|
||||
explicit CallExprFinder(const SourceManager &SM)
|
||||
:SM(SM) { }
|
||||
Decl *OuterDecl;
|
||||
|
||||
bool checkCallExpr(Expr *E) {
|
||||
ArgumentList *Args = nullptr;
|
||||
if (auto *CE = dyn_cast<CallExpr>(E)) {
|
||||
// Call expression can have argument.
|
||||
Args = CE->getArgs();
|
||||
explicit CallExprFinder(const SourceManager &SM) : SM(SM) {}
|
||||
|
||||
void checkArgumentList(ArgumentList *Args) {
|
||||
ASTNode Enclosing;
|
||||
if (auto *E = Parent.getAsExpr()) {
|
||||
// Must have a function call or macro parent.
|
||||
if (!isa<CallExpr, MacroExpansionExpr>(E) ||
|
||||
E->getArgs() != Args) {
|
||||
return;
|
||||
}
|
||||
// If the outer expression is the call itself, disregard it.
|
||||
if (OuterExpr == E)
|
||||
OuterExpr = nullptr;
|
||||
|
||||
Enclosing = E;
|
||||
}
|
||||
if (!Args)
|
||||
return false;
|
||||
if (EnclosingCallAndArg.first)
|
||||
OuterExpr = EnclosingCallAndArg.first;
|
||||
EnclosingCallAndArg = {E, Args};
|
||||
return true;
|
||||
if (auto *D = Parent.getAsDecl()) {
|
||||
// Must have a macro decl parent.
|
||||
auto *MED = dyn_cast<MacroExpansionDecl>(D);
|
||||
if (!MED || MED->getArgs() != Args)
|
||||
return;
|
||||
Enclosing = D;
|
||||
}
|
||||
if (!Enclosing)
|
||||
return;
|
||||
|
||||
// If we have an outer enclosing call, update the outer nodes if needed.
|
||||
if (auto EnclosingCall = EnclosingCallAndArg.first) {
|
||||
if (!OuterExpr)
|
||||
OuterExpr = EnclosingCall.dyn_cast<Expr *>();
|
||||
if (!OuterDecl)
|
||||
OuterDecl = EnclosingCall.dyn_cast<Decl *>();
|
||||
}
|
||||
|
||||
EnclosingCallAndArg = {Enclosing, Args};
|
||||
}
|
||||
|
||||
MacroWalking getMacroWalkingBehavior() const override {
|
||||
return MacroWalking::Arguments;
|
||||
}
|
||||
|
||||
PreWalkResult<ArgumentList *>
|
||||
walkToArgumentListPre(ArgumentList *ArgList) override {
|
||||
auto SR = ArgList->getSourceRange();
|
||||
if (SR.isValid() && SM.rangeContainsTokenLoc(SR, TargetLoc))
|
||||
checkArgumentList(ArgList);
|
||||
|
||||
return Action::Continue(ArgList);
|
||||
}
|
||||
|
||||
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
|
||||
auto SR = E->getSourceRange();
|
||||
if (SR.isValid() && SM.rangeContainsTokenLoc(SR, TargetLoc) &&
|
||||
!checkCallExpr(E) && !EnclosingCallAndArg.first) {
|
||||
!OuterExpr && !EnclosingCallAndArg.first) {
|
||||
if (!isa<TryExpr>(E) && !isa<AwaitExpr>(E) && !isa<UnsafeExpr>(E) &&
|
||||
!isa<PrefixUnaryExpr>(E)) {
|
||||
// We don't want to expand to trailing closures if the call is
|
||||
@@ -1782,6 +1813,7 @@ private:
|
||||
EnclosingCallAndArg = {nullptr, nullptr};
|
||||
OuterExpr = nullptr;
|
||||
OuterStmt = nullptr;
|
||||
OuterDecl = nullptr;
|
||||
TargetLoc = SL;
|
||||
SF.walk(*this);
|
||||
return EnclosingCallAndArg.second;
|
||||
@@ -1791,14 +1823,9 @@ private:
|
||||
CallExprFinder CEFinder(SM);
|
||||
auto *Args = CEFinder.findEnclosingCallArg(SF, SL);
|
||||
|
||||
if (!Args)
|
||||
return std::make_pair(Args, false);
|
||||
if (CEFinder.OuterExpr)
|
||||
return std::make_pair(Args, false);
|
||||
if (CEFinder.OuterStmt)
|
||||
return std::make_pair(Args, false);
|
||||
|
||||
return std::make_pair(Args, true);
|
||||
auto HasOuterNode =
|
||||
CEFinder.OuterExpr || CEFinder.OuterStmt || CEFinder.OuterDecl;
|
||||
return std::make_pair(Args, /*useTrailingClosure*/ Args && !HasOuterNode);
|
||||
}
|
||||
|
||||
struct ParamClosureInfo {
|
||||
|
||||
Reference in New Issue
Block a user