-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[CodeComplete] Match argument labels when completing function arguments #36538
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
26ab904
to
48d660c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for fixing this issue!
lib/IDE/ExprContextAnalysis.cpp
Outdated
for (unsigned i = PosInParams; i < Params.size(); ++i) { | ||
if (Params[i].getLabel() == ArgName) { | ||
// We have found a label match. Advance the position in the params | ||
// to point to the param after the one with this label. | ||
PosInParams = i + 1; | ||
FoundLabelMatch = true; | ||
break; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, we look for the label even if there are non-matching not defaulted parameters.
So this suggest z: <#Int#>
class C {
func foo(x: Int, y: Int, z: Int) {}
}
func test(c: C) {
c.foo(y: 1, #^HERE^#)
}
which is reasonable. If we don't have a test case like this, please add it while you are here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it does. I added the test case you suggested.
auto ArgName = tuple->getElementName(PosInArgs); | ||
bool FoundLabelMatch = false; | ||
for (unsigned i = PosInParams; i < Params.size(); ++i) { | ||
if (Params[i].getLabel() == ArgName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class C {
func foo(x: Int..., y: Int, z: Int) {}
}
func test(c: C) {
c.foo(x: 10, 20, 30, y: 40, #^HERE^#)
}
When PosInArgs
is 1
, this loop ends up with ++PosInParams
which is incorrect. I think we need some special handling for variadic parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good thinking! I added special handling for variadics so that variadic parameters consume all unlabelled arguments following them.
Also added the test case you suggested.
48d660c
to
385917e
Compare
Previously, we always assumed that the position in the arguments would match the position in the parameter, which isn’t true in case of defaulted arguments. Try matching parameters based on argument labels to give better completion results. Fixes rdar://60346573
385917e
to
433d756
Compare
@swift-ci Please smoke test |
@swift-ci Please smoke test Windows |
Previously, we always assumed that the position in the arguments would match the position in the parameter, which isn’t true in case of defaulted arguments. Try matching parameters based on argument labels to give better completion results.
Fixes rdar://60346573