-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Signature help turns off current-parameter display for non-trailing rest parameters #42592
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
Signature help turns off current-parameter display for non-trailing rest parameters #42592
Conversation
In signature help, the first rest parameter will always be the *last* 'current' parameter (disregarding types). Previously, the signature help current-parameter highlight was only correct for trailing rest parameters. However, with tuple types, you can now create non-trailing rest parameters. This PR now correctly highlights non-trailing rest parameters as the last 'current' parameter. For example, `names` should be the current parameter in all the calls below: ```ts declare function loading(...args: [...names: string[], allCaps: boolean, extra: boolean]): void; leading(/**/ leading('one', /**/ leading('one', 'two', /**/ ``` And, because signature help doesn't do real overload resolution, `names` is also the current parameter for other calls: ```ts leading(1, 2, 3, 'ill-typed', /**/ leading('fine', true, /**/ ```
Wait, we don't look at types here? So in a valid usage like loading("name1", "name2", /*allCaps*/ true, /**/ you’d always be stuck on |
Yeah, previously, we'd just do overload resolution and then highlight whichever parameter matched the count of arguments. This is more clever, but only a little. I don't think it's worthwhile to be too clever here. |
The checker code that iterates arguments and gets a matching parameter is buried pretty deep. It might be possible to expose that to the services layer, but I'm not sure how much scaffolding I'd have to make to make it work. |
What if we just don’t set a current argument since we know we won’t get it right? |
@typescript-bot pack this |
Heya @DanielRosenwasser, I've started to run the tarball bundle task on this PR at 692c590. You can monitor the build here. |
Another alternative might be to not flatten the signature if the tuple has a non-trailing rest element. |
@andrewbranch |
Well, uh, we don't even try to highlight the current parameter correctly for the last argument of this simple example: declare function mcduff(x, y, ...args)
mcduff(1, 2, 3, 4) So I think it's fine to fall back to that behaviour for now. I've got fairly simple code that deactivates the tuple expansion in case of non-trailing rests, which I'll push shortly. |
!!! |
src/services/signatureHelp.ts
Outdated
const lists = checker.getExpandedParameters(candidateSignature); | ||
return lists.map(parameterList => { | ||
const expansions = checker.getExpandedParameters(candidateSignature); | ||
const hasNonTrailingRest = expansions.some(e => e.some((p,i) => (p as TransientSymbol).checkFlags & CheckFlags.RestParameter && i !== e.length - 1)); |
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.
const hasNonTrailingRest = expansions.some(e => e.some((p,i) => (p as TransientSymbol).checkFlags & CheckFlags.RestParameter && i !== e.length - 1)); | |
const hasNonTrailingRest = expansions.some(e => e.some((p, i) => (p as TransientSymbol).checkFlags & CheckFlags.RestParameter && i !== e.length - 1)); |
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.
Can we get an example with a middle spread too?
I still feel a bit conflicted because this displays more poorly. Maybe |
I was wondering about setting |
Well, editors today have to sort of handle the case where there's too many parentheses, right? I don't exactly know what the expected behavior is. Maybe @CyrusNajmabadi has some thoughts from the Roslyn side. |
It already works fine to have argumentIndex > parameters.length if you want to turn off current-parameter highlighting. I think that's a pretty good option. |
This reverts commit f0896f3.
1. Trailing rest keeps highlight at end instead of going off the end. 2. Non-trailing rest disable highlight entirely (by putting the index one past the end).
The latest commit:
|
const firstRest = findIndex(selected.parameters, p => !!p.isRest); | ||
if (-1 < firstRest && firstRest < selected.parameters.length - 1) { | ||
// We don't have any code to get this correct; instead, don't highlight a current parameter AT ALL | ||
help.argumentIndex = selected.parameters.length; |
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.
We could also make this conditional upon argumentIndex >= firstRest
if we wanted parameter highlighting to work up until the first rest, where the ambiguity begins. But maybe that would be a worse experience than consistently seeing no highlighting. I personally feel like parameter highlighting is pretty useful when parameters have JSDoc description, and it might be worthwhile to show them as often as we can. But it might be pretty confusing for it to stop working halfway through typing call arguments. Don’t have a super strong opinion here.
With tuple types as rest parameters, you can now create non-trailing rest parameters. However, the simplistic current-parameter index matching just increments right past them. This PR turns off the current-parameter highlight for non-trailing rest parameters.
For these calls, there is no current parameter, because signature help doesn't have any code to map multiple arguments to a single rest parameter. But at least it's never wrong!
Fixes #42292
Scope Creep Time!
I improved current-parameter highlighting for trailing rest parameters as well: the highlight now stops at the end.