Skip to content

add additional exports to public API - #2910

Merged
rchl merged 23 commits into
mainfrom
feat/public-api
Sep 27, 2026
Merged

rchl merged 23 commits into
mainfrom
feat/public-api

Conversation

@rchl

@rchl rchl commented May 17, 2026 •

Copy link
Copy Markdown
Member

@jwortmann

jwortmann commented May 17, 2026 •

Copy link
Copy Markdown
Member

There are probably various other utility functions from views.py that could be useful to be exported in the plugin API. Whenever you want to implement the handling of a custom request or notification, there is a high chance that you need to create some LSP type from a position or a selection in the file. For example some more functions that I used in LSP-Tinymist and LSP-julia are position, region_to_range, text_document_identifier, text_document_position_params.

https://github.com/sublimelsp/LSP-Tinymist/blob/5173ee56e777e3587f4823ef82107905e7445cd5/plugin.py#L22-L25
https://github.com/sublimelsp/LSP-julia/blob/6575c619fe9604845ddbd0ef0b542e7943b662d5/plugin.py#L20-L21

If we want to export more of them in the public API, perhaps it would be useful to reconsider some of the names, because there is a bit of inconsistency. A few function names are in the form "X_to_Y" (point_to_offset, region_to_range), while others are only named after the resulting type (position instead of offset_to_position), and even a third variant of utility function names use a get_ prefix (get_uri_and_range_from_location instead of location_to_uri_and_range).

Also the Point name for that custom class is perhaps not the best name, because meanwhile ST has introduced a type with the same name (in the sublime_types module), representing just an offset (int alias): https://www.sublimetext.com/docs/api_reference.html#sublime.Point
Perhaps a better name for the custom class from this package would be TextPosition (because it corresponds to a LSP Position)?

@jwortmann

Copy link
Copy Markdown
Member

I think for backwards compatibility with packages that import Point directly from LSP.plugin.core.protocol, we could rename Point to TextPosition in the LSP code base, export TextPosition in the public API, and add this into the core/protocol.py file:

@deprecated('Use TextPosition instead')
class Point(TextPosition):
    pass

@rchl

rchl commented May 22, 2026

Copy link
Copy Markdown
Member Author

I think for backwards compatibility with packages that import Point directly from LSP.plugin.core.protocol, we could rename Point to TextPosition in the LSP code base, export TextPosition in the public API, and add this into the core/protocol.py file:

Did that but not using new name in the code as I don't want to make things more difficult for @rwols. Can be renamed internally at later time.

As for other utility functions and their inconsistent names, perhaps we could group those into some classes with just static functions. But then we'd have to come up with some logical grouping and naming which will probably take some time.

@jwortmann

jwortmann commented May 22, 2026 •

Copy link
Copy Markdown
Member

Did that but not using new name in the code as I don't want to make things more difficult for @rwols. Can be renamed internally at later time.

Ok. But I think you still need to update a few references to the Point class inside of the TextPosition class itself. I would also rename the parameter in from_lsp from point to position.

And as far as I can tell, the basic purpose of this class is to make the LSP Position comparable (by defining __lt__ method). I wonder could we get this automatically if we just derive from NamedTuple:

>>> from typing import TypedDict
>>> from typing import NamedTuple
>>> class Position(TypedDict):
...     line: int
...     character: int
...
>>> class TextPosition(NamedTuple):
...     row: int
...     col: int
...     @classmethod
...     def from_lsp(cls, position: Position) -> TextPosition:
...         return TextPosition(position['line'], position['character'])
...     def to_lsp(self) -> Position:
...         return {'line': self.row, 'character': self.col}
...
>>> p1 = TextPosition.from_lsp({'line': 3, 'character': 5})
>>> p2 = TextPosition.from_lsp({'line': 3, 'character': 10})
>>> p1 < p2
True
>>> p1.to_lsp()
{'line': 3, 'character': 5}
>>> p1.row
3
>>> p3 = TextPosition.from_lsp({'line': 3, 'character': 5})
>>> p1 == p3
True

@rchl

rchl commented May 22, 2026 •

Copy link
Copy Markdown
Member Author

That wouldn't have int coercion on init but I guess we don't really need that.

Also it would pass TextPosition(1, 2) == (1, 2) which we currently don't allow. Perhaps also OK?

Subclassing wouldn't work correctly for NamedTuple, though, I believe.

@rchl

rchl commented May 22, 2026

Copy link
Copy Markdown
Member Author

It can be a dataclass with a caveat that comparing Point and TextPosition won't work:

>>> from LSP.plugin.core.protocol import Point, TextPosition
>>> a = Point(1,1)
>>> b = TextPosition(1,1)
>>> a==b
False

@rwols

rwols commented Jul 11, 2026

Copy link
Copy Markdown
Member

Perhaps you could merge with the latest changes from the main branch to run the handy new β€œtype-check community packages” GH action?

@rchl

rchl commented Jul 12, 2026

Copy link
Copy Markdown
Member Author

All appears to pass.
I've also tested merging with asyncio branch and there was just a one trivial conflict.

@rwols rwols left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really have a big opinion on the function names. Looks good to me in any case.

Comment thread plugin/core/views.py Resolved
Comment thread plugin/core/views.py


def point_to_offset(point: Point, view: sublime.View) -> int:
def point_to_offset(point: TextPosition, view: sublime.View) -> int:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before we export these in the public API, could we also make the argument order consistent?

The exported offset_to_point, offset_to_position, region_to_range and text_document_position_params take the View as the first argument, while point_to_offset and position_to_offset have that as the second argument. I think it would be nice if all utility functions which take a View have it as the first argument.

Changing the argument order in point_to_offset would affect

  • LSP-typescript
  • LSP-julia
  • LSP-rust-anylyzer

And in position_to_offset would affect

  • LSP-copilot
  • LSP-typescript
  • LSP-tsgo
  • LSP-some-sass

@jwortmann jwortmann Jul 23, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to maintain backwards compatibility for those helper packages for now, we could leave these two functions witch current argument order in views.py and mark them as deprecated, but also copy them with the updated argument order into another file. And then just import the updated functions from the new locations for the public API (in __init__.py). Later when all helper packages are updated to the new argument order, we could remove the deprecated functions and just move the updated ones back into views.py.

@netlify

netlify Bot commented Sep 24, 2026

Copy link
Copy Markdown

βœ… Deploy Preview for sublime-lsp ready!

Name Link
πŸ”¨ Latest commit 1f731b1
πŸ” Latest deploy log https://app.netlify.com/projects/sublime-lsp/deploys/6ab58cd3ea08b60008c92f26
😎 Deploy Preview https://deploy-preview-2910--sublime-lsp.netlify.app
πŸ“± Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Sep 24, 2026

Copy link
Copy Markdown

βœ… Deploy Preview for sublime-lsp ready!

Name Link
πŸ”¨ Latest commit e45f2df
πŸ” Latest deploy log https://app.netlify.com/projects/sublime-lsp/deploys/6ab58cdf87a6e60008c8b40a
😎 Deploy Preview https://deploy-preview-2910--sublime-lsp.netlify.app
πŸ“± Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@rchl
rchl changed the base branch from main to fix/testing September 26, 2026 22:38
Base automatically changed from fix/testing to main September 27, 2026 10:12
@rchl
rchl merged commit 300dc77 into main Sep 27, 2026
8 of 9 checks passed
@rchl
rchl deleted the feat/public-api branch September 27, 2026 15:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants