diff --git a/src/serena/project.py b/src/serena/project.py index b73a252d..d6a7ba79 100644 --- a/src/serena/project.py +++ b/src/serena/project.py @@ -5,11 +5,13 @@ from pathlib import Path import pathspec from serena.config.serena_config import DEFAULT_TOOL_TIMEOUT, ProjectConfig +from serena.constants import SERENA_MANAGED_DIR_IN_HOME from serena.text_utils import MatchedConsecutiveLines, search_files from serena.util.file_system import GitignoreParser, match_path from solidlsp import SolidLanguageServer from solidlsp.ls_config import Language, LanguageServerConfig from solidlsp.ls_logger import LanguageServerLogger +from solidlsp.settings import SolidLSPSettings log = logging.getLogger(__name__) @@ -271,4 +273,5 @@ class Project: ls_logger, self.project_root, timeout=ls_timeout, + solidlsp_settings=SolidLSPSettings(solidlsp_dir=SERENA_MANAGED_DIR_IN_HOME), ) diff --git a/src/solidlsp/language_servers/clangd_language_server.py b/src/solidlsp/language_servers/clangd_language_server.py index b8845d84..a770d78e 100644 --- a/src/solidlsp/language_servers/clangd_language_server.py +++ b/src/solidlsp/language_servers/clangd_language_server.py @@ -13,6 +13,7 @@ from solidlsp.ls_config import LanguageServerConfig from solidlsp.ls_logger import LanguageServerLogger 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 @@ -24,25 +25,30 @@ class ClangdLanguageServer(SolidLanguageServer): Also make sure compile_commands.json is created at root of the source directory. Check clangd test case for example. """ - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates a ClangdLanguageServer instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - clangd_executable_path = self._setup_runtime_dependencies(logger, config) + clangd_executable_path = self._setup_runtime_dependencies(logger, config, solidlsp_settings) super().__init__( config, logger, repository_root_path, ProcessLaunchInfo(cmd=clangd_executable_path, cwd=repository_root_path), "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() - @staticmethod - def _setup_runtime_dependencies(logger: LanguageServerLogger, config: LanguageServerConfig) -> str: + @classmethod + def _setup_runtime_dependencies( + cls, logger: LanguageServerLogger, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings + ) -> str: """ Setup runtime dependencies for ClangdLanguageServer and return the command to start the server. """ @@ -75,7 +81,7 @@ class ClangdLanguageServer(SolidLanguageServer): ] ) - clangd_ls_dir = os.path.join(os.path.dirname(__file__), "static", "clangd") + clangd_ls_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "clangd") dep = deps.single_for_current_platform() clangd_executable_path = deps.binary_path(clangd_ls_dir) if not os.path.exists(clangd_executable_path): diff --git a/src/solidlsp/language_servers/clojure_lsp.py b/src/solidlsp/language_servers/clojure_lsp.py index 5939a7e4..f973db15 100644 --- a/src/solidlsp/language_servers/clojure_lsp.py +++ b/src/solidlsp/language_servers/clojure_lsp.py @@ -15,6 +15,7 @@ from solidlsp.ls_config import LanguageServerConfig from solidlsp.ls_logger import LanguageServerLogger 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 @@ -78,17 +79,20 @@ class ClojureLSP(SolidLanguageServer): ] ) - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates a ClojureLSP instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - clojure_lsp_executable_path = self._setup_runtime_dependencies(logger, config) + clojure_lsp_executable_path = self._setup_runtime_dependencies(logger, config, solidlsp_settings) super().__init__( config, logger, repository_root_path, ProcessLaunchInfo(cmd=clojure_lsp_executable_path, cwd=repository_root_path), "clojure", + solidlsp_settings, ) self.server_ready = threading.Event() self.initialize_searcher_command_available = threading.Event() @@ -96,13 +100,15 @@ class ClojureLSP(SolidLanguageServer): self.service_ready_event = threading.Event() @classmethod - def _setup_runtime_dependencies(cls, logger: LanguageServerLogger, config: LanguageServerConfig) -> str: + def _setup_runtime_dependencies( + cls, logger: LanguageServerLogger, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings + ) -> str: """Setup runtime dependencies for clojure-lsp and return the command to start the server.""" verify_clojure_cli() deps = ClojureLSP.runtime_dependencies dependency = deps.single_for_current_platform() - clojurelsp_ls_dir = cls.ls_resources_dir() + clojurelsp_ls_dir = cls.ls_resources_dir(solidlsp_settings) clojurelsp_executable_path = deps.binary_path(clojurelsp_ls_dir) if not os.path.exists(clojurelsp_executable_path): logger.log( diff --git a/src/solidlsp/language_servers/csharp_language_server.py b/src/solidlsp/language_servers/csharp_language_server.py index 7d11a1df..88bf9bc4 100644 --- a/src/solidlsp/language_servers/csharp_language_server.py +++ b/src/solidlsp/language_servers/csharp_language_server.py @@ -25,6 +25,7 @@ from solidlsp.ls_logger import LanguageServerLogger from solidlsp.ls_utils import PathUtils 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 @@ -175,18 +176,20 @@ class CSharpLanguageServer(SolidLanguageServer): This is the official Roslyn-based language server from Microsoft. """ - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates a CSharpLanguageServer instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - dotnet_path, language_server_path = self._ensure_server_installed(logger, config) + dotnet_path, language_server_path = self._ensure_server_installed(logger, config, solidlsp_settings) # Find solution or project file solution_or_project = find_solution_or_project_file(repository_root_path) # Create log directory - log_dir = Path(self.ls_resources_dir()) / "logs" + log_dir = Path(self.ls_resources_dir(solidlsp_settings)) / "logs" log_dir.mkdir(parents=True, exist_ok=True) # Build command using dotnet directly @@ -206,6 +209,7 @@ class CSharpLanguageServer(SolidLanguageServer): repository_root_path, ProcessLaunchInfo(cmd=cmd, cwd=repository_root_path), "csharp", + solidlsp_settings, ) self.initialization_complete = threading.Event() @@ -215,15 +219,17 @@ class CSharpLanguageServer(SolidLanguageServer): return super().is_ignored_dirname(dirname) or dirname in ["bin", "obj", "packages", ".vs"] @classmethod - def _ensure_server_installed(cls, logger: LanguageServerLogger, config: LanguageServerConfig) -> tuple[str, str]: + def _ensure_server_installed( + cls, logger: LanguageServerLogger, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings + ) -> tuple[str, str]: """ Ensure .NET runtime and Microsoft.CodeAnalysis.LanguageServer are available. Returns a tuple of (dotnet_path, language_server_dll_path). """ runtime_id = CSharpLanguageServer._get_runtime_id() lang_server_dep, dotnet_runtime_dep = CSharpLanguageServer._get_runtime_dependencies(runtime_id) - dotnet_path = CSharpLanguageServer._ensure_dotnet_runtime(logger, dotnet_runtime_dep) - server_dll_path = CSharpLanguageServer._ensure_language_server(logger, lang_server_dep) + dotnet_path = CSharpLanguageServer._ensure_dotnet_runtime(logger, dotnet_runtime_dep, solidlsp_settings) + server_dll_path = CSharpLanguageServer._ensure_language_server(logger, lang_server_dep, solidlsp_settings) return dotnet_path, server_dll_path @@ -261,8 +267,10 @@ class CSharpLanguageServer(SolidLanguageServer): return lang_server_dep, dotnet_runtime_dep - @staticmethod - def _ensure_dotnet_runtime(logger: LanguageServerLogger, runtime_dep: RuntimeDependency) -> str: + @classmethod + def _ensure_dotnet_runtime( + cls, logger: LanguageServerLogger, runtime_dep: RuntimeDependency, solidlsp_settings: SolidLSPSettings + ) -> str: """Ensure .NET runtime is available and return the dotnet executable path.""" # Check if dotnet is already available on the system system_dotnet = shutil.which("dotnet") @@ -277,15 +285,17 @@ class CSharpLanguageServer(SolidLanguageServer): pass # Download .NET 9 runtime using config - return CSharpLanguageServer._ensure_dotnet_runtime_from_config(logger, runtime_dep) + return cls._ensure_dotnet_runtime_from_config(logger, runtime_dep, solidlsp_settings) @classmethod - def _ensure_language_server(cls, logger: LanguageServerLogger, lang_server_dep: RuntimeDependency) -> str: + def _ensure_language_server( + cls, logger: LanguageServerLogger, lang_server_dep: RuntimeDependency, solidlsp_settings: SolidLSPSettings + ) -> str: """Ensure language server is available and return the DLL path.""" package_name = lang_server_dep.package_name package_version = lang_server_dep.package_version - server_dir = Path(cls.ls_resources_dir()) / f"{package_name}.{package_version}" + server_dir = Path(cls.ls_resources_dir(solidlsp_settings)) / f"{package_name}.{package_version}" server_dll = server_dir / lang_server_dep.binary_name if server_dll.exists(): @@ -294,10 +304,10 @@ class CSharpLanguageServer(SolidLanguageServer): # Download and install the language server logger.log(f"Downloading {package_name} version {package_version}...", logging.INFO) - package_path = CSharpLanguageServer._download_nuget_package_direct(logger, package_name, package_version) + package_path = cls._download_nuget_package_direct(logger, package_name, package_version, solidlsp_settings) # Extract and install - CSharpLanguageServer._extract_language_server(lang_server_dep, package_path, server_dir) + cls._extract_language_server(lang_server_dep, package_path, server_dir) if not server_dll.exists(): raise LanguageServerException("Microsoft.CodeAnalysis.LanguageServer.dll not found after extraction") @@ -333,7 +343,9 @@ class CSharpLanguageServer(SolidLanguageServer): shutil.copytree(source_dir, server_dir, dirs_exist_ok=True) @classmethod - def _download_nuget_package_direct(cls, logger: LanguageServerLogger, package_name: str, package_version: str) -> Path: + def _download_nuget_package_direct( + cls, logger: LanguageServerLogger, package_name: str, package_version: str, solidlsp_settings: SolidLSPSettings + ) -> Path: """ Download a NuGet package directly from the Azure NuGet feed. Returns the path to the extracted package directory. @@ -341,7 +353,7 @@ class CSharpLanguageServer(SolidLanguageServer): azure_feed_url = "https://pkgs.dev.azure.com/azure-public/vside/_packaging/vs-impl/nuget/v3/index.json" # Create temporary directory for package download - temp_dir = Path(cls.ls_resources_dir()) / "temp_downloads" + temp_dir = Path(cls.ls_resources_dir(solidlsp_settings)) / "temp_downloads" temp_dir.mkdir(parents=True, exist_ok=True) try: @@ -390,7 +402,9 @@ class CSharpLanguageServer(SolidLanguageServer): ) from e @classmethod - def _ensure_dotnet_runtime_from_config(cls, logger: LanguageServerLogger, runtime_dep: RuntimeDependency) -> str: + def _ensure_dotnet_runtime_from_config( + cls, logger: LanguageServerLogger, runtime_dep: RuntimeDependency, solidlsp_settings: SolidLSPSettings + ) -> str: """ Ensure .NET 9 runtime is available using runtime dependency configuration. Returns the path to the dotnet executable. @@ -408,7 +422,7 @@ class CSharpLanguageServer(SolidLanguageServer): pass # Download .NET 9 runtime using config - dotnet_dir = Path(cls.ls_resources_dir()) / "dotnet-runtime-9.0" + dotnet_dir = Path(cls.ls_resources_dir(solidlsp_settings)) / "dotnet-runtime-9.0" dotnet_exe = dotnet_dir / runtime_dep.binary_name if dotnet_exe.exists(): diff --git a/src/solidlsp/language_servers/dart_language_server.py b/src/solidlsp/language_servers/dart_language_server.py index 28696ad6..c9cfcad1 100644 --- a/src/solidlsp/language_servers/dart_language_server.py +++ b/src/solidlsp/language_servers/dart_language_server.py @@ -6,6 +6,7 @@ import stat from solidlsp.ls import SolidLanguageServer from solidlsp.ls_logger import LanguageServerLogger from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo +from solidlsp.settings import SolidLSPSettings from .common import RuntimeDependency, RuntimeDependencyCollection @@ -15,21 +16,22 @@ class DartLanguageServer(SolidLanguageServer): Provides Dart specific instantiation of the LanguageServer class. Contains various configurations and settings specific to Dart. """ - def __init__(self, config, logger, repository_root_path): + def __init__(self, config, logger, repository_root_path, solidlsp_settings: SolidLSPSettings): """ Creates a DartServer instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - executable_path = self._setup_runtime_dependencies(logger) + executable_path = self._setup_runtime_dependencies(logger, solidlsp_settings) super().__init__( config, logger, repository_root_path, ProcessLaunchInfo(cmd=executable_path, cwd=repository_root_path), "dart", + solidlsp_settings, ) @classmethod - def _setup_runtime_dependencies(cls, logger: "LanguageServerLogger") -> str: + def _setup_runtime_dependencies(cls, logger: "LanguageServerLogger", solidlsp_settings: SolidLSPSettings) -> str: deps = RuntimeDependencyCollection( [ RuntimeDependency( @@ -75,7 +77,7 @@ class DartLanguageServer(SolidLanguageServer): ] ) - dart_ls_dir = cls.ls_resources_dir() + dart_ls_dir = cls.ls_resources_dir(solidlsp_settings) dart_executable_path = deps.binary_path(dart_ls_dir) if not os.path.exists(dart_executable_path): diff --git a/src/solidlsp/language_servers/eclipse_jdtls.py b/src/solidlsp/language_servers/eclipse_jdtls.py index 3ac80046..bf87aab7 100644 --- a/src/solidlsp/language_servers/eclipse_jdtls.py +++ b/src/solidlsp/language_servers/eclipse_jdtls.py @@ -51,7 +51,7 @@ class EclipseJDTLS(SolidLanguageServer): Creates a new EclipseJDTLS instance initializing the language server settings appropriately. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - runtime_dependency_paths = self._setupRuntimeDependencies(logger, config) + runtime_dependency_paths = self._setupRuntimeDependencies(logger, config, solidlsp_settings) self.runtime_dependency_paths = runtime_dependency_paths # ws_dir is the workspace directory for the EclipseJDTLS server @@ -157,7 +157,9 @@ class EclipseJDTLS(SolidLanguageServer): ] @classmethod - def _setupRuntimeDependencies(cls, logger: LanguageServerLogger, config: LanguageServerConfig) -> RuntimeDependencyPaths: + def _setupRuntimeDependencies( + cls, logger: LanguageServerLogger, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings + ) -> RuntimeDependencyPaths: """ Setup runtime dependencies for EclipseJDTLS and return the paths. """ @@ -242,7 +244,7 @@ class EclipseJDTLS(SolidLanguageServer): gradle_path = str( PurePath( - cls.ls_resources_dir(), + cls.ls_resources_dir(solidlsp_settings), "gradle-7.3.3", ) ) @@ -258,7 +260,7 @@ class EclipseJDTLS(SolidLanguageServer): assert os.path.exists(gradle_path) dependency = runtime_dependencies["vscode-java"][platformId.value] - vscode_java_path = str(PurePath(cls.ls_resources_dir(), dependency["relative_extraction_path"])) + vscode_java_path = str(PurePath(cls.ls_resources_dir(solidlsp_settings), dependency["relative_extraction_path"])) os.makedirs(vscode_java_path, exist_ok=True) jre_home_path = str(PurePath(vscode_java_path, dependency["jre_home_path"])) jre_path = str(PurePath(vscode_java_path, dependency["jre_path"])) @@ -287,7 +289,7 @@ class EclipseJDTLS(SolidLanguageServer): assert os.path.exists(jdtls_readonly_config_path) dependency = runtime_dependencies["intellicode"]["platform-agnostic"] - intellicode_directory_path = str(PurePath(cls.ls_resources_dir(), dependency["relative_extraction_path"])) + intellicode_directory_path = str(PurePath(cls.ls_resources_dir(solidlsp_settings), dependency["relative_extraction_path"])) os.makedirs(intellicode_directory_path, exist_ok=True) intellicode_jar_path = str(PurePath(intellicode_directory_path, dependency["intellicode_jar_path"])) intellisense_members_path = str(PurePath(intellicode_directory_path, dependency["intellisense_members_path"])) diff --git a/src/solidlsp/language_servers/elixir_tools/elixir_tools.py b/src/solidlsp/language_servers/elixir_tools/elixir_tools.py index 16df9027..5f6a9794 100644 --- a/src/solidlsp/language_servers/elixir_tools/elixir_tools.py +++ b/src/solidlsp/language_servers/elixir_tools/elixir_tools.py @@ -14,6 +14,7 @@ from solidlsp.ls_logger import LanguageServerLogger from solidlsp.ls_utils import FileUtils, PlatformId, PlatformUtils 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 @@ -80,7 +81,9 @@ class ElixirTools(SolidLanguageServer): return None @classmethod - def _setup_runtime_dependencies(cls, logger: LanguageServerLogger, config: LanguageServerConfig) -> str: + def _setup_runtime_dependencies( + cls, logger: LanguageServerLogger, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings + ) -> str: """ Setup runtime dependencies for Next LS. Downloads the Next LS binary for the current platform and returns the path to the executable. @@ -110,7 +113,7 @@ class ElixirTools(SolidLanguageServer): ] assert platform_id in valid_platforms, f"Platform {platform_id} is not supported for Next LS at the moment" - next_ls_dir = os.path.join(cls.ls_resources_dir(), "next-ls") + next_ls_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "next-ls") # Define runtime dependencies inline runtime_deps = { @@ -162,8 +165,10 @@ class ElixirTools(SolidLanguageServer): logger.log(f"Next LS binary ready at: {executable_path}", logging.INFO) return executable_path - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): - nextls_executable_path = self._setup_runtime_dependencies(logger, config) + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): + nextls_executable_path = self._setup_runtime_dependencies(logger, config, solidlsp_settings) super().__init__( config, @@ -171,6 +176,7 @@ class ElixirTools(SolidLanguageServer): repository_root_path, ProcessLaunchInfo(cmd=f'"{nextls_executable_path}" --stdio', cwd=repository_root_path), "elixir", + solidlsp_settings, ) self.server_ready = threading.Event() self.request_id = 0 diff --git a/src/solidlsp/language_servers/gopls.py b/src/solidlsp/language_servers/gopls.py index 70eb15fa..c21663b7 100644 --- a/src/solidlsp/language_servers/gopls.py +++ b/src/solidlsp/language_servers/gopls.py @@ -11,6 +11,7 @@ from solidlsp.ls_config import LanguageServerConfig from solidlsp.ls_logger import LanguageServerLogger from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo +from solidlsp.settings import SolidLSPSettings class Gopls(SolidLanguageServer): @@ -70,7 +71,9 @@ class Gopls(SolidLanguageServer): return True - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): self._setup_runtime_dependency() super().__init__( @@ -79,6 +82,7 @@ class Gopls(SolidLanguageServer): repository_root_path, ProcessLaunchInfo(cmd="gopls", cwd=repository_root_path), "go", + solidlsp_settings, ) self.server_ready = threading.Event() self.request_id = 0 diff --git a/src/solidlsp/language_servers/intelephense.py b/src/solidlsp/language_servers/intelephense.py index f9c83976..2d1d48e2 100644 --- a/src/solidlsp/language_servers/intelephense.py +++ b/src/solidlsp/language_servers/intelephense.py @@ -16,6 +16,7 @@ from solidlsp.ls_logger import LanguageServerLogger from solidlsp.ls_utils import PlatformId, PlatformUtils from solidlsp.lsp_protocol_handler.lsp_types import DefinitionParams, InitializeParams from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo +from solidlsp.settings import SolidLSPSettings from .common import RuntimeDependency, RuntimeDependencyCollection @@ -34,7 +35,9 @@ class Intelephense(SolidLanguageServer): return super().is_ignored_dirname(dirname) or dirname in ["node_modules", "vendor", "cache"] @classmethod - def _setup_runtime_dependencies(cls, logger: LanguageServerLogger, config: LanguageServerConfig) -> str: + def _setup_runtime_dependencies( + cls, logger: LanguageServerLogger, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings + ) -> str: """ Setup runtime dependencies for Intelephense and return the command to start the server. """ @@ -58,7 +61,7 @@ class Intelephense(SolidLanguageServer): assert is_npm_installed, "npm is not installed or isn't in PATH. Please install npm and try again." # Install intelephense if not already installed - intelephense_ls_dir = os.path.join(cls.ls_resources_dir(), "php-lsp") + intelephense_ls_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "php-lsp") os.makedirs(intelephense_ls_dir, exist_ok=True) intelephense_executable_path = os.path.join(intelephense_ls_dir, "node_modules", ".bin", "intelephense") if not os.path.exists(intelephense_executable_path): @@ -79,11 +82,20 @@ class Intelephense(SolidLanguageServer): return f"{intelephense_executable_path} --stdio" - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): # Setup runtime dependencies before initializing - intelephense_cmd = self._setup_runtime_dependencies(logger, config) + intelephense_cmd = self._setup_runtime_dependencies(logger, config, solidlsp_settings) - super().__init__(config, logger, repository_root_path, ProcessLaunchInfo(cmd=intelephense_cmd, cwd=repository_root_path), "php") + super().__init__( + config, + logger, + repository_root_path, + ProcessLaunchInfo(cmd=intelephense_cmd, cwd=repository_root_path), + "php", + solidlsp_settings, + ) self.request_id = 0 @staticmethod diff --git a/src/solidlsp/language_servers/jedi_server.py b/src/solidlsp/language_servers/jedi_server.py index 161ce754..956e00b9 100644 --- a/src/solidlsp/language_servers/jedi_server.py +++ b/src/solidlsp/language_servers/jedi_server.py @@ -13,6 +13,7 @@ from solidlsp.ls_config import LanguageServerConfig from solidlsp.ls_logger import LanguageServerLogger from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo +from solidlsp.settings import SolidLSPSettings class JediServer(SolidLanguageServer): @@ -20,7 +21,9 @@ class JediServer(SolidLanguageServer): Provides Python specific instantiation of the LanguageServer class. Contains various configurations and settings specific to Python. """ - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates a JediServer instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ @@ -30,6 +33,7 @@ class JediServer(SolidLanguageServer): repository_root_path, ProcessLaunchInfo(cmd="jedi-language-server", cwd=repository_root_path), "python", + solidlsp_settings, ) @override diff --git a/src/solidlsp/language_servers/kotlin_language_server.py b/src/solidlsp/language_servers/kotlin_language_server.py index ef2a77ca..5d0d2083 100644 --- a/src/solidlsp/language_servers/kotlin_language_server.py +++ b/src/solidlsp/language_servers/kotlin_language_server.py @@ -14,6 +14,7 @@ from solidlsp.ls_logger import LanguageServerLogger from solidlsp.ls_utils import FileUtils, PlatformUtils from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo +from solidlsp.settings import SolidLSPSettings @dataclasses.dataclass @@ -32,11 +33,13 @@ class KotlinLanguageServer(SolidLanguageServer): Provides Kotlin specific instantiation of the LanguageServer class. Contains various configurations and settings specific to Kotlin. """ - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates a Kotlin Language Server instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - runtime_dependency_paths = self._setup_runtime_dependencies(logger, config) + runtime_dependency_paths = self._setup_runtime_dependencies(logger, config, solidlsp_settings) self.runtime_dependency_paths = runtime_dependency_paths # Create command to execute the Kotlin Language Server script @@ -51,10 +54,13 @@ class KotlinLanguageServer(SolidLanguageServer): repository_root_path, ProcessLaunchInfo(cmd=cmd, env=proc_env, cwd=repository_root_path), "kotlin", + solidlsp_settings, ) @classmethod - def _setup_runtime_dependencies(cls, logger: LanguageServerLogger, config: LanguageServerConfig) -> KotlinRuntimeDependencyPaths: + def _setup_runtime_dependencies( + cls, logger: LanguageServerLogger, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings + ) -> KotlinRuntimeDependencyPaths: """ Setup runtime dependencies for Kotlin Language Server and return the paths. """ @@ -111,7 +117,7 @@ class KotlinLanguageServer(SolidLanguageServer): java_dependency = runtime_dependencies["java"][platform_id.value] # Setup paths for dependencies - static_dir = os.path.join(cls.ls_resources_dir(), "kotlin_language_server") + static_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "kotlin_language_server") os.makedirs(static_dir, exist_ok=True) # Setup Java paths diff --git a/src/solidlsp/language_servers/omnisharp.py b/src/solidlsp/language_servers/omnisharp.py index eafaa310..a23a58a8 100644 --- a/src/solidlsp/language_servers/omnisharp.py +++ b/src/solidlsp/language_servers/omnisharp.py @@ -19,6 +19,7 @@ from solidlsp.ls_logger import LanguageServerLogger from solidlsp.ls_utils import DotnetVersion, FileUtils, PlatformId, PlatformUtils from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo +from solidlsp.settings import SolidLSPSettings def breadth_first_file_scan(root) -> Iterable[str]: @@ -59,11 +60,13 @@ class OmniSharp(SolidLanguageServer): Provides C# specific instantiation of the LanguageServer class. Contains various configurations and settings specific to C#. """ - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates an OmniSharp instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - omnisharp_executable_path, dll_path = self._setup_runtime_dependencies(logger, config) + omnisharp_executable_path, dll_path = self._setup_runtime_dependencies(logger, config, solidlsp_settings) slnfilename = find_least_depth_sln_file(repository_root_path) if slnfilename is None: @@ -102,7 +105,9 @@ class OmniSharp(SolidLanguageServer): "formattingOptions:indentationSize=4", ] ) - super().__init__(config, logger, repository_root_path, ProcessLaunchInfo(cmd=cmd, cwd=repository_root_path), "csharp") + super().__init__( + config, logger, repository_root_path, ProcessLaunchInfo(cmd=cmd, cwd=repository_root_path), "csharp", solidlsp_settings + ) self.server_ready = threading.Event() self.definition_available = threading.Event() @@ -138,7 +143,9 @@ class OmniSharp(SolidLanguageServer): return d @classmethod - def _setup_runtime_dependencies(cls, logger: LanguageServerLogger, config: LanguageServerConfig) -> tuple[str, str]: + def _setup_runtime_dependencies( + cls, logger: LanguageServerLogger, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings + ) -> tuple[str, str]: """ Setup runtime dependencies for OmniSharp. """ @@ -181,7 +188,7 @@ class OmniSharp(SolidLanguageServer): assert "OmniSharp" in runtime_dependencies assert "RazorOmnisharp" in runtime_dependencies - omnisharp_ls_dir = os.path.join(cls.ls_resources_dir(), "OmniSharp") + omnisharp_ls_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "OmniSharp") if not os.path.exists(omnisharp_ls_dir): os.makedirs(omnisharp_ls_dir) FileUtils.download_and_extract_archive(logger, runtime_dependencies["OmniSharp"]["url"], omnisharp_ls_dir, "zip") @@ -189,7 +196,7 @@ class OmniSharp(SolidLanguageServer): assert os.path.exists(omnisharp_executable_path) os.chmod(omnisharp_executable_path, stat.S_IEXEC) - razor_omnisharp_ls_dir = os.path.join(cls.ls_resources_dir(), "RazorOmnisharp") + razor_omnisharp_ls_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "RazorOmnisharp") if not os.path.exists(razor_omnisharp_ls_dir): os.makedirs(razor_omnisharp_ls_dir) FileUtils.download_and_extract_archive(logger, runtime_dependencies["RazorOmnisharp"]["url"], razor_omnisharp_ls_dir, "zip") diff --git a/src/solidlsp/language_servers/pyright_server.py b/src/solidlsp/language_servers/pyright_server.py index 905bb3d6..c760ebc1 100644 --- a/src/solidlsp/language_servers/pyright_server.py +++ b/src/solidlsp/language_servers/pyright_server.py @@ -15,6 +15,7 @@ from solidlsp.ls_config import LanguageServerConfig from solidlsp.ls_logger import LanguageServerLogger from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo +from solidlsp.settings import SolidLSPSettings class PyrightServer(SolidLanguageServer): @@ -23,7 +24,9 @@ class PyrightServer(SolidLanguageServer): Contains various configurations and settings specific to Python. """ - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates a PyrightServer instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. @@ -36,6 +39,7 @@ class PyrightServer(SolidLanguageServer): # Note 2: we can also use `bpyright-langserver --stdio` if we ever are unhappy with pyright ProcessLaunchInfo(cmd="python -m pyright.langserver --stdio", cwd=repository_root_path), "python", + solidlsp_settings, ) # Event to signal when initial workspace analysis is complete diff --git a/src/solidlsp/language_servers/rust_analyzer.py b/src/solidlsp/language_servers/rust_analyzer.py index 0f2f2cf1..48bae28a 100644 --- a/src/solidlsp/language_servers/rust_analyzer.py +++ b/src/solidlsp/language_servers/rust_analyzer.py @@ -15,6 +15,7 @@ from solidlsp.ls_config import LanguageServerConfig from solidlsp.ls_logger import LanguageServerLogger 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 @@ -24,17 +25,20 @@ class RustAnalyzer(SolidLanguageServer): Provides Rust specific instantiation of the LanguageServer class. Contains various configurations and settings specific to Rust. """ - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates a RustAnalyzer instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - rustanalyzer_executable_path = self._setup_runtime_dependencies(logger, config) + rustanalyzer_executable_path = self._setup_runtime_dependencies(logger, config, solidlsp_settings) super().__init__( config, logger, repository_root_path, ProcessLaunchInfo(cmd=rustanalyzer_executable_path, cwd=repository_root_path), "rust", + solidlsp_settings, ) self.server_ready = threading.Event() self.service_ready_event = threading.Event() @@ -46,7 +50,9 @@ class RustAnalyzer(SolidLanguageServer): return super().is_ignored_dirname(dirname) or dirname in ["target"] @classmethod - def _setup_runtime_dependencies(cls, logger: LanguageServerLogger, config: LanguageServerConfig) -> str: + def _setup_runtime_dependencies( + cls, logger: LanguageServerLogger, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings + ) -> str: """ Setup runtime dependencies for rust_analyzer and return the command to start the server. """ @@ -92,7 +98,7 @@ class RustAnalyzer(SolidLanguageServer): # "win-x64", # ], "Only linux-x64 and win-x64 platform is supported for in multilspy at the moment" - rustanalyzer_ls_dir = os.path.join(cls.ls_resources_dir(), "RustAnalyzer") + rustanalyzer_ls_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "RustAnalyzer") rustanalyzer_executable_path = deps.binary_path(rustanalyzer_ls_dir) if not os.path.exists(rustanalyzer_ls_dir): os.makedirs(rustanalyzer_ls_dir) diff --git a/src/solidlsp/language_servers/solargraph.py b/src/solidlsp/language_servers/solargraph.py index 8034ad80..56a1b7f7 100644 --- a/src/solidlsp/language_servers/solargraph.py +++ b/src/solidlsp/language_servers/solargraph.py @@ -18,6 +18,7 @@ from solidlsp.ls_config import LanguageServerConfig from solidlsp.ls_logger import LanguageServerLogger from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo +from solidlsp.settings import SolidLSPSettings class Solargraph(SolidLanguageServer): @@ -26,7 +27,9 @@ class Solargraph(SolidLanguageServer): Contains various configurations and settings specific to Ruby. """ - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates a Solargraph instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. @@ -38,6 +41,7 @@ class Solargraph(SolidLanguageServer): repository_root_path, ProcessLaunchInfo(cmd=f"{solargraph_executable_path} stdio", cwd=repository_root_path), "ruby", + solidlsp_settings, ) self.server_ready = threading.Event() self.service_ready_event = threading.Event() diff --git a/src/solidlsp/language_servers/terraform_ls.py b/src/solidlsp/language_servers/terraform_ls.py index 5a230a23..e40d9af1 100644 --- a/src/solidlsp/language_servers/terraform_ls.py +++ b/src/solidlsp/language_servers/terraform_ls.py @@ -12,6 +12,7 @@ from solidlsp.ls_logger import LanguageServerLogger from solidlsp.ls_utils import PathUtils, PlatformUtils 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 @@ -57,7 +58,7 @@ class TerraformLS(SolidLanguageServer): ) @classmethod - def _setup_runtime_dependencies(cls, logger: LanguageServerLogger) -> str: + def _setup_runtime_dependencies(cls, logger: LanguageServerLogger, solidlsp_settings: SolidLSPSettings) -> str: """ Setup runtime dependencies for terraform-ls. Downloads and installs terraform-ls if not already present. @@ -102,10 +103,10 @@ class TerraformLS(SolidLanguageServer): ) dependency = deps.single_for_current_platform() - terraform_ls_executable_path = deps.binary_path(cls.ls_resources_dir()) + terraform_ls_executable_path = deps.binary_path(cls.ls_resources_dir(solidlsp_settings)) if not os.path.exists(terraform_ls_executable_path): logger.log(f"Downloading terraform-ls from {dependency.url}", logging.INFO) - deps.install(logger, cls.ls_resources_dir()) + deps.install(logger, cls.ls_resources_dir(solidlsp_settings)) assert os.path.exists(terraform_ls_executable_path), f"terraform-ls executable not found at {terraform_ls_executable_path}" @@ -115,11 +116,13 @@ class TerraformLS(SolidLanguageServer): return terraform_ls_executable_path - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates a TerraformLS instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - terraform_ls_executable_path = self._setup_runtime_dependencies(logger) + terraform_ls_executable_path = self._setup_runtime_dependencies(logger, solidlsp_settings) super().__init__( config, @@ -127,6 +130,7 @@ class TerraformLS(SolidLanguageServer): repository_root_path, ProcessLaunchInfo(cmd=f"{terraform_ls_executable_path} serve", cwd=repository_root_path), "terraform", + solidlsp_settings, ) self.server_ready = threading.Event() self.request_id = 0 diff --git a/src/solidlsp/language_servers/typescript_language_server.py b/src/solidlsp/language_servers/typescript_language_server.py index f994f95f..9709cc8f 100644 --- a/src/solidlsp/language_servers/typescript_language_server.py +++ b/src/solidlsp/language_servers/typescript_language_server.py @@ -17,6 +17,7 @@ from solidlsp.ls_logger import LanguageServerLogger from solidlsp.ls_utils import PlatformId, PlatformUtils 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 @@ -41,17 +42,20 @@ class TypeScriptLanguageServer(SolidLanguageServer): Provides TypeScript specific instantiation of the LanguageServer class. Contains various configurations and settings specific to TypeScript. """ - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates a TypeScriptLanguageServer instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - ts_lsp_executable_path = self._setup_runtime_dependencies(logger, config) + ts_lsp_executable_path = self._setup_runtime_dependencies(logger, config, solidlsp_settings) super().__init__( config, logger, repository_root_path, ProcessLaunchInfo(cmd=ts_lsp_executable_path, cwd=repository_root_path), "typescript", + solidlsp_settings, ) self.server_ready = threading.Event() self.initialize_searcher_command_available = threading.Event() @@ -66,7 +70,9 @@ class TypeScriptLanguageServer(SolidLanguageServer): ] @classmethod - def _setup_runtime_dependencies(cls, logger: LanguageServerLogger, config: LanguageServerConfig) -> str: + def _setup_runtime_dependencies( + cls, logger: LanguageServerLogger, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings + ) -> str: """ Setup runtime dependencies for TypeScript Language Server and return the command to start the server. """ @@ -113,7 +119,7 @@ class TypeScriptLanguageServer(SolidLanguageServer): assert is_npm_installed, "npm is not installed or isn't in PATH. Please install npm and try again." # Install typescript and typescript-language-server if not already installed - tsserver_ls_dir = os.path.join(cls.ls_resources_dir(), "ts-lsp") + tsserver_ls_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "ts-lsp") tsserver_executable_path = os.path.join(tsserver_ls_dir, "node_modules", ".bin", "typescript-language-server") if not os.path.exists(tsserver_executable_path): logger.log(f"Typescript Language Server executable not found at {tsserver_executable_path}. Installing...", logging.INFO) diff --git a/src/solidlsp/language_servers/vts_language_server.py b/src/solidlsp/language_servers/vts_language_server.py index 40de7b55..c8596b89 100644 --- a/src/solidlsp/language_servers/vts_language_server.py +++ b/src/solidlsp/language_servers/vts_language_server.py @@ -19,6 +19,7 @@ from solidlsp.ls_logger import LanguageServerLogger from solidlsp.ls_utils import PlatformId, PlatformUtils 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 @@ -29,17 +30,20 @@ class VtsLanguageServer(SolidLanguageServer): Contains various configurations and settings specific to TypeScript via vtsls wrapper. """ - def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str): + def __init__( + self, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, solidlsp_settings: SolidLSPSettings + ): """ Creates a VtsLanguageServer instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ - vts_lsp_executable_path = self._setup_runtime_dependencies(logger, config) + vts_lsp_executable_path = self._setup_runtime_dependencies(logger, config, solidlsp_settings) super().__init__( config, logger, repository_root_path, ProcessLaunchInfo(cmd=vts_lsp_executable_path, cwd=repository_root_path), "typescript", + solidlsp_settings, ) self.server_ready = threading.Event() self.initialize_searcher_command_available = threading.Event() @@ -54,7 +58,9 @@ class VtsLanguageServer(SolidLanguageServer): ] @classmethod - def _setup_runtime_dependencies(cls, logger: LanguageServerLogger, config: LanguageServerConfig) -> str: + def _setup_runtime_dependencies( + cls, logger: LanguageServerLogger, config: LanguageServerConfig, solidlsp_settings: SolidLSPSettings + ) -> str: """ Setup runtime dependencies for VTS Language Server and return the command to start the server. """ @@ -81,7 +87,7 @@ class VtsLanguageServer(SolidLanguageServer): ), ] ) - vts_ls_dir = os.path.join(cls.ls_resources_dir(), "vts-lsp") + vts_ls_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "vts-lsp") vts_executable_path = os.path.join(vts_ls_dir, "vtsls") # Verify both node and npm are installed diff --git a/src/solidlsp/ls.py b/src/solidlsp/ls.py index e47e83ca..873213e0 100644 --- a/src/solidlsp/ls.py +++ b/src/solidlsp/ls.py @@ -119,8 +119,8 @@ class SolidLanguageServer(ABC): config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, - solidlsp_settings: SolidLSPSettings, timeout: float | None = None, + solidlsp_settings: SolidLSPSettings | None = None, ) -> "SolidLanguageServer": """ Creates a language specific LanguageServer instance based on the given configuration, and appropriate settings for the programming language. @@ -135,6 +135,8 @@ class SolidLanguageServer(ABC): :return LanguageServer: A language specific LanguageServer instance. """ ls: SolidLanguageServer + if solidlsp_settings is None: + solidlsp_settings = SolidLSPSettings() if config.code_language == Language.PYTHON: from solidlsp.language_servers.pyright_server import ( diff --git a/test/conftest.py b/test/conftest.py index 90e522d0..849af543 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -4,11 +4,13 @@ from pathlib import Path import pytest from sensai.util.logging import configure +from serena.constants import SERENA_MANAGED_DIR_IN_HOME from serena.project import Project from serena.util.file_system import GitignoreParser from solidlsp.ls import SolidLanguageServer from solidlsp.ls_config import Language, LanguageServerConfig from solidlsp.ls_logger import LanguageServerLogger +from solidlsp.settings import SolidLSPSettings configure(level=logging.ERROR) @@ -43,7 +45,9 @@ def create_ls( ignored_paths.extend(spec.patterns) config = LanguageServerConfig(code_language=language, ignored_paths=ignored_paths, trace_lsp_communication=trace_lsp_communication) logger = LanguageServerLogger(log_level=log_level) - return SolidLanguageServer.create(config, logger, repo_path) + return SolidLanguageServer.create( + config, logger, repo_path, solidlsp_settings=SolidLSPSettings(solidlsp_dir=SERENA_MANAGED_DIR_IN_HOME) + ) def create_default_ls(language: Language) -> SolidLanguageServer: diff --git a/test/solidlsp/csharp/test_csharp_basic.py b/test/solidlsp/csharp/test_csharp_basic.py index 59f393ac..89d3caea 100644 --- a/test/solidlsp/csharp/test_csharp_basic.py +++ b/test/solidlsp/csharp/test_csharp_basic.py @@ -13,6 +13,7 @@ from solidlsp.language_servers.csharp_language_server import ( ) from solidlsp.ls_config import Language, LanguageServerConfig from solidlsp.ls_utils import SymbolUtils +from solidlsp.settings import SolidLSPSettings @pytest.mark.csharp @@ -214,7 +215,9 @@ class TestCSharpSolutionProjectOpening: mock_config.ignored_paths = [] # Create CSharpLanguageServer instance - CSharpLanguageServer(mock_config, mock_logger, str(temp_path)) + mock_settings = Mock(spec=SolidLSPSettings) + mock_settings.ls_resources_dir = "/tmp/test_ls_resources" + CSharpLanguageServer(mock_config, mock_logger, str(temp_path), mock_settings) # Verify that logger was called with solution file discovery mock_logger.log.assert_any_call(f"Found solution/project file: {solution_file}", 20) # logging.INFO @@ -236,7 +239,9 @@ class TestCSharpSolutionProjectOpening: mock_config.ignored_paths = [] # Create CSharpLanguageServer instance - CSharpLanguageServer(mock_config, mock_logger, str(temp_path)) + mock_settings = Mock(spec=SolidLSPSettings) + mock_settings.ls_resources_dir = "/tmp/test_ls_resources" + CSharpLanguageServer(mock_config, mock_logger, str(temp_path), mock_settings) # Verify that logger was called with warning about no solution/project files mock_logger.log.assert_any_call(