Description
Given code like this:
def foo(a, b): ...
foo(1, 2, |)
If the cursor is on the last parameter to the call, we want to specify that nothing should be highlighted. Additionally, the function may be overloaded, in which case we specify per-signature active parameters (microsoft/vscode#94637). Some of those overloads may not match what the user has written, and so none of the parameters should be highlighted.
The spec says:
/**
* The active parameter of the active signature. If omitted or the value
* lies outside the range of `signatures[activeSignature].parameters`
* defaults to 0 if the active signature has parameters. If
* the active signature has no parameters it is ignored.
* In future version of the protocol this property might become
* mandatory to better express the active parameter if the
* active signature does have any.
*/
activeParameter?: uinteger;
And for the the signature itself:
/**
* The index of the active parameter.
*
* If provided, this is used in place of `SignatureHelp.activeParameter`.
*
* @since 3.16.0
*/
activeParameter?: uinteger;
This means there is no spec-compliant way to say "don't highlight any parameters"; omitting the active parameter on the signature defers to the old-style active parameter field, which will be zero (the first parameter) if not provided or specified with an out of bounds value.
We can work around this in pyright/pylance by making use of the fact that the VS Code LSP client doesn't verify the values its given when they are numbers:
VS Code doesn't implement the "if out of bounds, assume zero" part of the spec, instead not highlighting a parameter, which is what we want, so it works. We've been using -1
as the out of bounds value: https://github.com/microsoft/pyright/blob/48a5f1284055e61f9887a6e0fbfb6176bae730bf/packages/pyright-internal/src/languageServerBase.ts#L702
However, the specs were retroactively changed to specify uinteger
for many values, and some clients strictly check that the value is non-negative (microsoft/pyright#1783), so we will likely need to move to some other out of bounds value to maintain this hack. Looking at other languages, I can see that gopls
is also relying on this behavior, providing indexes past the end of the parameter list to avoid highlighting, so we can do that too.
But, swapping one hack for another doesn't really address the original need of being able to explicitly specify that no parameter is selected (for the single signature or for all).
Can the spec be modified in some way to explicitly allow something like this? E.g.:
- Treat "index past end of parameter list" as "no highlight"; this may match the behavior of existing language servers.
- Allow explicitly setting
null
or something to say "no highlight" behind a capability.