From 0c4ab2111c11505d37b7329beb84e9931fdd4889 Mon Sep 17 00:00:00 2001 From: irreg Date: Sat, 21 Jun 2025 00:14:13 +0900 Subject: [PATCH] Fix to finalize even when exiting contextmanager by exception --- src/multilspy/language_server.py | 40 +++++++++++-------- .../clangd_language_server.py | 10 ++--- .../dart_language_server.py | 10 ++--- .../eclipse_jdtls/eclipse_jdtls.py | 10 ++--- src/multilspy/language_servers/gopls/gopls.py | 10 ++--- .../jedi_language_server/jedi_server.py | 10 ++--- .../kotlin_language_server.py | 17 ++++---- .../language_servers/omnisharp/omnisharp.py | 10 ++--- .../rust_analyzer/rust_analyzer.py | 10 ++--- .../language_servers/solargraph/solargraph.py | 10 ++--- .../typescript_language_server.py | 10 ++--- 11 files changed, 79 insertions(+), 68 deletions(-) diff --git a/src/multilspy/language_server.py b/src/multilspy/language_server.py index bd05b27..0eae418 100644 --- a/src/multilspy/language_server.py +++ b/src/multilspy/language_server.py @@ -105,6 +105,7 @@ def create(cls, config: MultilspyConfig, logger: MultilspyLogger, repository_roo from multilspy.language_servers.typescript_language_server.typescript_language_server import ( TypeScriptLanguageServer, ) + return TypeScriptLanguageServer(config, logger, repository_root_path) elif config.code_language == Language.GO: from multilspy.language_servers.gopls.gopls import Gopls @@ -194,8 +195,10 @@ async def start_server(self) -> AsyncIterator["LanguageServer"]: ``` """ self.server_started = True - yield self - self.server_started = False + try: + yield self + finally: + self.server_started = False # TODO: Add support for more LSP features @@ -221,8 +224,6 @@ def open_file(self, relative_file_path: str) -> Iterator[None]: assert self.open_file_buffers[uri].ref_count >= 1 self.open_file_buffers[uri].ref_count += 1 - yield - self.open_file_buffers[uri].ref_count -= 1 else: contents = FileUtils.read_file(self.logger, absolute_file_path) @@ -239,18 +240,20 @@ def open_file(self, relative_file_path: str) -> Iterator[None]: } } ) + try: yield + finally: self.open_file_buffers[uri].ref_count -= 1 - if self.open_file_buffers[uri].ref_count == 0: - self.server.notify.did_close_text_document( - { - LSPConstants.TEXT_DOCUMENT: { - LSPConstants.URI: uri, + if self.open_file_buffers[uri].ref_count == 0: + self.server.notify.did_close_text_document( + { + LSPConstants.TEXT_DOCUMENT: { + LSPConstants.URI: uri, + } } - } - ) - del self.open_file_buffers[uri] + ) + del self.open_file_buffers[uri] def insert_text_at_position( self, relative_file_path: str, line: int, column: int, text_to_be_inserted: str @@ -686,6 +689,7 @@ async def request_workspace_symbol(self, query: str) -> Union[List[multilspy_typ return ret + @ensure_all_methods_implemented(LanguageServer) class SyncLanguageServer: """ @@ -771,10 +775,14 @@ def start_server(self) -> Iterator["SyncLanguageServer"]: loop_thread.start() ctx = self.language_server.start_server() asyncio.run_coroutine_threadsafe(ctx.__aenter__(), loop=self.loop).result() - yield self - asyncio.run_coroutine_threadsafe(ctx.__aexit__(None, None, None), loop=self.loop).result() - self.loop.call_soon_threadsafe(self.loop.stop) - loop_thread.join() + try: + yield self + finally: + asyncio.run_coroutine_threadsafe( + ctx.__aexit__(None, None, None), loop=self.loop + ).result() + self.loop.call_soon_threadsafe(self.loop.stop) + loop_thread.join() def request_definition(self, file_path: str, line: int, column: int) -> List[multilspy_types.Location]: """ diff --git a/src/multilspy/language_servers/clangd_language_server/clangd_language_server.py b/src/multilspy/language_servers/clangd_language_server/clangd_language_server.py index a5e5326..55d9350 100644 --- a/src/multilspy/language_servers/clangd_language_server/clangd_language_server.py +++ b/src/multilspy/language_servers/clangd_language_server/clangd_language_server.py @@ -181,8 +181,8 @@ async def window_log_message(msg): # set ready flag self.server_ready.set() await self.server_ready.wait() - - yield self - - await self.server.shutdown() - await self.server.stop() + try: + yield self + finally: + await self.server.shutdown() + await self.server.stop() diff --git a/src/multilspy/language_servers/dart_language_server/dart_language_server.py b/src/multilspy/language_servers/dart_language_server/dart_language_server.py index b814306..4840ea3 100644 --- a/src/multilspy/language_servers/dart_language_server/dart_language_server.py +++ b/src/multilspy/language_servers/dart_language_server/dart_language_server.py @@ -139,8 +139,8 @@ async def window_log_message(msg): ) self.server.notify.initialized({}) - - yield self - - await self.server.shutdown() - await self.server.stop() + try: + yield self + finally: + await self.server.shutdown() + await self.server.stop() diff --git a/src/multilspy/language_servers/eclipse_jdtls/eclipse_jdtls.py b/src/multilspy/language_servers/eclipse_jdtls/eclipse_jdtls.py index ed4bfae..ae8ccae 100644 --- a/src/multilspy/language_servers/eclipse_jdtls/eclipse_jdtls.py +++ b/src/multilspy/language_servers/eclipse_jdtls/eclipse_jdtls.py @@ -398,8 +398,8 @@ async def do_nothing(params): # TODO: Add comments about why we wait here, and how this can be optimized await self.service_ready_event.wait() - - yield self - - await self.server.shutdown() - await self.server.stop() + try: + yield self + finally: + await self.server.shutdown() + await self.server.stop() diff --git a/src/multilspy/language_servers/gopls/gopls.py b/src/multilspy/language_servers/gopls/gopls.py index 40031db..0ef31b9 100644 --- a/src/multilspy/language_servers/gopls/gopls.py +++ b/src/multilspy/language_servers/gopls/gopls.py @@ -144,8 +144,8 @@ async def do_nothing(params): # gopls server is typically ready immediately after initialization self.server_ready.set() await self.server_ready.wait() - - yield self - - await self.server.shutdown() - await self.server.stop() + try: + yield self + finally: + await self.server.shutdown() + await self.server.stop() diff --git a/src/multilspy/language_servers/jedi_language_server/jedi_server.py b/src/multilspy/language_servers/jedi_language_server/jedi_server.py index d49ace2..76214c8 100644 --- a/src/multilspy/language_servers/jedi_language_server/jedi_server.py +++ b/src/multilspy/language_servers/jedi_language_server/jedi_server.py @@ -113,8 +113,8 @@ async def window_log_message(msg): } self.server.notify.initialized({}) - - yield self - - await self.server.shutdown() - await self.server.stop() + try: + yield self + finally: + await self.server.shutdown() + await self.server.stop() diff --git a/src/multilspy/language_servers/kotlin_language_server/kotlin_language_server.py b/src/multilspy/language_servers/kotlin_language_server/kotlin_language_server.py index 76bc1e8..2c6c117 100644 --- a/src/multilspy/language_servers/kotlin_language_server/kotlin_language_server.py +++ b/src/multilspy/language_servers/kotlin_language_server/kotlin_language_server.py @@ -223,12 +223,15 @@ async def window_log_message(msg): self.server.notify.initialized({}) self.completions_available.set() - - yield self - try: - await self.server.shutdown() - except Exception as e: - self.logger.log(f"Error during Kotlin server shutdown: {str(e)}", logging.WARNING) + yield self finally: - await self.server.stop() + try: + await self.server.shutdown() + except Exception as e: + self.logger.log( + f"Error during Kotlin server shutdown: {str(e)}", + logging.WARNING, + ) + finally: + await self.server.stop() diff --git a/src/multilspy/language_servers/omnisharp/omnisharp.py b/src/multilspy/language_servers/omnisharp/omnisharp.py index 0f295a0..617f937 100644 --- a/src/multilspy/language_servers/omnisharp/omnisharp.py +++ b/src/multilspy/language_servers/omnisharp/omnisharp.py @@ -396,8 +396,8 @@ async def workspace_configuration_handler(params): await self.definition_available.wait() await self.references_available.wait() - - yield self - - await self.server.shutdown() - await self.server.stop() + try: + yield self + finally: + await self.server.shutdown() + await self.server.stop() diff --git a/src/multilspy/language_servers/rust_analyzer/rust_analyzer.py b/src/multilspy/language_servers/rust_analyzer/rust_analyzer.py index 1a95eec..bcd598d 100644 --- a/src/multilspy/language_servers/rust_analyzer/rust_analyzer.py +++ b/src/multilspy/language_servers/rust_analyzer/rust_analyzer.py @@ -175,8 +175,8 @@ async def window_log_message(msg): self.completions_available.set() await self.server_ready.wait() - - yield self - - await self.server.shutdown() - await self.server.stop() + try: + yield self + finally: + await self.server.shutdown() + await self.server.stop() diff --git a/src/multilspy/language_servers/solargraph/solargraph.py b/src/multilspy/language_servers/solargraph/solargraph.py index 8326779..7c0a0d8 100644 --- a/src/multilspy/language_servers/solargraph/solargraph.py +++ b/src/multilspy/language_servers/solargraph/solargraph.py @@ -181,8 +181,8 @@ async def window_log_message(msg): self.server_ready.set() await self.server_ready.wait() - - yield self - - await self.server.shutdown() - await self.server.stop() + try: + yield self + finally: + await self.server.shutdown() + await self.server.stop() diff --git a/src/multilspy/language_servers/typescript_language_server/typescript_language_server.py b/src/multilspy/language_servers/typescript_language_server/typescript_language_server.py index fde7d3b..86a9a64 100644 --- a/src/multilspy/language_servers/typescript_language_server/typescript_language_server.py +++ b/src/multilspy/language_servers/typescript_language_server/typescript_language_server.py @@ -195,8 +195,8 @@ async def window_log_message(msg): # TypeScript server is typically ready immediately after initialization self.server_ready.set() await self.server_ready.wait() - - yield self - - await self.server.shutdown() - await self.server.stop() + try: + yield self + finally: + await self.server.shutdown() + await self.server.stop()