textDocumentPositionParams: add optional range by adonovan · Pull Request #2027 · microsoft/language-server-protocol

@adonovan

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 #377
Fixes #1029

jul1u5, hasufell, ntc2, predragnikolic, sideeffffect, xzbdmw, chiawendt, arisgk, skewb1k, HighCommander4, and 2 more reacted with thumbs up emoji matklad, xzbdmw, sideeffffect, georgefst, arisgk, HighCommander4, and h9jiang reacted with heart emoji

@adonovan

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

@microsoft-github-policy-service agree company="Google"

@dbaeumer

@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

@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.

@adonovan

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)))))))

@adonovan

Is there anything we can do to help move this process along?

@xzbdmw

to merge something into the spec we usually require an implementation in at least one client

The "one client" seems always mean vscode.

@MagicRB

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?

@dbaeumer

@MagicRB can you point me to that client implementation?

@MagicRB

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)))))))

^

@sideeffffect

@tgodzik doesn't Scala's Language Server Metals also use "range"?

@tgodzik

@sideeffffect

@PolyMeilex

@adonovan

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?

sideeffffect, matklad, xzbdmw, davidbarsky, kmicklas, runiq, singiamtel, mweinelt, osa1, liff, and 38 more reacted with thumbs up emoji

@nik-rev

@dbaeumer

@dbaeumer

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.

@sideeffffect

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?

@dbaeumer

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.

@charlesottesen9

This was referenced

Sep 28, 2025

dbaeumer


/**
* 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.