[Sema] Maintain the implicitness of call argument tuple/parens in coerceCallArguments

If any arguments were defaulted the tuple/paren was made implicit, even though
the original tuple/paren was present in the source.

This prevented some sourcekit ASTWalkers from considering them, making
refactorings, documentation info, jump-to-definition and other features
unavailable when queried via their argument labels.

Resolves rdar://problem/62118957
This commit is contained in:
Nathan Hawes
2020-04-21 11:47:12 -07:00
parent 82d73b531b
commit 7c0a17803d
5 changed files with 36 additions and 20 deletions

View File

@@ -4133,9 +4133,9 @@ public:
DefaultArgsOwner(defaultArgsOwner), ParamIndex(paramIndex), Loc(loc), DefaultArgsOwner(defaultArgsOwner), ParamIndex(paramIndex), Loc(loc),
ContextOrCallerSideExpr(dc) { } ContextOrCallerSideExpr(dc) { }
SourceRange getSourceRange() const { SourceRange getSourceRange() const { return {}; }
return Loc;
} SourceLoc getArgumentListLoc() const { return Loc; }
ConcreteDeclRef getDefaultArgsOwner() const { ConcreteDeclRef getDefaultArgsOwner() const {
return DefaultArgsOwner; return DefaultArgsOwner;

View File

@@ -547,22 +547,24 @@ std::pair<bool, Expr *> ModelASTWalker::walkToExprPre(Expr *E) {
return {false, E}; return {false, E};
auto addCallArgExpr = [&](Expr *Elem, TupleExpr *ParentTupleExpr) { auto addCallArgExpr = [&](Expr *Elem, TupleExpr *ParentTupleExpr) {
if (isCurrentCallArgExpr(ParentTupleExpr)) { if (isa<DefaultArgumentExpr>(Elem) ||
CharSourceRange NR = parameterNameRangeOfCallArg(ParentTupleExpr, Elem); !isCurrentCallArgExpr(ParentTupleExpr))
SyntaxStructureNode SN; return;
SN.Kind = SyntaxStructureKind::Argument;
SN.NameRange = NR;
SN.BodyRange = charSourceRangeFromSourceRange(SM, Elem->getSourceRange());
if (NR.isValid()) {
SN.Range = charSourceRangeFromSourceRange(SM, SourceRange(NR.getStart(),
Elem->getEndLoc()));
passTokenNodesUntil(NR.getStart(), ExcludeNodeAtLocation);
}
else
SN.Range = SN.BodyRange;
pushStructureNode(SN, Elem); CharSourceRange NR = parameterNameRangeOfCallArg(ParentTupleExpr, Elem);
SyntaxStructureNode SN;
SN.Kind = SyntaxStructureKind::Argument;
SN.NameRange = NR;
SN.BodyRange = charSourceRangeFromSourceRange(SM, Elem->getSourceRange());
if (NR.isValid()) {
SN.Range = charSourceRangeFromSourceRange(SM, SourceRange(NR.getStart(),
Elem->getEndLoc()));
passTokenNodesUntil(NR.getStart(), ExcludeNodeAtLocation);
} }
else
SN.Range = SN.BodyRange;
pushStructureNode(SN, Elem);
}; };
if (auto *ParentTupleExpr = dyn_cast_or_null<TupleExpr>(Parent.getAsExpr())) { if (auto *ParentTupleExpr = dyn_cast_or_null<TupleExpr>(Parent.getAsExpr())) {

View File

@@ -5759,9 +5759,10 @@ Expr *ExprRewriter::coerceCallArguments(Expr *arg, AnyFunctionType *funcType,
// We already had a ParenExpr, so replace it's sub-expression. // We already had a ParenExpr, so replace it's sub-expression.
argParen->setSubExpr(newArgs[0]); argParen->setSubExpr(newArgs[0]);
} else { } else {
bool isImplicit = arg->isImplicit();
arg = new (ctx) arg = new (ctx)
ParenExpr(lParenLoc, newArgs[0], rParenLoc, hasTrailingClosure); ParenExpr(lParenLoc, newArgs[0], rParenLoc, hasTrailingClosure);
arg->setImplicit(); arg->setImplicit(isImplicit);
} }
} else { } else {
assert(isa<TupleType>(paramType.getPointer())); assert(isa<TupleType>(paramType.getPointer()));
@@ -5776,7 +5777,7 @@ Expr *ExprRewriter::coerceCallArguments(Expr *arg, AnyFunctionType *funcType,
// Build a new TupleExpr, re-using source location information. // Build a new TupleExpr, re-using source location information.
arg = TupleExpr::create(ctx, lParenLoc, newArgs, newLabels, newLabelLocs, arg = TupleExpr::create(ctx, lParenLoc, newArgs, newLabels, newLabelLocs,
rParenLoc, hasTrailingClosure, rParenLoc, hasTrailingClosure,
/*implicit=*/true); /*implicit=*/arg->isImplicit());
} }
} }

View File

@@ -788,7 +788,8 @@ Expr *CallerSideDefaultArgExprRequest::evaluate(
auto paramTy = defaultExpr->getType(); auto paramTy = defaultExpr->getType();
// Re-create the default argument using the location info of the call site. // Re-create the default argument using the location info of the call site.
auto *initExpr = synthesizeCallerSideDefault(param, defaultExpr->getLoc()); auto *initExpr =
synthesizeCallerSideDefault(param, defaultExpr->getArgumentListLoc());
auto *dc = defaultExpr->ContextOrCallerSideExpr.get<DeclContext *>(); auto *dc = defaultExpr->ContextOrCallerSideExpr.get<DeclContext *>();
assert(dc && "Expected a DeclContext before type-checking caller-side arg"); assert(dc && "Expected a DeclContext before type-checking caller-side arg");

View File

@@ -106,6 +106,13 @@ struct TestDefaultedParen {
TestDefaultedParen.init() TestDefaultedParen.init()
struct HasInitWithDefaultArgs {
init(x: Int = 10, y: Int = 20, z: Int = 10)
}
HasInitWithDefaultArgs(z: 45)
HasInitWithDefaultArgs(y: 45, z: 89)
// RUN: %sourcekitd-test -req=cursor -pos=3:1 -end-pos=5:13 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK1 // RUN: %sourcekitd-test -req=cursor -pos=3:1 -end-pos=5:13 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK1
// CHECK1: ACTIONS BEGIN // CHECK1: ACTIONS BEGIN
@@ -139,6 +146,11 @@ TestDefaultedParen.init()
// RUN: %sourcekitd-test -req=cursor -pos=107:20 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-NORENAME // RUN: %sourcekitd-test -req=cursor -pos=107:20 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-NORENAME
// RUN: %sourcekitd-test -req=cursor -pos=113:24 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-GLOBAL
// RUN: %sourcekitd-test -req=cursor -pos=114:24 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-GLOBAL
// RUN: %sourcekitd-test -req=cursor -pos=114:31 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-GLOBAL
// RUN: %sourcekitd-test -req=cursor -pos=114:31 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-GLOBAL
// RUN: %sourcekitd-test -req=cursor -pos=35:10 -end-pos=35:16 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-RENAME-EXTRACT // RUN: %sourcekitd-test -req=cursor -pos=35:10 -end-pos=35:16 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-RENAME-EXTRACT
// RUN: %sourcekitd-test -req=cursor -pos=35:10 -end-pos=35:16 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-RENAME-EXTRACT // RUN: %sourcekitd-test -req=cursor -pos=35:10 -end-pos=35:16 -cursor-action %s -- %s | %FileCheck %s -check-prefix=CHECK-RENAME-EXTRACT