diff --git a/src/solidlsp/language_servers/clangd_language_server.py b/src/solidlsp/language_servers/clangd_language_server.py index eccd6017..192ef199 100644 --- a/src/solidlsp/language_servers/clangd_language_server.py +++ b/src/solidlsp/language_servers/clangd_language_server.py @@ -8,10 +8,9 @@ import pathlib import threading from typing import Any, cast -from solidlsp.ls import SolidLanguageServer +from solidlsp.ls import LanguageServerDependencyProvider, LanguageServerDependencyProviderSinglePath, SolidLanguageServer from solidlsp.ls_config import LanguageServerConfig from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams -from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo from solidlsp.settings import SolidLSPSettings from .common import RuntimeDependency, RuntimeDependencyCollection @@ -30,92 +29,95 @@ class ClangdLanguageServer(SolidLanguageServer): """ Creates a ClangdLanguageServer instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - clangd_executable_path = self._setup_runtime_dependencies(config, solidlsp_settings) - super().__init__( - config, repository_root_path, ProcessLaunchInfo(cmd=clangd_executable_path, cwd=repository_root_path), "cpp", solidlsp_settings - ) + super().__init__(config, repository_root_path, None, "cpp", solidlsp_settings) self.server_ready = threading.Event() self.service_ready_event = threading.Event() self.initialize_searcher_command_available = threading.Event() self.resolve_main_method_available = threading.Event() - @classmethod - def _setup_runtime_dependencies(cls, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings) -> str: - """ - Setup runtime dependencies for ClangdLanguageServer and return the command to start the server. - """ - import shutil + def _create_dependency_provider(self) -> LanguageServerDependencyProvider: + return self.DependencyProvider(self._custom_settings, self._ls_resources_dir) - deps = RuntimeDependencyCollection( - [ - RuntimeDependency( - id="Clangd", - description="Clangd for Linux (x64)", - url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-linux-19.1.2.zip", - platform_id="linux-x64", - archive_type="zip", - binary_name="clangd_19.1.2/bin/clangd", - ), - RuntimeDependency( - id="Clangd", - description="Clangd for Windows (x64)", - url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-windows-19.1.2.zip", - platform_id="win-x64", - archive_type="zip", - binary_name="clangd_19.1.2/bin/clangd.exe", - ), - RuntimeDependency( - id="Clangd", - description="Clangd for macOS (x64)", - url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-mac-19.1.2.zip", - platform_id="osx-x64", - archive_type="zip", - binary_name="clangd_19.1.2/bin/clangd", - ), - RuntimeDependency( - id="Clangd", - description="Clangd for macOS (Arm64)", - url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-mac-19.1.2.zip", - platform_id="osx-arm64", - archive_type="zip", - binary_name="clangd_19.1.2/bin/clangd", - ), - ] - ) + class DependencyProvider(LanguageServerDependencyProviderSinglePath): + def _get_or_install_core_dependency(self) -> str: + """ + Setup runtime dependencies for ClangdLanguageServer and return the path to the executable. + """ + import shutil - clangd_ls_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "clangd") + deps = RuntimeDependencyCollection( + [ + RuntimeDependency( + id="Clangd", + description="Clangd for Linux (x64)", + url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-linux-19.1.2.zip", + platform_id="linux-x64", + archive_type="zip", + binary_name="clangd_19.1.2/bin/clangd", + ), + RuntimeDependency( + id="Clangd", + description="Clangd for Windows (x64)", + url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-windows-19.1.2.zip", + platform_id="win-x64", + archive_type="zip", + binary_name="clangd_19.1.2/bin/clangd.exe", + ), + RuntimeDependency( + id="Clangd", + description="Clangd for macOS (x64)", + url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-mac-19.1.2.zip", + platform_id="osx-x64", + archive_type="zip", + binary_name="clangd_19.1.2/bin/clangd", + ), + RuntimeDependency( + id="Clangd", + description="Clangd for macOS (Arm64)", + url="https://github.com/clangd/clangd/releases/download/19.1.2/clangd-mac-19.1.2.zip", + platform_id="osx-arm64", + archive_type="zip", + binary_name="clangd_19.1.2/bin/clangd", + ), + ] + ) - try: - dep = deps.get_single_dep_for_current_platform() - except RuntimeError: - dep = None + clangd_ls_dir = os.path.join(self._ls_resources_dir, "clangd") - if dep is None: - # No prebuilt binary available, look for system-installed clangd - clangd_executable_path = shutil.which("clangd") - if not clangd_executable_path: - raise FileNotFoundError( - "Clangd is not installed on your system.\n" - + "Please install clangd using your system package manager:\n" - + " Ubuntu/Debian: sudo apt-get install clangd\n" - + " Fedora/RHEL: sudo dnf install clang-tools-extra\n" - + " Arch Linux: sudo pacman -S clang\n" - + "See https://clangd.llvm.org/installation for more details." - ) - log.info(f"Using system-installed clangd at {clangd_executable_path}") - else: - # Standard download and install for platforms with prebuilt binaries - clangd_executable_path = deps.binary_path(clangd_ls_dir) - if not os.path.exists(clangd_executable_path): - log.info(f"Clangd executable not found at {clangd_executable_path}. Downloading from {dep.url}") - _ = deps.install(clangd_ls_dir) - if not os.path.exists(clangd_executable_path): - raise FileNotFoundError( - f"Clangd executable not found at {clangd_executable_path}.\n" - + "Make sure you have installed clangd. See https://clangd.llvm.org/installation" - ) - os.chmod(clangd_executable_path, 0o755) - return clangd_executable_path + try: + dep = deps.get_single_dep_for_current_platform() + except RuntimeError: + dep = None + + if dep is None: + # No prebuilt binary available, look for system-installed clangd + clangd_executable_path = shutil.which("clangd") + if not clangd_executable_path: + raise FileNotFoundError( + "Clangd is not installed on your system.\n" + + "Please install clangd using your system package manager:\n" + + " Ubuntu/Debian: sudo apt-get install clangd\n" + + " Fedora/RHEL: sudo dnf install clang-tools-extra\n" + + " Arch Linux: sudo pacman -S clang\n" + + "See https://clangd.llvm.org/installation for more details." + ) + log.info(f"Using system-installed clangd at {clangd_executable_path}") + else: + # Standard download and install for platforms with prebuilt binaries + clangd_executable_path = deps.binary_path(clangd_ls_dir) + if not os.path.exists(clangd_executable_path): + log.info(f"Clangd executable not found at {clangd_executable_path}. Downloading from {dep.url}") + _ = deps.install(clangd_ls_dir) + if not os.path.exists(clangd_executable_path): + raise FileNotFoundError( + f"Clangd executable not found at {clangd_executable_path}.\n" + + "Make sure you have installed clangd. See https://clangd.llvm.org/installation" + ) + os.chmod(clangd_executable_path, 0o755) + return clangd_executable_path + + def _create_launch_command(self, core_path: str) -> list[str] | str: + return [core_path] @staticmethod def _get_initialize_params(repository_absolute_path: str) -> InitializeParams: