mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-12 22:14:54 +00:00
Vue: fix, ensure LS is operational before accepting requests
This commit is contained in:
1 parent
562bfeaa3b
commit
1558a4e3bc
1 file changed
+65
-23
@@ -156,6 +156,48 @@ class VueLanguageServer(SolidLanguageServer):
|
||||
self._ts_server_started = False
|
||||
self._vue_files_indexed = False
|
||||
self._indexed_vue_file_uris: list[str] = []
|
||||
self._ls_operational_ready_event = threading.Event()
|
||||
self._ls_operational_lock = threading.Lock()
|
||||
self._ls_operational_thread: threading.Thread | None = None
|
||||
|
||||
def _warm_up_ls_operational_state(self) -> None:
|
||||
"""Warm up the Vue language server operational state asynchronously."""
|
||||
# execute the operational warm-up
|
||||
try:
|
||||
self._ensure_ls_operational()
|
||||
except SolidLSPException:
|
||||
if not self.server_started:
|
||||
log.debug("Skipping Vue language server operational warm-up because the server is stopping")
|
||||
return
|
||||
log.exception("Error while warming up Vue language server operational state")
|
||||
except Exception:
|
||||
log.exception("Error while warming up Vue language server operational state")
|
||||
|
||||
def _ensure_ls_operational(self) -> None:
|
||||
# short-circuit completed warm-up
|
||||
if self._ls_operational_ready_event.is_set():
|
||||
return
|
||||
|
||||
# serialize the warm-up sequence
|
||||
with self._ls_operational_lock:
|
||||
# short-circuit repeated callers after waiting for the lock
|
||||
if self._ls_operational_ready_event.is_set():
|
||||
return
|
||||
|
||||
# validate server availability
|
||||
if not self.server_started:
|
||||
raise SolidLSPException("Language Server not started")
|
||||
|
||||
# wait for cross-file reference readiness
|
||||
if not self._has_waited_for_cross_file_references:
|
||||
sleep(self._get_wait_time_for_cross_file_referencing())
|
||||
self._has_waited_for_cross_file_references = True
|
||||
|
||||
# index Vue files on the companion TypeScript server
|
||||
self._ensure_vue_files_indexed_on_ts_server()
|
||||
|
||||
# publish operational readiness
|
||||
self._ls_operational_ready_event.set()
|
||||
|
||||
@override
|
||||
def is_ignored_dirname(self, dirname: str) -> bool:
|
||||
@@ -283,9 +325,7 @@ class VueLanguageServer(SolidLanguageServer):
|
||||
return result
|
||||
|
||||
def request_file_references(self, relative_file_path: str) -> list:
|
||||
if not self.server_started:
|
||||
log.error("request_file_references called before Language Server started")
|
||||
raise SolidLSPException("Language Server not started")
|
||||
self._ensure_ls_operational()
|
||||
|
||||
absolute_file_path = os.path.join(self.repository_root_path, relative_file_path)
|
||||
uri = PathUtils.path_to_uri(absolute_file_path)
|
||||
@@ -348,15 +388,7 @@ class VueLanguageServer(SolidLanguageServer):
|
||||
|
||||
@override
|
||||
def request_references(self, relative_file_path: str, line: int, column: int) -> list[ls_types.Location]:
|
||||
if not self.server_started:
|
||||
log.error("request_references called before Language Server started")
|
||||
raise SolidLSPException("Language Server not started")
|
||||
|
||||
if not self._has_waited_for_cross_file_references:
|
||||
sleep(self._get_wait_time_for_cross_file_referencing())
|
||||
self._has_waited_for_cross_file_references = True
|
||||
|
||||
self._ensure_vue_files_indexed_on_ts_server()
|
||||
self._ensure_ls_operational()
|
||||
symbol_refs = self._send_ts_references_request(relative_file_path, line=line, column=column)
|
||||
|
||||
if relative_file_path.endswith(".vue"):
|
||||
@@ -381,20 +413,14 @@ class VueLanguageServer(SolidLanguageServer):
|
||||
|
||||
@override
|
||||
def request_definition(self, relative_file_path: str, line: int, column: int) -> list[ls_types.Location]:
|
||||
if not self.server_started:
|
||||
log.error("request_definition called before Language Server started")
|
||||
raise SolidLSPException("Language Server not started")
|
||||
|
||||
self._ensure_ls_operational()
|
||||
assert self._ts_server is not None
|
||||
with self._ts_server.open_file(relative_file_path):
|
||||
return self._ts_server.request_definition(relative_file_path, line, column)
|
||||
|
||||
@override
|
||||
def request_rename_symbol_edit(self, relative_file_path: str, line: int, column: int, new_name: str) -> ls_types.WorkspaceEdit | None:
|
||||
if not self.server_started:
|
||||
log.error("request_rename_symbol_edit called before Language Server started")
|
||||
raise SolidLSPException("Language Server not started")
|
||||
|
||||
self._ensure_ls_operational()
|
||||
assert self._ts_server is not None
|
||||
with self._ts_server.open_file(relative_file_path):
|
||||
return self._ts_server.request_rename_symbol_edit(relative_file_path, line, column, new_name)
|
||||
@@ -698,6 +724,15 @@ class VueLanguageServer(SolidLanguageServer):
|
||||
else:
|
||||
log.info("Vue server initialization complete")
|
||||
|
||||
# kick off asynchronous operational warm-up
|
||||
self._ls_operational_ready_event.clear()
|
||||
self._ls_operational_thread = threading.Thread(
|
||||
target=self._warm_up_ls_operational_state,
|
||||
name="vue-ls-operational-warmup",
|
||||
daemon=True,
|
||||
)
|
||||
self._ls_operational_thread.start()
|
||||
|
||||
def _find_tsconfig_for_file(self, file_path: str) -> str | None:
|
||||
if not file_path:
|
||||
tsconfig_path = os.path.join(self.repository_root_path, "tsconfig.json")
|
||||
@@ -724,8 +759,14 @@ class VueLanguageServer(SolidLanguageServer):
|
||||
|
||||
@override
|
||||
def stop(self, shutdown_timeout: float = 5.0) -> None:
|
||||
self._cleanup_indexed_vue_files()
|
||||
self._stop_typescript_server()
|
||||
# serialize shutdown with operational warm-up
|
||||
with self._ls_operational_lock:
|
||||
self.server_started = False
|
||||
self._ls_operational_ready_event.clear()
|
||||
self._cleanup_indexed_vue_files()
|
||||
self._stop_typescript_server()
|
||||
self._ls_operational_thread = None
|
||||
|
||||
super().stop(shutdown_timeout)
|
||||
|
||||
@override
|
||||
@@ -760,8 +801,9 @@ class VueLanguageServer(SolidLanguageServer):
|
||||
|
||||
return self._filter_shorthand_property_duplicates(symbols)
|
||||
|
||||
@staticmethod
|
||||
def _filter_shorthand_property_duplicates(
|
||||
self, symbols: list[DocumentSymbol] | list[SymbolInformation]
|
||||
symbols: list[DocumentSymbol] | list[SymbolInformation],
|
||||
) -> list[DocumentSymbol] | list[SymbolInformation]:
|
||||
"""
|
||||
Filter out Property symbols that have a matching Variable symbol with the same name.
|
||||
|
||||
Reference in new issue
Block a user