From 6cb66985aa190a645ff5a221cee1331af4d77393 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Thu, 12 Mar 2026 00:04:08 -0500 Subject: [PATCH] refactor(lsp): replace controller layer with client module and LSPManager orchestration * Rename legacy controller subsystem (LSPController, websocket controller, controller events, and base classes) into clarified client module for LSP communication * Structure around LSPManager and LSPManagerClient to handle orchestration and client lifecycle * Update plugin integration to use LSPManager instead of LSPController * Simplify architecture by reducing controller indirection --- .../code/ui/lsp_manager/client/__init__.py | 3 ++ .../lsp_client.py} | 6 +-- .../lsp_client_base.py} | 4 +- .../lsp_client_events.py} | 2 +- .../lsp_client_websocket.py} | 4 +- .../websocket_client.py | 0 .../ui/lsp_manager/controllers/__init__.py | 3 -- .../{lsp_controller.py => lsp_manager.py} | 40 +++++++++---------- ...nt_controller.py => lsp_manager_client.py} | 12 +++--- plugins/code/ui/lsp_manager/plugin.py | 28 ++++++------- 10 files changed, 50 insertions(+), 52 deletions(-) create mode 100644 plugins/code/ui/lsp_manager/client/__init__.py rename plugins/code/ui/lsp_manager/{controllers/lsp_controller.py => client/lsp_client.py} (93%) rename plugins/code/ui/lsp_manager/{controllers/lsp_controller_base.py => client/lsp_client_base.py} (78%) rename plugins/code/ui/lsp_manager/{controllers/lsp_controller_events.py => client/lsp_client_events.py} (99%) rename plugins/code/ui/lsp_manager/{controllers/lsp_controller_websocket.py => client/lsp_client_websocket.py} (91%) rename plugins/code/ui/lsp_manager/{controllers => client}/websocket_client.py (100%) delete mode 100644 plugins/code/ui/lsp_manager/controllers/__init__.py rename plugins/code/ui/lsp_manager/{lsp_controller.py => lsp_manager.py} (60%) rename plugins/code/ui/lsp_manager/{lsp_client_controller.py => lsp_manager_client.py} (83%) diff --git a/plugins/code/ui/lsp_manager/client/__init__.py b/plugins/code/ui/lsp_manager/client/__init__.py new file mode 100644 index 0000000..8f09a89 --- /dev/null +++ b/plugins/code/ui/lsp_manager/client/__init__.py @@ -0,0 +1,3 @@ +""" + LSP Clients Module +""" \ No newline at end of file diff --git a/plugins/code/ui/lsp_manager/controllers/lsp_controller.py b/plugins/code/ui/lsp_manager/client/lsp_client.py similarity index 93% rename from plugins/code/ui/lsp_manager/controllers/lsp_controller.py rename to plugins/code/ui/lsp_manager/client/lsp_client.py index a5be028..d593807 100644 --- a/plugins/code/ui/lsp_manager/controllers/lsp_controller.py +++ b/plugins/code/ui/lsp_manager/client/lsp_client.py @@ -10,13 +10,13 @@ from gi.repository import GLib # Application imports from libs.dto.code.lsp.lsp_messages import get_message_str from libs.dto.code.lsp.lsp_message_structs import LSPResponseTypes, ClientRequest, ClientNotification -from .lsp_controller_websocket import LSPControllerWebsocket +from .lsp_client_websocket import LSPClientWebsocket -class LSPController(LSPControllerWebsocket): +class LSPClient(LSPClientWebsocket): def __init__(self): - super(LSPController, self).__init__() + super(LSPClient, self).__init__() # https://github.com/microsoft/multilspy/tree/main/src/multilspy/language_servers # initialize-params-slim.json was created off of jedi_language_server one diff --git a/plugins/code/ui/lsp_manager/controllers/lsp_controller_base.py b/plugins/code/ui/lsp_manager/client/lsp_client_base.py similarity index 78% rename from plugins/code/ui/lsp_manager/controllers/lsp_controller_base.py rename to plugins/code/ui/lsp_manager/client/lsp_client_base.py index 3a5c3ad..4305270 100644 --- a/plugins/code/ui/lsp_manager/controllers/lsp_controller_base.py +++ b/plugins/code/ui/lsp_manager/client/lsp_client_base.py @@ -3,12 +3,12 @@ # Lib imports # Application imports -from .lsp_controller_events import LSPControllerEvents +from .lsp_client_events import LSPClientEvents from libs.dto.code.lsp.lsp_message_structs import ClientRequest, ClientNotification -class LSPControllerBase(LSPControllerEvents): +class LSPClientBase(LSPClientEvents): def _send_message(self, data: ClientRequest or ClientNotification): raise NotImplementedError diff --git a/plugins/code/ui/lsp_manager/controllers/lsp_controller_events.py b/plugins/code/ui/lsp_manager/client/lsp_client_events.py similarity index 99% rename from plugins/code/ui/lsp_manager/controllers/lsp_controller_events.py rename to plugins/code/ui/lsp_manager/client/lsp_client_events.py index 5bc8a0f..10b91d2 100644 --- a/plugins/code/ui/lsp_manager/controllers/lsp_controller_events.py +++ b/plugins/code/ui/lsp_manager/client/lsp_client_events.py @@ -17,7 +17,7 @@ from libs.dto.code.lsp.lsp_messages import symbols_request -class LSPControllerEvents: +class LSPClientEvents: def send_initialize_message(self, init_ops: dict, workspace_file: str, workspace_uri: str): folder_name = os.path.basename(workspace_file) diff --git a/plugins/code/ui/lsp_manager/controllers/lsp_controller_websocket.py b/plugins/code/ui/lsp_manager/client/lsp_client_websocket.py similarity index 91% rename from plugins/code/ui/lsp_manager/controllers/lsp_controller_websocket.py rename to plugins/code/ui/lsp_manager/client/lsp_client_websocket.py index 4e2f256..46a31ff 100644 --- a/plugins/code/ui/lsp_manager/controllers/lsp_controller_websocket.py +++ b/plugins/code/ui/lsp_manager/client/lsp_client_websocket.py @@ -10,12 +10,12 @@ from libs.dto.code.lsp.lsp_message_structs import \ LSPResponseTypes, ClientRequest, ClientNotification, \ LSPResponseRequest, LSPResponseNotification, LSPIDResponseNotification -from .lsp_controller_base import LSPControllerBase +from .lsp_client_base import LSPClientBase from .websocket_client import WebsocketClient -class LSPControllerWebsocket(LSPControllerBase): +class LSPClientWebsocket(LSPClientBase): def _send_message(self, data: ClientRequest | ClientNotification): if not data: return diff --git a/plugins/code/ui/lsp_manager/controllers/websocket_client.py b/plugins/code/ui/lsp_manager/client/websocket_client.py similarity index 100% rename from plugins/code/ui/lsp_manager/controllers/websocket_client.py rename to plugins/code/ui/lsp_manager/client/websocket_client.py diff --git a/plugins/code/ui/lsp_manager/controllers/__init__.py b/plugins/code/ui/lsp_manager/controllers/__init__.py deleted file mode 100644 index a3fad54..0000000 --- a/plugins/code/ui/lsp_manager/controllers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" - Plugin Controller Module -""" \ No newline at end of file diff --git a/plugins/code/ui/lsp_manager/lsp_controller.py b/plugins/code/ui/lsp_manager/lsp_manager.py similarity index 60% rename from plugins/code/ui/lsp_manager/lsp_controller.py rename to plugins/code/ui/lsp_manager/lsp_manager.py index a854563..cd1160e 100644 --- a/plugins/code/ui/lsp_manager/lsp_controller.py +++ b/plugins/code/ui/lsp_manager/lsp_manager.py @@ -8,14 +8,14 @@ from libs.dto.code.lsp.lsp_message_structs import LSPResponseTypes, LSPResponseR from .provider import Provider from .provider_response_cache import ProviderResponseCache from .lsp_manager_ui import LSPManagerUI -from .lsp_client_controller import LSPClientController +from .lsp_manager_client import LSPManagerClient from .handlers.registry import HandlerRegistry -class LSPController: +class LSPManager: def __init__(self): - super(LSPController, self).__init__() + super(LSPManager, self).__init__() self._init() self._load_widgets() @@ -23,10 +23,10 @@ class LSPController: def _init(self): - self.provider: Provider = Provider() - self.response_cache: ProviderResponseCache = ProviderResponseCache() - self.lsp_client_controller: LSPClientController = LSPClientController() - self.handler_registry: HandlerRegistry = HandlerRegistry() + self.provider: Provider = Provider() + self.response_cache: ProviderResponseCache = ProviderResponseCache() + self.lsp_manager_client: LSPManagerClient = LSPManagerClient() + self.handler_registry: HandlerRegistry = HandlerRegistry() def _load_widgets(self): self.lsp_manager_ui: LSPManagerUI = LSPManagerUI() @@ -34,28 +34,27 @@ class LSPController: self.lsp_manager_ui.close_client = self.close_client def _do_bind_mapping(self): - self.response_cache.process_file_load = self.lsp_client_controller.process_file_load - self.response_cache.process_file_close = self.lsp_client_controller.process_file_close - self.response_cache.process_file_save = self.lsp_client_controller.process_file_save - self.response_cache.process_file_change = self.lsp_client_controller.process_file_change + self.response_cache.process_file_load = self.lsp_manager_client.process_file_load + self.response_cache.process_file_close = self.lsp_manager_client.process_file_close + self.response_cache.process_file_save = self.lsp_manager_client.process_file_save + self.response_cache.process_file_change = self.lsp_manager_client.process_file_change self.provider.response_cache = self.response_cache - def create_client( self, lang_id: str = "python", workspace_uri: str = "", init_opts: dict = {} ) -> bool: - client = self.lsp_client_controller.create_client( + client = self.lsp_manager_client.create_client( lang_id, workspace_uri, init_opts ) handler = self.handler_registry.get_handler(lang_id) - self.lsp_client_controller.active_language_id = lang_id + self.lsp_manager_client.active_language_id = lang_id if not client or not handler: - logger.error(f"LSP Controller: Either 'client' or 'handler' didn't get created...'") + logger.error(f"LSP Manager: Either 'client' or 'handler' didn't get created...'") self.close_client(lang_id) return False @@ -68,7 +67,7 @@ class LSPController: return True def close_client(self, lang_id: str) -> bool: - self.lsp_client_controller.close_client(lang_id) + self.lsp_manager_client.close_client(lang_id) self.handler_registry.close_handler(lang_id) return True @@ -77,14 +76,14 @@ class LSPController: logger.debug(f"LSP Response: { lsp_response }") if isinstance(lsp_response, LSPResponseRequest): - if not self.lsp_client_controller.active_language_id in self.lsp_client_controller.clients: - logger.debug(f"No LSP client for '{self.lsp_client_controller.active_language_id}', skipping 'server_response'") + if not self.lsp_manager_client.active_language_id in self.lsp_manager_client.clients: + logger.debug(f"No LSP client for '{self.lsp_manager_client.active_language_id}', skipping 'server_response'") return - controller = self.lsp_client_controller.get_active_client() + controller = self.lsp_manager_client.get_active_client() event = controller.get_event_by_id(lsp_response.id) handler = self.handler_registry.get_handler( - self.lsp_client_controller.active_language_id, event + self.lsp_manager_client.active_language_id, event ) if not handler: return @@ -94,7 +93,6 @@ class LSPController: if not handler: return - # TODO: Need to make default singleton so as to not need to set these here handler.set_context(self.handler_registry) handler.set_response_cache(self.response_cache) handler.handle(lsp_response.method, lsp_response.params, None) diff --git a/plugins/code/ui/lsp_manager/lsp_client_controller.py b/plugins/code/ui/lsp_manager/lsp_manager_client.py similarity index 83% rename from plugins/code/ui/lsp_manager/lsp_client_controller.py rename to plugins/code/ui/lsp_manager/lsp_manager_client.py index 87ed201..8e649dd 100644 --- a/plugins/code/ui/lsp_manager/lsp_client_controller.py +++ b/plugins/code/ui/lsp_manager/lsp_manager_client.py @@ -5,13 +5,13 @@ from concurrent.futures import ThreadPoolExecutor # Application imports from .mixins.lsp_client_events_mixin import LSPClientEventsMixin -from .controllers.lsp_controller import LSPController +from .client.lsp_client import LSPClient -class LSPClientController(LSPClientEventsMixin): +class LSPManagerClient(LSPClientEventsMixin): def __init__(self): - super(LSPClientController, self).__init__() + super(LSPManagerClient, self).__init__() self._cache_refresh_timeout_id: int = None @@ -25,13 +25,13 @@ class LSPClientController(LSPClientEventsMixin): lang_id: str = "python", workspace_uri: str = "", init_opts: dict = {} - ) -> LSPController: + ) -> LSPClient: if lang_id in self.clients: return None address = "127.0.0.1" port = 9999 uri = f"ws://{address}:{port}/{lang_id}" - client = LSPController() + client = LSPClient() client.set_language(lang_id) client.set_socket(uri) @@ -53,5 +53,5 @@ class LSPClientController(LSPClientEventsMixin): return True - def get_active_client(self) -> LSPController: + def get_active_client(self) -> LSPClient: return self.clients[self.active_language_id] diff --git a/plugins/code/ui/lsp_manager/plugin.py b/plugins/code/ui/lsp_manager/plugin.py index 2dd2d1d..5bbcfee 100644 --- a/plugins/code/ui/lsp_manager/plugin.py +++ b/plugins/code/ui/lsp_manager/plugin.py @@ -11,11 +11,11 @@ from libs.dto.states import SourceViewStates from plugins.plugin_types import PluginCode -from .lsp_controller import LSPController +from .lsp_manager import LSPManager -lsp_controller = LSPController() +lsp_manager = LSPManager() @@ -30,7 +30,7 @@ class Plugin(PluginCode): def load(self): window = self.request_ui_element("main-window") - lsp_controller.lsp_manager_ui.map_parent_resize_event(window) + lsp_manager.lsp_manager_ui.map_parent_resize_event(window) event = Event_Factory.create_event("register_command", command_name = "LSP Manager", @@ -43,7 +43,7 @@ class Plugin(PluginCode): event = Event_Factory.create_event( "register_provider", provider_name = "LSP Completer", - provider = lsp_controller.provider, + provider = lsp_manager.provider, language_ids = [] ) self.emit_to("completion", event) @@ -55,14 +55,14 @@ class Plugin(PluginCode): self.emit_to("source_views", event) source_view = event.response - lsp_controller.lsp_manager_ui.load_lsp_servers_config() - lsp_controller.lsp_manager_ui.set_source_view(source_view) - lsp_controller.lsp_manager_ui.load_lsp_servers_config_placeholders() + lsp_manager.lsp_manager_ui.load_lsp_servers_config() + lsp_manager.lsp_manager_ui.set_source_view(source_view) + lsp_manager.lsp_manager_ui.load_lsp_servers_config_placeholders() - lsp_controller.handler_registry.emit = self.emit - lsp_controller.handler_registry.emit_to = self.emit_to - lsp_controller.handler_registry._prompt_goto_request = self._prompt_goto_request - lsp_controller.handler_registry._prompt_completion_request = self._prompt_completion_request + lsp_manager.handler_registry.emit = self.emit + lsp_manager.handler_registry.emit_to = self.emit_to + lsp_manager.handler_registry._prompt_goto_request = self._prompt_goto_request + lsp_manager.handler_registry._prompt_completion_request = self._prompt_completion_request def run(self): ... @@ -98,7 +98,7 @@ class Plugin(PluginCode): event = Event_Factory.create_event( "request_completion", view = view, - provider = lsp_controller.provider + provider = lsp_manager.provider ) self.emit_to("completion", event) @@ -121,7 +121,7 @@ class Handler: column = iter.get_line_offset() if char_str == "g": - lsp_controller.lsp_client_controller.process_goto_definition( + lsp_manager.lsp_manager_client.process_goto_definition( file.ftype, file.fpath, line, column ) @@ -130,4 +130,4 @@ class Handler: if char_str == "i": return - lsp_controller.lsp_manager_ui.hide() if lsp_controller.lsp_manager_ui.is_visible() else lsp_controller.lsp_manager_ui.show() + lsp_manager.lsp_manager_ui.hide() if lsp_manager.lsp_manager_ui.is_visible() else lsp_manager.lsp_manager_ui.show()