Merge pull request #982 from oraios/ls-completions-event

Remove event completions_available and other superfluous events
This commit is contained in:
Dominik Jain authored and GitHub committed 2026-02-01 22:58:59 +01:00
commit 764f26f28f
40 files changed
+14 -107

No files matched your search

@@ -148,7 +148,6 @@ class BashLanguageServer(SolidLanguageServer):
if "Analyzing" in message_text or "analysis complete" in message_text.lower():
log.info("Bash language server analysis signals detected")
self.server_ready.set()
self.completions_available.set()
self.server.on_request("client/registerCapability", register_capability_handler)
self.server.on_notification("window/logMessage", window_log_message)
@@ -183,7 +182,6 @@ class BashLanguageServer(SolidLanguageServer):
# This is common. bash-language-server doesn't always send explicit ready signals. Log as info
log.info("Timeout waiting for bash server ready signal, proceeding anyway")
self.server_ready.set()
self.completions_available.set()
else:
log.info("Bash server initialization complete")
@@ -156,5 +156,4 @@ class CclsLanguageServer(SolidLanguageServer):
self.server.notify.initialized({})
# Basic readiness
self.completions_available.set()
self.server_ready.set()
@@ -214,7 +214,9 @@ class ClangdLanguageServer(SolidLanguageServer):
self.server.notify.initialized({})
self.completions_available.set()
# set ready flag
# TODO This defeats the purpose of the event; we should wait for the server to actually be ready
self.server_ready.set()
# wait for server to be ready
self.server_ready.wait()
@@ -214,4 +214,3 @@ class ClojureLSP(SolidLanguageServer):
self.server.notify.initialized({})
# after initialize, Clojure-lsp is ready to serve
self.server_ready.set()
self.completions_available.set()
@@ -213,8 +213,6 @@ class CSharpLanguageServer(SolidLanguageServer):
"""
super().__init__(config, repository_root_path, None, "csharp", solidlsp_settings)
self.initialization_complete = threading.Event()
def _create_dependency_provider(self) -> LanguageServerDependencyProvider:
return self.DependencyProvider(self._custom_settings, self._ls_resources_dir, self._solidlsp_settings, self.repository_root_path)
@@ -538,6 +536,8 @@ class CSharpLanguageServer(SolidLanguageServer):
)
def _start_server(self) -> None:
indexing_complete = threading.Event()
def do_nothing(params: dict) -> None:
return
@@ -645,7 +645,7 @@ class CSharpLanguageServer(SolidLanguageServer):
return
def handle_workspace_indexing_complete(params: dict) -> None:
self.completions_available.set()
indexing_complete.set()
# Set up notification handlers
self.server.on_notification("window/logMessage", window_log_message)
@@ -699,19 +699,16 @@ class CSharpLanguageServer(SolidLanguageServer):
# Open solution and project files
self._open_solution_and_projects()
self.initialization_complete.set()
log.info(
"Microsoft.CodeAnalysis.LanguageServer initialized and ready\n"
"Waiting for language server to index project files...\n"
"This may take a while for large projects"
)
if self.completions_available.wait(30): # Wait up to 30 seconds for indexing
if indexing_complete.wait(30): # Wait up to 30 seconds for indexing
log.info("Indexing complete")
else:
log.warning("Timeout waiting for indexing to complete, proceeding anyway")
self.completions_available.set()
def _force_pull_diagnostics(self, init_response: dict | InitializeResult) -> None:
"""
@@ -739,7 +739,6 @@ class EclipseJDTLS(SolidLanguageServer):
"*",
" ",
]
self.completions_available.set()
if registration["method"] == "workspace/executeCommand":
if "java.intellicode.enable" in registration["registerOptions"]["commands"]:
self._intellicode_enable_command_available.set()
@@ -328,7 +328,6 @@ class ElixirTools(SolidLanguageServer):
assert "textDocumentSync" in init_response["capabilities"], f"Missing textDocumentSync in {init_response['capabilities']}"
self.server.notify.initialized({})
self.completions_available.set()
# Expert needs time to compile the project and build indexes on first run.
# This can take 2-3+ minutes for mid-sized codebases.
@@ -50,7 +50,6 @@ class ElmLanguageServer(SolidLanguageServer):
"elm",
solidlsp_settings,
)
self.server_ready = threading.Event()
@override
def is_ignored_dirname(self, dirname: str) -> bool:
@@ -196,8 +195,6 @@ class ElmLanguageServer(SolidLanguageServer):
else:
log.warning("Timeout waiting for Elm workspace scan, proceeding anyway")
self.server_ready.set()
self.completions_available.set()
log.info("Elm server ready")
@override
@@ -155,7 +155,6 @@ class ErlangLanguageServer(SolidLanguageServer):
log.info(f"Erlang LS capabilities: {list(init_response['capabilities'].keys())}")
self.server.notify.initialized({})
self.completions_available.set()
# Wait for Erlang LS to be ready - adjust timeout based on environment
is_ci = os.getenv("CI") == "true" or os.getenv("GITHUB_ACTIONS") == "true"
@@ -7,7 +7,6 @@ import os
import pathlib
import re
import shutil
import threading
from overrides import override
@@ -190,7 +189,6 @@ class FortranLanguageServer(SolidLanguageServer):
super().__init__(
config, repository_root_path, ProcessLaunchInfo(cmd=fortls_cmd, cwd=repository_root_path), "fortran", solidlsp_settings
)
self.server_ready = threading.Event()
@staticmethod
def _get_initialize_params(repository_absolute_path: str) -> InitializeParams:
@@ -283,8 +281,6 @@ class FortranLanguageServer(SolidLanguageServer):
log.info("Fortran LSP document symbol provider available")
self.server.notify.initialized({})
self.completions_available.set()
# Fortran Language Server is ready after initialization
self.server_ready.set()
log.info("Fortran Language Server initialization complete")
+1 -5
View File
@@ -2,7 +2,6 @@ import logging
import os
import pathlib
import subprocess
import threading
from typing import Any, cast
from overrides import override
@@ -95,7 +94,6 @@ class Gopls(SolidLanguageServer):
self._setup_runtime_dependency()
super().__init__(config, repository_root_path, ProcessLaunchInfo(cmd="gopls", cwd=repository_root_path), "go", solidlsp_settings)
self.server_ready = threading.Event()
self.request_id = 0
def _get_initialize_params(self, repository_absolute_path: str) -> InitializeParams:
@@ -234,8 +232,6 @@ class Gopls(SolidLanguageServer):
assert "definitionProvider" in init_response["capabilities"]
self.server.notify.initialized({})
self.completions_available.set()
# gopls server is typically ready immediately after initialization
self.server_ready.set()
self.server_ready.wait()
# (no need to wait for events)
@@ -271,4 +271,3 @@ class GroovyLanguageServer(SolidLanguageServer):
assert "workspaceSymbolProvider" in capabilities, "Server must support workspace symbols"
self.server.notify.initialized({})
self.completions_available.set()
@@ -374,7 +374,6 @@ class HaskellLanguageServer(SolidLanguageServer):
log.info(f"HLS capabilities: {list(capabilities.keys())}")
self.server.notify.initialized({})
self.completions_available.set()
# Give HLS time to index the project
# HLS can be slow to index, especially on first run
@@ -172,7 +172,6 @@ class Intelephense(SolidLanguageServer):
assert "definitionProvider" in init_response["capabilities"]
self.server.notify.initialized({})
self.completions_available.set()
# Intelephense server is typically ready immediately after initialization
# TODO: This is probably incorrect; the server does send an initialized notification, which we could wait for!
+3 -1
View File
@@ -5,6 +5,7 @@ Provides Python specific instantiation of the LanguageServer class. Contains var
import logging
import os
import pathlib
import threading
from typing import cast
from overrides import override
@@ -155,6 +156,7 @@ class JediServer(SolidLanguageServer):
"""
Starts the JEDI Language Server
"""
completions_available = threading.Event()
def execute_client_command_handler(params: dict) -> list:
return []
@@ -164,7 +166,7 @@ class JediServer(SolidLanguageServer):
def check_experimental_status(params: dict) -> None:
if params["quiescent"] == True:
self.completions_available.set()
completions_available.set()
def window_log_message(msg: dict) -> None:
log.info(f"LSP: window/logMessage: {msg}")
@@ -166,5 +166,4 @@ class JuliaLanguageServer(SolidLanguageServer):
assert "documentSymbolProvider" in init_response["capabilities"]
self.server.notify.initialized({})
self.completions_available.set()
log.info("Julia Language Server is initialized and ready.")
@@ -485,4 +485,3 @@ class KotlinLanguageServer(SolidLanguageServer):
assert "semanticTokensProvider" in capabilities, "Server must support semantic tokens"
self.server.notify.initialized({})
self.completions_available.set()
+1 -5
View File
@@ -8,7 +8,6 @@ import pathlib
import platform
import shutil
import tarfile
import threading
import zipfile
from pathlib import Path
@@ -161,7 +160,6 @@ class LuaLanguageServer(SolidLanguageServer):
super().__init__(
config, repository_root_path, ProcessLaunchInfo(cmd=lua_ls_path, cwd=repository_root_path), "lua", solidlsp_settings
)
self.server_ready = threading.Event()
self.request_id = 0
@staticmethod
@@ -281,8 +279,6 @@ class LuaLanguageServer(SolidLanguageServer):
assert "referencesProvider" in init_response["capabilities"]
self.server.notify.initialized({})
self.completions_available.set()
# Lua Language Server is typically ready immediately after initialization
self.server_ready.set()
self.server_ready.wait()
# (no need to wait for events)
@@ -6,7 +6,6 @@ Contains various configurations and settings specific to Markdown.
import logging
import os
import pathlib
import threading
from overrides import override
@@ -99,7 +98,6 @@ class Marksman(SolidLanguageServer):
"markdown",
solidlsp_settings,
)
self.server_ready = threading.Event()
@override
def is_ignored_dirname(self, dirname: str) -> bool:
@@ -181,5 +179,3 @@ class Marksman(SolidLanguageServer):
# marksman is typically ready immediately after initialization
log.info("Marksman server initialization complete")
self.server_ready.set()
self.completions_available.set()
@@ -463,7 +463,6 @@ class MatlabLanguageServer(SolidLanguageServer):
if "mvm attach success" in message_text.lower() or "adding workspace folder" in message_text.lower():
log.info("MATLAB language server ready signal detected (MVM attached)")
self.server_ready.set()
self.completions_available.set()
self.server.on_request("client/registerCapability", register_capability_handler)
self.server.on_notification("window/logMessage", window_log_message)
@@ -508,7 +507,6 @@ class MatlabLanguageServer(SolidLanguageServer):
# Fallback: assume server is ready after timeout
log.info("Timeout waiting for MATLAB server ready signal, proceeding anyway")
self.server_ready.set()
self.completions_available.set()
else:
log.info("MATLAB server initialization complete")
-5
View File
@@ -11,7 +11,6 @@ import pathlib
import platform
import shutil
import subprocess
import threading
from pathlib import Path
from overrides import override
@@ -249,7 +248,6 @@ class NixLanguageServer(SolidLanguageServer):
nixd_path = self._setup_runtime_dependency()
super().__init__(config, repository_root_path, ProcessLaunchInfo(cmd=nixd_path, cwd=repository_root_path), "nix", solidlsp_settings)
self.server_ready = threading.Event()
self.request_id = 0
@staticmethod
@@ -374,8 +372,5 @@ class NixLanguageServer(SolidLanguageServer):
assert "referencesProvider" in init_response["capabilities"]
self.server.notify.initialized({})
self.completions_available.set()
# nixd server is typically ready immediately after initialization
self.server_ready.set()
self.server_ready.wait()
@@ -108,6 +108,7 @@ class OmniSharp(SolidLanguageServer):
self.server_ready = threading.Event()
self.definition_available = threading.Event()
self.references_available = threading.Event()
self.completions_available = threading.Event()
@override
def is_ignored_dirname(self, dirname: str) -> bool:
@@ -141,7 +141,6 @@ class PascalLanguageServer(SolidLanguageServer):
solidlsp_settings,
)
self.server_ready = threading.Event()
self.completions_available_event = threading.Event()
# ============== Metadata Directory Management ==============
@@ -859,7 +858,6 @@ class PascalLanguageServer(SolidLanguageServer):
if "initialized" in message_text.lower() or "ready" in message_text.lower():
log.info("Pascal language server ready signal detected")
self.server_ready.set()
self.completions_available.set()
def publish_diagnostics(params: dict) -> None:
log.debug(f"Diagnostics: {params}")
@@ -904,7 +902,6 @@ class PascalLanguageServer(SolidLanguageServer):
# pasls may not send explicit ready signals, so we proceed after timeout
log.info("Timeout waiting for Pascal server ready signal, assuming server is ready")
self.server_ready.set()
self.completions_available.set()
else:
log.info("Pascal server initialization complete")
@@ -206,8 +206,6 @@ class PerlLanguageServer(SolidLanguageServer):
log.info(f"Sending workspace/didChangeConfiguration notification with config: {perl_config}")
self.server.notify.workspace_did_change_configuration(perl_config)
self.completions_available.set()
# Perl::LanguageServer needs time to index files and resolve cross-file references
# Without this delay, requests for definitions/references may return empty results
settling_time = 0.5
@@ -287,7 +287,6 @@ class PowerShellLanguageServer(SolidLanguageServer):
if "started" in message_text.lower() or "ready" in message_text.lower():
log.info("PowerShell Editor Services ready signal detected")
self.server_ready.set()
self.completions_available.set()
def do_nothing(params: dict) -> None:
return
@@ -320,6 +319,5 @@ class PowerShellLanguageServer(SolidLanguageServer):
# Fallback: assume server is ready after timeout
log.info("Timeout waiting for PSES ready signal, proceeding anyway")
self.server_ready.set()
self.completions_available.set()
else:
log.info("PowerShell Editor Services initialization complete")
@@ -154,7 +154,6 @@ class PyrightServer(SolidLanguageServer):
log.info("Pyright workspace scanning complete")
self.found_source_files = True
self.analysis_complete.set()
self.completions_available.set()
def check_experimental_status(params: dict) -> None:
"""
@@ -164,7 +163,6 @@ class PyrightServer(SolidLanguageServer):
log.info("Received experimental/serverStatus with quiescent=true")
if not self.found_source_files:
self.analysis_complete.set()
self.completions_available.set()
# Set up notification handlers
self.server.on_request("client/registerCapability", do_nothing)
@@ -203,4 +201,3 @@ class PyrightServer(SolidLanguageServer):
log.warning("Timeout waiting for Pyright analysis completion, proceeding anyway")
# Fallback: assume analysis is complete after timeout
self.analysis_complete.set()
self.completions_available.set()
@@ -2,7 +2,6 @@ import logging
import os
import pathlib
import subprocess
import threading
from typing import Any
from overrides import override
@@ -68,7 +67,6 @@ class RLanguageServer(SolidLanguageServer):
r_cmd = 'R --vanilla --quiet --slave -e "options(languageserver.debug_mode = FALSE); languageserver::run()"'
super().__init__(config, repository_root_path, ProcessLaunchInfo(cmd=r_cmd, cwd=repository_root_path), "r", solidlsp_settings)
self.server_ready = threading.Event()
@staticmethod
def _get_initialize_params(repository_absolute_path: str) -> InitializeParams:
@@ -158,7 +156,5 @@ class RLanguageServer(SolidLanguageServer):
log.info("R LSP definition provider available")
self.server.notify.initialized({})
self.completions_available.set()
# R Language Server is ready after initialization
self.server_ready.set()
@@ -3,7 +3,6 @@
import logging
import os
import shutil
import threading
from overrides import override
@@ -53,7 +52,6 @@ class RegalLanguageServer(SolidLanguageServer):
"rego",
solidlsp_settings,
)
self.server_ready = threading.Event()
@staticmethod
def _get_initialize_params(repository_absolute_path: str) -> InitializeParams:
@@ -129,8 +127,5 @@ class RegalLanguageServer(SolidLanguageServer):
assert "textDocumentSync" in init_response["capabilities"]
self.server.notify.initialized({})
self.completions_available.set()
# Regal server is ready immediately after initialization
self.server_ready.set()
self.server_ready.wait()
@@ -350,7 +350,6 @@ class RubyLsp(SolidLanguageServer):
if params.get("type") == "ready":
log.info("ruby-lsp service is ready.")
self.analysis_complete.set()
self.completions_available.set()
def execute_client_command_handler(params: dict) -> list:
return []
@@ -370,7 +369,6 @@ class RubyLsp(SolidLanguageServer):
if value.get("kind") == "end":
log.info("ruby-lsp indexing complete ($/progress end)")
self.analysis_complete.set()
self.completions_available.set()
elif value.get("kind") == "begin":
log.info("ruby-lsp indexing started ($/progress begin)")
elif "percentage" in value:
@@ -384,7 +382,6 @@ class RubyLsp(SolidLanguageServer):
if value.get("kind") == "end" or value.get("percentage") == 100:
log.info("ruby-lsp indexing complete (token progress)")
self.analysis_complete.set()
self.completions_available.set()
def window_work_done_progress_create(params: dict) -> dict:
"""Handle workDoneProgress/create requests from ruby-lsp"""
@@ -429,7 +426,6 @@ class RubyLsp(SolidLanguageServer):
log.warning("Timeout waiting for ruby-lsp indexing completion, proceeding anyway")
# Fallback: assume indexing is complete after timeout
self.analysis_complete.set()
self.completions_available.set()
def _handle_initialization_response(self, init_response: InitializeResult) -> None:
"""
@@ -721,6 +721,5 @@ class RustAnalyzer(SolidLanguageServer):
"completionItem": {"labelDetailsSupport": True},
}
self.server.notify.initialized({})
self.completions_available.set()
self.server_ready.wait()
@@ -320,7 +320,6 @@ class Solargraph(SolidLanguageServer):
if params.get("type") == "ServiceReady" and params.get("message") == "Service is ready.":
log.info("Solargraph service is ready.")
self.analysis_complete.set()
self.completions_available.set()
def execute_client_command_handler(params: dict) -> list:
return []
@@ -364,4 +363,3 @@ class Solargraph(SolidLanguageServer):
log.warning("Timeout waiting for Solargraph analysis completion, proceeding anyway")
# Fallback: assume analysis is complete after timeout
self.analysis_complete.set()
self.completions_available.set()
@@ -2,7 +2,6 @@ import logging
import os
import pathlib
import subprocess
import threading
import time
from overrides import override
@@ -53,7 +52,6 @@ class SourceKitLSP(SolidLanguageServer):
super().__init__(
config, repository_root_path, ProcessLaunchInfo(cmd="sourcekit-lsp", cwd=repository_root_path), "swift", solidlsp_settings
)
self.server_ready = threading.Event()
self.request_id = 0
self._did_sleep_before_requesting_references = False
self._initialization_timestamp: float | None = None
@@ -332,10 +330,6 @@ class SourceKitLSP(SolidLanguageServer):
assert "definitionProvider" in capabilities, "definitionProvider capability missing"
self.server.notify.initialized({})
self.completions_available.set()
self.server_ready.set()
self.server_ready.wait()
# Mark initialization timestamp for smarter delay calculation
self._initialization_timestamp = time.time()
@@ -11,7 +11,6 @@ import platform
import shutil
import socket
import stat
import threading
import urllib.request
from typing import Any
@@ -128,7 +127,6 @@ class TaploServer(SolidLanguageServer):
"toml",
solidlsp_settings,
)
self.server_ready = threading.Event()
@classmethod
def _setup_runtime_dependencies(cls, solidlsp_settings: SolidLSPSettings) -> str:
@@ -308,8 +306,6 @@ class TaploServer(SolidLanguageServer):
self.server.notify.initialized({})
log.info("Taplo server initialization complete")
self.server_ready.set()
self.completions_available.set()
def is_ignored_dirname(self, dirname: str) -> bool:
"""Define TOML-specific directories to ignore."""
@@ -1,7 +1,6 @@
import logging
import os
import shutil
import threading
from typing import cast
from overrides import override
@@ -166,7 +165,6 @@ class TerraformLS(SolidLanguageServer):
"terraform",
solidlsp_settings,
)
self.server_ready = threading.Event()
self.request_id = 0
@staticmethod
@@ -232,8 +230,5 @@ class TerraformLS(SolidLanguageServer):
assert "definitionProvider" in init_response["capabilities"]
self.server.notify.initialized({})
self.completions_available.set()
# terraform-ls server is typically ready immediately after initialization
self.server_ready.set()
self.server_ready.wait()
@@ -269,7 +269,6 @@ class TypeScriptLanguageServer(SolidLanguageServer):
"""
if params.get("quiescent") == True:
self.server_ready.set()
self.completions_available.set()
self.server.on_request("client/registerCapability", register_capability_handler)
self.server.on_notification("window/logMessage", window_log_message)
@@ -302,7 +301,6 @@ class TypeScriptLanguageServer(SolidLanguageServer):
log.info("Timeout waiting for TypeScript server to become ready, proceeding anyway")
# Fallback: assume server is ready after timeout
self.server_ready.set()
self.completions_available.set()
@override
def _get_wait_time_for_cross_file_referencing(self) -> float:
@@ -186,7 +186,6 @@ class VtsLanguageServer(SolidLanguageServer):
"""
if params.get("quiescent") is True:
self.server_ready.set()
self.completions_available.set()
self.server.on_request("client/registerCapability", register_capability_handler)
self.server.on_notification("window/logMessage", window_log_message)
@@ -222,7 +221,6 @@ class VtsLanguageServer(SolidLanguageServer):
log.info("Timeout waiting for VTS server to become ready, proceeding anyway")
# Fallback: assume server is ready after timeout
self.server_ready.set()
self.completions_available.set()
@override
def _get_wait_time_for_cross_file_referencing(self) -> float:
@@ -633,7 +633,6 @@ class VueLanguageServer(SolidLanguageServer):
if "initialized" in message_text.lower() or "ready" in message_text.lower():
log.info("Vue language server ready signal detected")
self.server_ready.set()
self.completions_available.set()
def tsserver_request_notification_handler(params: list) -> None:
try:
@@ -683,7 +682,6 @@ class VueLanguageServer(SolidLanguageServer):
if not self.server_ready.wait(timeout=self.VUE_SERVER_READY_TIMEOUT):
log.info("Timeout waiting for Vue server ready signal, proceeding anyway")
self.server_ready.set()
self.completions_available.set()
else:
log.info("Vue server initialization complete")
@@ -7,7 +7,6 @@ import logging
import os
import pathlib
import shutil
import threading
from typing import Any
from solidlsp.language_servers.common import RuntimeDependency, RuntimeDependencyCollection
@@ -55,7 +54,6 @@ class YamlLanguageServer(SolidLanguageServer):
"yaml",
solidlsp_settings,
)
self.server_ready = threading.Event()
@classmethod
def _setup_runtime_dependencies(cls, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings) -> str:
@@ -184,5 +182,3 @@ class YamlLanguageServer(SolidLanguageServer):
# YAML language server is ready immediately after initialization
log.info("YAML server initialization complete")
self.server_ready.set()
self.completions_available.set()
+1 -5
View File
@@ -8,7 +8,6 @@ import pathlib
import platform
import shutil
import subprocess
import threading
from overrides import override
@@ -100,7 +99,6 @@ class ZigLanguageServer(SolidLanguageServer):
self._setup_runtime_dependency()
super().__init__(config, repository_root_path, ProcessLaunchInfo(cmd="zls", cwd=repository_root_path), "zig", solidlsp_settings)
self.server_ready = threading.Event()
self.request_id = 0
@staticmethod
@@ -213,11 +211,9 @@ class ZigLanguageServer(SolidLanguageServer):
assert "referencesProvider" in init_response["capabilities"]
self.server.notify.initialized({})
self.completions_available.set()
# ZLS server is ready after initialization
self.server_ready.set()
self.server_ready.wait()
# (no need to wait for an event)
# Open build.zig if it exists to help ZLS understand project structure
build_zig_path = os.path.join(self.repository_root_path, "build.zig")
-2
View File
@@ -409,7 +409,6 @@ class SolidLanguageServer(ABC):
self._load_document_symbols_cache()
self.server_started = False
self.completions_available = threading.Event()
if config.trace_lsp_communication:
def logging_fn(source: str, target: str, msg: StringDict | str) -> None:
@@ -1005,7 +1004,6 @@ class SolidLanguageServer(ABC):
num_retries = 0
while response is None or (response["isIncomplete"] and num_retries < 30): # type: ignore
self.completions_available.wait()
response = self.server.send.completion(completion_params)
if isinstance(response, list):
response = {"items": response, "isIncomplete": False}