Skip to content

Commit

Permalink
Merge branch 'main' into no-restart
Browse files Browse the repository at this point in the history
  • Loading branch information
jwortmann committed Apr 21, 2024
2 parents b27b317 + 4c8da78 commit 8a16356
Show file tree
Hide file tree
Showing 84 changed files with 860 additions and 809 deletions.
5 changes: 3 additions & 2 deletions boot.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import annotations
import os
import sublime
import sublime_plugin
Expand Down Expand Up @@ -36,7 +37,6 @@
from .plugin.core.transports import kill_all_subprocesses
from .plugin.core.tree_view import LspCollapseTreeItemCommand
from .plugin.core.tree_view import LspExpandTreeItemCommand
from .plugin.core.typing import Any, Optional, List, Type, Dict
from .plugin.core.views import LspRunTextCommandHelperCommand
from .plugin.document_link import LspOpenLinkCommand
from .plugin.documents import DocumentSyncListener
Expand Down Expand Up @@ -86,6 +86,7 @@
from .plugin.tooling import LspOnDoubleClickCommand
from .plugin.tooling import LspParseVscodePackageJson
from .plugin.tooling import LspTroubleshootServerCommand
from typing import Any, Dict, List, Optional, Type


def _get_final_subclasses(derived: List[Type], results: List[Type]) -> None:
Expand All @@ -98,7 +99,7 @@ def _get_final_subclasses(derived: List[Type], results: List[Type]) -> None:


def _register_all_plugins() -> None:
plugin_classes = [] # type: List[Type[AbstractPlugin]]
plugin_classes: List[Type[AbstractPlugin]] = []
_get_final_subclasses(AbstractPlugin.__subclasses__(), plugin_classes)
for plugin_class in plugin_classes:
try:
Expand Down
1 change: 1 addition & 0 deletions dependencies.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
">=4096": [
"bracex",
"mdpopups",
"typing_extensions",
"wcmatch"
]
}
Expand Down
27 changes: 15 additions & 12 deletions plugin/code_actions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import annotations
from .core.promise import Promise
from .core.protocol import CodeAction
from .core.protocol import CodeActionKind
Expand All @@ -11,7 +12,6 @@
from .core.sessions import AbstractViewListener
from .core.sessions import SessionBufferProtocol
from .core.settings import userprefs
from .core.typing import Any, List, Dict, Callable, Optional, Tuple, TypeGuard, Union, cast
from .core.views import entire_content_region
from .core.views import first_selection_region
from .core.views import format_code_actions_for_quick_panel
Expand All @@ -21,6 +21,9 @@
from abc import ABCMeta
from abc import abstractmethod
from functools import partial
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
from typing import cast
from typing_extensions import TypeGuard
import sublime

ConfigName = str
Expand All @@ -37,10 +40,10 @@ class CodeActionsManager:
"""Manager for per-location caching of code action responses."""

def __init__(self) -> None:
self._response_cache = None # type: Optional[Tuple[str, Promise[List[CodeActionsByConfigName]]]]
self.menu_actions_cache_key = None # type: Optional[str]
self.refactor_actions_cache = [] # type: List[Tuple[str, CodeAction]]
self.source_actions_cache = [] # type: List[Tuple[str, CodeAction]]
self._response_cache: Optional[Tuple[str, Promise[List[CodeActionsByConfigName]]]] = None
self.menu_actions_cache_key: Optional[str] = None
self.refactor_actions_cache: List[Tuple[str, CodeAction]] = []
self.source_actions_cache: List[Tuple[str, CodeAction]] = []

def request_for_region_async(
self,
Expand Down Expand Up @@ -74,7 +77,7 @@ def request_for_region_async(
self.source_actions_cache.clear()

def request_factory(sb: SessionBufferProtocol) -> Optional[Request]:
diagnostics = [] # type: List[Diagnostic]
diagnostics: List[Diagnostic] = []
for diag_sb, diags in session_buffer_diagnostics:
if diag_sb == sb:
diagnostics = diags
Expand Down Expand Up @@ -122,7 +125,7 @@ def request_factory(sb: SessionBufferProtocol) -> Optional[Request]:
matching_kinds = get_matching_on_save_kinds(on_save_actions, session_kinds)
if not matching_kinds:
return None
diagnostics = [] # type: List[Diagnostic]
diagnostics: List[Diagnostic] = []
for diag_sb, diags in session_buffer_diagnostics:
if diag_sb == sb:
diagnostics = diags
Expand Down Expand Up @@ -155,13 +158,13 @@ def on_response(
actions = response_filter(sb, response)
return (sb.session.config.name, actions)

tasks = [] # type: List[Promise[CodeActionsByConfigName]]
tasks: List[Promise[CodeActionsByConfigName]] = []
for sb in listener.session_buffers_async('codeActionProvider'):
session = sb.session
request = request_factory(sb)
if request:
response_handler = partial(on_response, sb)
task = session.send_request_task(request) # type: Promise[Optional[List[CodeActionOrCommand]]]
task: Promise[Optional[List[CodeActionOrCommand]]] = session.send_request_task(request)
tasks.append(task.then(response_handler))
# Return only results for non-empty lists.
return Promise.all(tasks) \
Expand All @@ -172,7 +175,7 @@ def on_response(


def get_session_kinds(sb: SessionBufferProtocol) -> List[CodeActionKind]:
session_kinds = sb.get_capability('codeActionProvider.codeActionKinds') # type: Optional[List[CodeActionKind]]
session_kinds: Optional[List[CodeActionKind]] = sb.get_capability('codeActionProvider.codeActionKinds')
return session_kinds or []


Expand Down Expand Up @@ -254,7 +257,7 @@ def _handle_response_async(self, responses: List[CodeActionsByConfigName]) -> No
if self._cancelled:
return
view = self._task_runner.view
tasks = [] # type: List[Promise]
tasks: List[Promise] = []
for config_name, code_actions in responses:
session = self._task_runner.session_by_name(config_name, 'codeActionProvider')
if session:
Expand Down Expand Up @@ -308,7 +311,7 @@ def _run_async(self, only_kinds: Optional[List[CodeActionKind]] = None) -> None:

def _handle_code_actions(self, response: List[CodeActionsByConfigName], run_first: bool = False) -> None:
# Flatten response to a list of (config_name, code_action) tuples.
actions = [] # type: List[Tuple[ConfigName, CodeActionOrCommand]]
actions: List[Tuple[ConfigName, CodeActionOrCommand]] = []
for config_name, session_actions in response:
actions.extend([(config_name, action) for action in session_actions])
if actions:
Expand Down
12 changes: 7 additions & 5 deletions plugin/code_lens.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
from __future__ import annotations
from .core.constants import CODE_LENS_ENABLED_KEY
from .core.protocol import CodeLens
from .core.protocol import CodeLensExtended
from .core.protocol import Error
from .core.typing import List, Tuple, Dict, Iterable, Optional, Generator, Union, cast
from .core.registry import LspTextCommand
from .core.registry import LspWindowCommand
from .core.registry import windows
from .core.views import make_command_link
from .core.views import range_to_region
from html import escape as html_escape
from functools import partial
from typing import Dict, Generator, Iterable, List, Optional, Tuple, Union
from typing import cast
import itertools
import sublime

Expand Down Expand Up @@ -108,7 +110,7 @@ def __init__(self, view: sublime.View) -> None:
self.view = view
self._init = False
self._phantom = sublime.PhantomSet(view, self.CODE_LENS_KEY)
self._code_lenses = {} # type: Dict[Tuple[int, int], List[CodeLensData]]
self._code_lenses: Dict[Tuple[int, int], List[CodeLensData]] = {}

def clear(self) -> None:
self._code_lenses.clear()
Expand All @@ -134,10 +136,10 @@ def handle_response(self, session_name: str, response: List[CodeLens]) -> None:
self._init = True
responses = [CodeLensData(data, self.view, session_name) for data in response]
responses.sort(key=lambda c: c.region)
result = {
result: Dict[Tuple[int, int], List[CodeLensData]] = {
region.to_tuple(): list(groups)
for region, groups in itertools.groupby(responses, key=lambda c: c.region)
} # type: Dict[Tuple[int, int], List[CodeLensData]]
}

# Fast path: no extra work to do
if self.is_empty():
Expand Down Expand Up @@ -215,7 +217,7 @@ def run(self, edit: sublime.Edit) -> None:
listener = windows.listener_for_view(self.view)
if not listener:
return
code_lenses = [] # type: List[CodeLensExtended]
code_lenses: List[CodeLensExtended] = []
for region in self.view.sel():
for sv in listener.session_views_async():
code_lenses.extend(sv.get_resolved_code_lenses_for_region(region))
Expand Down
9 changes: 5 additions & 4 deletions plugin/color.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from __future__ import annotations
from .core.edit import apply_text_edits
from .core.protocol import ColorInformation
from .core.protocol import ColorPresentation
from .core.protocol import ColorPresentationParams
from .core.protocol import Request
from .core.registry import LspTextCommand
from .core.typing import List
from .core.views import range_to_region
from .core.views import text_document_identifier
from typing import List
import sublime


Expand All @@ -19,11 +20,11 @@ def run(self, edit: sublime.Edit, color_information: ColorInformation) -> None:
if session:
self._version = self.view.change_count()
self._range = color_information['range']
params = {
params: ColorPresentationParams = {
'textDocument': text_document_identifier(self.view),
'color': color_information['color'],
'range': self._range
} # type: ColorPresentationParams
}
session.send_request_async(Request.colorPresentation(params, self.view), self._handle_response_async)

def want_event(self) -> bool:
Expand All @@ -38,7 +39,7 @@ def _handle_response_async(self, response: List[ColorPresentation]) -> None:
if self._version != self.view.change_count():
return
old_text = self.view.substr(range_to_region(self._range, self.view))
self._filtered_response = [] # type: List[ColorPresentation]
self._filtered_response: List[ColorPresentation] = []
for item in response:
# Filter out items that would apply no change
text_edit = item.get('textEdit')
Expand Down
35 changes: 19 additions & 16 deletions plugin/completion.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import annotations
from .core.constants import COMPLETION_KINDS
from .core.edit import apply_text_edits
from .core.logging import debug
Expand All @@ -19,24 +20,26 @@
from .core.registry import LspTextCommand
from .core.sessions import Session
from .core.settings import userprefs
from .core.typing import Callable, List, Dict, Optional, Generator, Tuple, Union, cast, Any, TypeGuard
from .core.views import FORMAT_STRING, FORMAT_MARKUP_CONTENT
from .core.views import MarkdownLangMap
from .core.views import minihtml
from .core.views import range_to_region
from .core.views import show_lsp_popup
from .core.views import text_document_position_params
from .core.views import update_lsp_popup
from typing import Any, Callable, Dict, Generator, List, Optional, Tuple, Union
from typing import cast
from typing_extensions import TypeAlias, TypeGuard
import functools
import html
import sublime
import weakref
import webbrowser

SessionName = str
CompletionResponse = Union[List[CompletionItem], CompletionList, None]
ResolvedCompletions = Tuple[Union[CompletionResponse, Error], 'weakref.ref[Session]']
CompletionsStore = Tuple[List[CompletionItem], CompletionItemDefaults]
SessionName: TypeAlias = str
CompletionResponse: TypeAlias = Union[List[CompletionItem], CompletionList, None]
ResolvedCompletions: TypeAlias = Tuple[Union[CompletionResponse, Error], 'weakref.ref[Session]']
CompletionsStore: TypeAlias = Tuple[List[CompletionItem], CompletionItemDefaults]


def format_completion(
Expand All @@ -56,7 +59,7 @@ def format_completion(
lsp_detail = (item.get('detail') or "").replace("\n", " ")
completion_kind = item.get('kind')
kind = COMPLETION_KINDS.get(completion_kind, sublime.KIND_AMBIGUOUS) if completion_kind else sublime.KIND_AMBIGUOUS
details = [] # type: List[str]
details: List[str] = []
if can_resolve_completion_items or item.get('documentation'):
# Not using "make_command_link" in a hot path to avoid slow json.dumps.
args = '{{"view_id":{},"command":"lsp_resolve_docs","args":{{"index":{},"session_name":"{}"}}}}'.format(
Expand Down Expand Up @@ -132,7 +135,7 @@ def completion_with_defaults(item: CompletionItem, item_defaults: CompletionItem
""" Currently supports defaults for: ["editRange", "insertTextFormat", "data"] """
if not item_defaults:
return item
default_text_edit = None # type: Optional[Union[TextEdit, InsertReplaceEdit]]
default_text_edit: Optional[Union[TextEdit, InsertReplaceEdit]] = None
edit_range = item_defaults.get('editRange')
if edit_range:
# If textEditText is not provided and a list's default range is provided
Expand Down Expand Up @@ -182,7 +185,7 @@ def __init__(
self._triggered_manually = triggered_manually
self._on_done_async = on_done_async
self._resolved = False
self._pending_completion_requests = {} # type: Dict[int, weakref.ref[Session]]
self._pending_completion_requests: Dict[int, weakref.ref[Session]] = {}

def query_completions_async(self, sessions: List[Session]) -> None:
promises = [self._create_completion_request_async(session) for session in sessions]
Expand All @@ -197,7 +200,7 @@ def _create_completion_request_async(self, session: Session) -> Promise[Resolved
return promise.then(lambda response: self._on_completion_response_async(response, request_id, weak_session))

def _on_completion_response_async(
self, response: CompletionResponse, request_id: int, weak_session: 'weakref.ref[Session]'
self, response: CompletionResponse, request_id: int, weak_session: weakref.ref[Session]
) -> ResolvedCompletions:
self._pending_completion_requests.pop(request_id, None)
return (response, weak_session)
Expand All @@ -206,10 +209,10 @@ def _resolve_completions_async(self, responses: List[ResolvedCompletions]) -> No
if self._resolved:
return
LspSelectCompletionCommand.completions = {}
items = [] # type: List[sublime.CompletionItem]
item_defaults = {} # type: CompletionItemDefaults
errors = [] # type: List[Error]
flags = 0 # int
items: List[sublime.CompletionItem] = []
item_defaults: CompletionItemDefaults = {}
errors: List[Error] = []
flags = 0
prefs = userprefs()
if prefs.inhibit_snippet_completions:
flags |= sublime.INHIBIT_EXPLICIT_COMPLETIONS
Expand All @@ -225,7 +228,7 @@ def _resolve_completions_async(self, responses: List[ResolvedCompletions]) -> No
session = weak_session()
if not session:
continue
response_items = [] # type: List[CompletionItem]
response_items: List[CompletionItem] = []
if isinstance(response, dict):
response_items = response["items"] or []
item_defaults = response.get('itemDefaults') or {}
Expand Down Expand Up @@ -291,7 +294,7 @@ def _handle_resolve_response_async(self, language_map: Optional[MarkdownLangMap]
detail = self._format_documentation(item.get('detail') or "", language_map)
documentation = self._format_documentation(item.get("documentation") or "", language_map)
if not documentation:
markdown = {"kind": MarkupKind.Markdown, "value": "*No documentation available.*"} # type: MarkupContent
markdown: MarkupContent = {"kind": MarkupKind.Markdown, "value": "*No documentation available.*"}
# No need for a language map here
documentation = self._format_documentation(markdown, None)
minihtml_content = ""
Expand Down Expand Up @@ -337,7 +340,7 @@ def run(self, edit: sublime.Edit, event: Optional[dict] = None) -> None:

class LspSelectCompletionCommand(LspTextCommand):

completions = {} # type: Dict[SessionName, CompletionsStore]
completions: Dict[SessionName, CompletionsStore] = {}

def run(self, edit: sublime.Edit, index: int, session_name: str) -> None:
items, item_defaults = LspSelectCompletionCommand.completions[session_name]
Expand Down
1 change: 1 addition & 0 deletions plugin/configuration.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import annotations
from .core.registry import windows
from .core.settings import client_configs
from .core.windows import WindowManager
Expand Down
5 changes: 3 additions & 2 deletions plugin/core/active_request.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from __future__ import annotations
from .sessions import SessionViewProtocol
from .progress import ProgressReporter
from .progress import ViewProgressReporter
from .progress import WindowProgressReporter
from .protocol import Request
from .typing import Any, Optional, Dict
from typing import Any, Dict, Optional
from weakref import ref
import sublime

Expand All @@ -18,7 +19,7 @@ def __init__(self, sv: SessionViewProtocol, request_id: int, request: Request) -
self.weaksv = ref(sv)
self.request_id = request_id
self.request = request
self.progress = None # type: Optional[ProgressReporter]
self.progress: Optional[ProgressReporter] = None
# `request.progress` is either a boolean or a string. If it's a boolean, then that signals that the server does
# not support client-initiated progress. However, for some requests we still want to notify some kind of
# progress to the end-user. This is communicated by the boolean value being "True".
Expand Down
Loading

0 comments on commit 8a16356

Please sign in to comment.