textDocumentPositionParams: add optional range by adonovan · Pull Request #2027 · microsoft/language-server-protocol
This change adds an optional range field to textDocumentPositionParams so that clients can, for example, query a subexpression such as x.f within a larger expression g(x.f[i]). Also, clarify the text about cursor bias. Fixes microsoft#377 Fixes microsoft#1029
@adonovan to merge something into the spec we usually require an implementation in at least one client. Are you willing to provide that as well.
And I was wondering if we at least should flag this as a feature / capability from the client side so that the servers know what to expect. In VS Code for example there will be a lot of cases where we can't fill in the range since it is not part of the original API request and getting it from the active editor is not possible (e.g. there might not be one, the cursor has been moved, ...)
@adonovan to merge something into the spec we usually require an implementation in at least one client. Are you willing to provide that as well.
I already have an implementation in eglot (Emacs): it's just a few lines.
And I was wondering if we at least should flag this as a feature / capability from the client side so that the servers know what to expect. In VS Code for example there will be a lot of cases where we can't fill in the range since it is not part of the original API request and getting it from the active editor is not possible (e.g. there might not be one, the cursor has been moved, ...)
I don't think this needs to be a capability; it's just an optional field, and its type tells the server that it can't be relied upon.
Sorry for not providing it earlier, but here's the diff to eglot:
(defun eglot--TextDocumentPositionParams () "Compute TextDocumentPositionParams." (list :textDocument (eglot--TextDocumentIdentifier) - :position (eglot--pos-to-lsp-position))) + :position (eglot--pos-to-lsp-position)) + (if (region-active-p) + (list :range + (list :start (eglot--pos-to-lsp-position (region-beginning)) + :end (eglot--pos-to-lsp-position (region-end)))))))
to merge something into the spec we usually require an implementation in at least one client
The "one client" seems always mean vscode.
to merge something into the spec we usually require an implementation in at least one client
The "one client" seems always mean vscode.
the one client :) but on a serious note, an implementation exists so the "at least one implementation" requirement is fulfilled, what else is blocking this?
@MagicRB can you point me to that client implementation?
Sorry for not providing it earlier, but here's the diff to eglot:
(defun eglot--TextDocumentPositionParams () "Compute TextDocumentPositionParams." (list :textDocument (eglot--TextDocumentIdentifier) - :position (eglot--pos-to-lsp-position))) + :position (eglot--pos-to-lsp-position)) + (if (region-active-p) + (list :range + (list :start (eglot--pos-to-lsp-position (region-beginning)) + :end (eglot--pos-to-lsp-position (region-end)))))))
^
@tgodzik doesn't Scala's Language Server Metals also use "range"?
Hey Microsoft folks, it seems like you are all very busy on other projects. (If MS is anything like Google, I suspect AI is the reason.)
Is it time for the community to start planning how control of the protocol can be transferred to a public consortium?
IMO we should in addition to the optional property add a client capability to signal if client in general compute that property. Otherwise it is not easy for a server to decide, whether there was no range or whether the client didn't provide it. However if we do that then clients need to consistently fill the property in. Or we can have a capability per request but that seems like overkill.
it is not easy for a server to decide, whether there was no range or whether the client didn't provide it
I'm wondering what would be the benefit of this? What would be such a distinction useful for?
If a server wants to implement a feature that requires having that property and a client will never provided it then there is no need to register a handler for it and the client doesn't call the server unnecessarily.
This was referenced
Sep 28, 2025|
|
||
| /** | ||
| * The position inside the text document. | ||
| * The cursor position within the text document. |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since LSP requests are also allowed for document that are not open we shouldn't talk about a cursor.
| */ | ||
| position: Position; | ||
|
|
||
| /** |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. We need to come up with something that doesn't talk about a selection since clients might send this even for documents not open in an editor.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters