Skip to content
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

Improve type stubs #2369

Merged
merged 8 commits into from
Dec 4, 2023
Merged

Improve type stubs #2369

merged 8 commits into from
Dec 4, 2023

Conversation

jwortmann
Copy link
Member

@jwortmann jwortmann commented Dec 1, 2023

In the type stubs for sublime.py and sublime_plugin.py:

  • Adds docstrings, which are shown in the hover popups
  • Adds several missing API methods that were added over time in ST
  • Adds missing function parameters that were added over time in ST
  • Fixes many many bugs for the type annotations
  • Uses conventions from https://typing.readthedocs.io/en/latest/source/stubs.html, e.g. int | str instead of Union[int, str]

This also revealed a few inaccuracies in the code (return value of View.sheet(), use of deprecated constant, etc.), which I have fixed too.

There is also a wrong type annotation in the current code base at

def confirm(self, value: Optional[Tuple[int, Diagnostic]]) -> None:

because the value can never be a tuple, even if it was provided as a tuple for the ListInputItem constructor at
list_items.append(sublime.ListInputItem(text, (i, diagnostic), annotation=annotation, kind=kind))

A tuple is incompatible with sublime.Value, it still works here, but internally it is converted to a list. You can confirm this with a little plugin like this:

import sublime
import sublime_plugin


class InputHandlerTestCommand(sublime_plugin.WindowCommand):

    def run(self, arg1):
        pass

    def input(self, args):
        if 'arg1' not in args:
            return MyListInputHandler()

class MyListInputHandler(sublime_plugin.ListInputHandler):

    def name(self):
        return 'arg1'

    def list_items(self):
        return [sublime.ListInputItem('test', ("foo", 42))]

    def confirm(self, value):
        print(value)
        print(isinstance(value, tuple))
        print(isinstance(value, list))

Result:

['foo', 42]
False
True

I fixed this type incompatibility in the last commit (it looks a little bit ugly though, but I didn't want to extra add a new TypedDict for this).

@@ -246,7 +249,7 @@ def list_items(self) -> List[sublime.ListInputItem]:
text = "{}: {}".format(format_severity(diagnostic_severity(diagnostic)), first_line)
annotation = format_diagnostic_source_and_code(diagnostic)
kind = DIAGNOSTIC_KINDS[diagnostic_severity(diagnostic)]
list_items.append(sublime.ListInputItem(text, (i, diagnostic), annotation=annotation, kind=kind))
list_items.append(sublime.ListInputItem(text, [i, diagnostic], annotation=annotation, kind=kind))
Copy link
Member

@rchl rchl Dec 1, 2023

Choose a reason for hiding this comment

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

I wouldn't mind a typed dict like

DiagnosticInputItem = TypedDict('DiagnosticInputItem', {
    'index': int,
    'diagnostic': Diagnostic
}, total=True)

(been testing it so wrote it already)

but... this still throws type error due to it being incompatible with Dict[str, Any]. So if we'd need more hacks on top of that then it defeats the point.

@rchl
Copy link
Member

rchl commented Dec 4, 2023

Trying to compete with https://github.com/jfcherng-sublime/ST-API-stubs with those? ;)

Copy link
Member

@rchl rchl left a comment

Choose a reason for hiding this comment

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

I won't verify every modification in stubs manually but it looks pretty good.

@rchl rchl merged commit a83e4e8 into sublimelsp:main Dec 4, 2023
4 checks passed
@jwortmann jwortmann deleted the type-stubs branch December 5, 2023 08:38
@jwortmann
Copy link
Member Author

Trying to compete with https://github.com/jfcherng-sublime/ST-API-stubs with those? ;)

Yeah, but those stubs only target the 3.8 API environment, and they use a few custom type definitions/aliases which would show up in the hover popup. At first I actually considered to start with jfcherng's stubs, but then it turned out to be easier to just take the original sublime.py/sublime_plugin.py files from the 3.8 API, and go through all classes and functions by comparing them to the same files from the 3.3 API. There are a few function parameters with different names and also some functions are missing. And I optimized most of the docstrings to have nice formatting in the hover popup, etc.

When LSP switches to the 3.8 API it should be relatively simple to go through the files again, in order to add the new enums, change the parameter names that are different, and to add the functions that are exclusive to the 3.8 API.


Btw, I had hoped that you would squash the commits in this PR, because they are not really important and a bit of a mess, but nevermind :-)

@rchl
Copy link
Member

rchl commented Dec 5, 2023

Btw, I had hoped that you would squash the commits in this PR, because they are not really important and a bit of a mess, but nevermind :-)

I have force-pushed now. Watch out for conflicts.

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.

2 participants