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

feat: add GlobalLspListener #2523

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
6 changes: 6 additions & 0 deletions plugin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
from .core.protocol import Notification
from .core.protocol import Request
from .core.protocol import Response
from .core.registry import AbstractViewListener
from .core.registry import LspTextCommand
from .core.registry import LspWindowCommand
from .core.registry import windows
from .core.sessions import AbstractPlugin
from .core.sessions import register_plugin
from .core.sessions import Session
Expand All @@ -25,12 +27,14 @@
from .core.version import __version__
from .core.views import MarkdownLangMap
from .core.views import uri_from_view
from .core.windows import GlobalLspListener
from .core.workspace import WorkspaceFolder

# This is the public API for LSP-* packages
__all__ = [
'__version__',
'AbstractPlugin',
'AbstractViewListener',
'apply_text_edits',
'ClientConfig',
'css',
Expand All @@ -41,6 +45,7 @@
'FileWatcherEvent',
'FileWatcherEventType',
'FileWatcherProtocol',
'GlobalLspListener',
'LspTextCommand',
'LspWindowCommand',
'MarkdownLangMap',
Expand All @@ -56,5 +61,6 @@
'unregister_plugin',
'uri_from_view',
'uri_to_filename', # deprecated
'windows',
'WorkspaceFolder',
]
46 changes: 43 additions & 3 deletions plugin/core/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
from .views import make_link
from .workspace import ProjectFolders
from .workspace import sorted_workspace_folders
from abc import ABCMeta
from abc import abstractmethod
from collections import deque
from collections import OrderedDict
from datetime import datetime
Expand Down Expand Up @@ -71,11 +73,29 @@ def set_diagnostics_count(view: sublime.View, errors: int, warnings: int) -> Non
pass


class GlobalLspListener(metaclass=ABCMeta):

@abstractmethod
def on_session_view_initialized_async(self, view_listener: AbstractViewListener, session: Session) -> None:
raise NotImplementedError()

@abstractmethod
def on_session_view_shutdown_async(self, view_listener: AbstractViewListener, session: Session) -> None:
raise NotImplementedError()


class WindowManager(Manager, WindowConfigChangeListener):

def __init__(self, window: sublime.Window, workspace: ProjectFolders, config_manager: WindowConfigManager) -> None:
def __init__(
self,
window: sublime.Window,
workspace: ProjectFolders,
config_manager: WindowConfigManager,
global_listener: GlobalLspListener,
) -> None:
self._window = window
self._config_manager = config_manager
self._global_listener = global_listener
self._sessions: set[Session] = set()
self._workspace = workspace
self._pending_listeners: deque[AbstractViewListener] = deque()
Expand Down Expand Up @@ -199,6 +219,8 @@ def _publish_sessions_to_listener_async(self, listener: AbstractViewListener) ->
except Exception as ex:
message = f"failed to register session {session.config.name} to listener {listener}"
exception_log(message, ex)
return
self._global_listener.on_session_view_initialized_async(listener, session)

def sessions(self, view: sublime.View, capability: str | None = None) -> Generator[Session, None, None]:
inside_workspace = self._workspace.contains(view)
Expand Down Expand Up @@ -388,6 +410,7 @@ def on_post_exit_async(self, session: Session, exit_code: int, exception: Except
self._sessions.discard(session)
for listener in self._listeners:
listener.on_session_shutdown_async(session)
self._global_listener.on_session_view_shutdown_async(listener, session)
if exit_code != 0 or exception:
config = session.config
restart = self._config_manager.record_crash(config.name, exit_code, exception)
Expand Down Expand Up @@ -519,12 +542,19 @@ def on_configs_changed(self, config_name: str | None = None) -> None:
sublime.set_timeout_async(lambda: self.restart_sessions_async(config_name))


class WindowRegistry(LspSettingsChangeListener):
class WindowRegistry(LspSettingsChangeListener, GlobalLspListener):
def __init__(self) -> None:
self._enabled = False
self._windows: dict[int, WindowManager] = {}
self._global_listeners: set[GlobalLspListener] = set()
client_configs.set_listener(self)

def add_global_listener(self, listener: GlobalLspListener) -> None:
self._global_listeners.add(listener)

def remove_global_listener(self, listener: GlobalLspListener) -> None:
self._global_listeners.discard(listener)

def enable(self) -> None:
self._enabled = True
# Initialize manually at plugin_loaded as we'll miss out on "on_new_window_async" events.
Expand All @@ -548,7 +578,7 @@ def lookup(self, window: sublime.Window | None) -> WindowManager | None:
return wm
workspace = ProjectFolders(window)
window_config_manager = WindowConfigManager(window, client_configs.all)
manager = WindowManager(window, workspace, window_config_manager)
manager = WindowManager(window, workspace, window_config_manager, self)
self._windows[window.id()] = manager
return manager

Expand Down Expand Up @@ -578,6 +608,16 @@ def on_client_config_updated(self, config_name: str | None = None) -> None:
def on_userprefs_updated(self) -> None:
sublime.set_timeout_async(self._on_userprefs_updated_async)

# --- Implements GlobalLspListener ---------------------------------------------------------------------------------

def on_session_view_initialized_async(self, view_listener: AbstractViewListener, session: Session) -> None:
for listener in self._global_listeners:
listener.on_session_view_initialized_async(view_listener, session)

def on_session_view_shutdown_async(self, view_listener: AbstractViewListener, session: Session) -> None:
for listener in self._global_listeners:
listener.on_session_view_shutdown_async(view_listener, session)


class RequestTimeTracker:
def __init__(self) -> None:
Expand Down
Loading