diff --git a/src/solidlsp/language_servers/eclipse_jdtls.py b/src/solidlsp/language_servers/eclipse_jdtls.py index 5ebb378c..3ac80046 100644 --- a/src/solidlsp/language_servers/eclipse_jdtls.py +++ b/src/solidlsp/language_servers/eclipse_jdtls.py @@ -44,7 +44,9 @@ class EclipseJDTLS(SolidLanguageServer): The EclipseJDTLS class provides a Java specific implementation of the LanguageServer class """ - 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 new EclipseJDTLS instance initializing the language server settings appropriately. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. @@ -55,7 +57,7 @@ class EclipseJDTLS(SolidLanguageServer): # ws_dir is the workspace directory for the EclipseJDTLS server ws_dir = str( PurePath( - SolidLSPSettings.get_language_server_directory(), + solidlsp_settings.ls_resources_dir, "EclipseJDTLS", "workspaces", uuid.uuid4().hex, @@ -63,15 +65,15 @@ class EclipseJDTLS(SolidLanguageServer): ) # shared_cache_location is the global cache used by Eclipse JDTLS across all workspaces - shared_cache_location = str(PurePath(SolidLSPSettings.get_global_cache_directory(), "lsp", "EclipseJDTLS", "sharedIndex")) + shared_cache_location = str(PurePath(solidlsp_settings.ls_resources_dir, "lsp", "EclipseJDTLS", "sharedIndex")) + os.makedirs(shared_cache_location, exist_ok=True) + os.makedirs(ws_dir, exist_ok=True) jre_path = self.runtime_dependency_paths.jre_path lombok_jar_path = self.runtime_dependency_paths.lombok_jar_path jdtls_launcher_jar = self.runtime_dependency_paths.jdtls_launcher_jar_path - os.makedirs(ws_dir, exist_ok=True) - data_dir = str(PurePath(ws_dir, "data_dir")) jdtls_config_path = str(PurePath(ws_dir, "config_path")) @@ -132,7 +134,9 @@ class EclipseJDTLS(SolidLanguageServer): self.intellicode_enable_command_available = threading.Event() self.initialize_searcher_command_available = threading.Event() - super().__init__(config, logger, repository_root_path, ProcessLaunchInfo(cmd, proc_env, proc_cwd), "java") + super().__init__( + config, logger, repository_root_path, ProcessLaunchInfo(cmd, proc_env, proc_cwd), "java", solidlsp_settings=solidlsp_settings + ) @override def is_ignored_dirname(self, dirname: str) -> bool: diff --git a/src/solidlsp/ls.py b/src/solidlsp/ls.py index 6c67f574..e47e83ca 100644 --- a/src/solidlsp/ls.py +++ b/src/solidlsp/ls.py @@ -35,6 +35,7 @@ from solidlsp.lsp_protocol_handler.server import ( ProcessLaunchInfo, StringDict, ) +from solidlsp.settings import SolidLSPSettings GenericDocumentSymbol = Union[LSPTypes.DocumentSymbol, LSPTypes.SymbolInformation, ls_types.UnifiedSymbolInformation] @@ -90,14 +91,14 @@ class SolidLanguageServer(ABC): return dirname.startswith(".") @classmethod - def ls_resources_dir(cls, mkdir: bool = True) -> str: + def ls_resources_dir(cls, solidlsp_settings: SolidLSPSettings, mkdir: bool = True) -> str: """ Returns the directory where the language server resources are downloaded. This is used to store language server binaries, configuration files, etc. """ - from serena.constants import SERENA_MANAGED_DIR_IN_HOME - - result = os.path.join(SERENA_MANAGED_DIR_IN_HOME, "language_servers", "static", cls.__name__) + if solidlsp_settings is None: + solidlsp_settings = SolidLSPSettings() + result = os.path.join(solidlsp_settings.ls_resources_dir, cls.__name__) # Migration of previously downloaded LS resources that were downloaded to a subdir of solidlsp instead of to the user's home pre_migration_ls_resources_dir = os.path.join(os.path.dirname(__file__), "language_servers", "static", cls.__name__) @@ -114,7 +115,12 @@ class SolidLanguageServer(ABC): @classmethod def create( - cls, config: LanguageServerConfig, logger: LanguageServerLogger, repository_root_path: str, timeout: float | None = None + cls, + config: LanguageServerConfig, + logger: LanguageServerLogger, + repository_root_path: str, + solidlsp_settings: SolidLSPSettings, + timeout: float | None = None, ) -> "SolidLanguageServer": """ Creates a language specific LanguageServer instance based on the given configuration, and appropriate settings for the programming language. @@ -135,90 +141,90 @@ class SolidLanguageServer(ABC): PyrightServer, ) - ls = PyrightServer(config, logger, repository_root_path) + ls = PyrightServer(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.PYTHON_JEDI: from solidlsp.language_servers.jedi_server import JediServer - ls = JediServer(config, logger, repository_root_path) + ls = JediServer(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.JAVA: from solidlsp.language_servers.eclipse_jdtls import ( EclipseJDTLS, ) - ls = EclipseJDTLS(config, logger, repository_root_path) + ls = EclipseJDTLS(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.KOTLIN: from solidlsp.language_servers.kotlin_language_server import ( KotlinLanguageServer, ) - ls = KotlinLanguageServer(config, logger, repository_root_path) + ls = KotlinLanguageServer(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.RUST: from solidlsp.language_servers.rust_analyzer import ( RustAnalyzer, ) - ls = RustAnalyzer(config, logger, repository_root_path) + ls = RustAnalyzer(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.CSHARP: from solidlsp.language_servers.csharp_language_server import CSharpLanguageServer - ls = CSharpLanguageServer(config, logger, repository_root_path) + ls = CSharpLanguageServer(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.CSHARP_OMNISHARP: - from solidlsp.language_servers.omnisharp.omnisharp import OmniSharp + from solidlsp.language_servers.omnisharp import OmniSharp - ls = OmniSharp(config, logger, repository_root_path) + ls = OmniSharp(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.TYPESCRIPT: from solidlsp.language_servers.typescript_language_server import ( TypeScriptLanguageServer, ) - ls = TypeScriptLanguageServer(config, logger, repository_root_path) + ls = TypeScriptLanguageServer(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.TYPESCRIPT_VTS: # VTS based Language Server implementation, need to experiment to see if it improves performance from solidlsp.language_servers.vts_language_server import VtsLanguageServer - ls = VtsLanguageServer(config, logger, repository_root_path) + ls = VtsLanguageServer(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.GO: from solidlsp.language_servers.gopls import Gopls - ls = Gopls(config, logger, repository_root_path) + ls = Gopls(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.RUBY: from solidlsp.language_servers.solargraph import Solargraph - ls = Solargraph(config, logger, repository_root_path) + ls = Solargraph(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.DART: from solidlsp.language_servers.dart_language_server import DartLanguageServer - ls = DartLanguageServer(config, logger, repository_root_path) + ls = DartLanguageServer(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.CPP: from solidlsp.language_servers.clangd_language_server import ClangdLanguageServer - ls = ClangdLanguageServer(config, logger, repository_root_path) + ls = ClangdLanguageServer(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.PHP: from solidlsp.language_servers.intelephense import Intelephense - ls = Intelephense(config, logger, repository_root_path) + ls = Intelephense(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.CLOJURE: from solidlsp.language_servers.clojure_lsp import ClojureLSP - ls = ClojureLSP(config, logger, repository_root_path) + ls = ClojureLSP(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.ELIXIR: from solidlsp.language_servers.elixir_tools.elixir_tools import ElixirTools - ls = ElixirTools(config, logger, repository_root_path) + ls = ElixirTools(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) elif config.code_language == Language.TERRAFORM: from solidlsp.language_servers.terraform_ls import TerraformLS - ls = TerraformLS(config, logger, repository_root_path) + ls = TerraformLS(config, logger, repository_root_path, solidlsp_settings=solidlsp_settings) else: logger.log(f"Language {config.code_language} is not supported", logging.ERROR) @@ -234,6 +240,7 @@ class SolidLanguageServer(ABC): repository_root_path: str, process_launch_info: ProcessLaunchInfo, language_id: str, + solidlsp_settings: SolidLSPSettings, ): """ Initializes a LanguageServer instance. @@ -248,6 +255,7 @@ class SolidLanguageServer(ABC): The command must pass appropriate flags to the binary, so that it runs in the stdio mode, as opposed to HTTP, TCP modes supported by some language servers. """ + self._solidlsp_settings = solidlsp_settings self.logger = logger self.repository_root_path: str = repository_root_path self.logger.log( diff --git a/src/solidlsp/settings.py b/src/solidlsp/settings.py index 38b30102..0b956bff 100644 --- a/src/solidlsp/settings.py +++ b/src/solidlsp/settings.py @@ -4,21 +4,17 @@ Defines settings for Solid-LSP import os import pathlib +from dataclasses import dataclass +@dataclass class SolidLSPSettings: - @staticmethod - def get_language_server_directory() -> str: - """Returns the directory for language servers""" - user_home = pathlib.Path.home() - multilspy_dir = str(pathlib.PurePath(user_home, ".multilspy")) - lsp_dir = str(pathlib.PurePath(multilspy_dir, "lsp")) - os.makedirs(lsp_dir, exist_ok=True) - return lsp_dir + solidlsp_dir: str = str(pathlib.Path.home() / ".solidlsp") - @staticmethod - def get_global_cache_directory() -> str: - """Returns the cache directory""" - global_cache_dir = os.path.join(str(pathlib.Path.home()), ".multilspy", "global_cache") - os.makedirs(global_cache_dir, exist_ok=True) - return global_cache_dir + def __post_init__(self): + os.makedirs(str(self.solidlsp_dir), exist_ok=True) + os.makedirs(str(self.ls_resources_dir), exist_ok=True) + + @property + def ls_resources_dir(self): + return os.path.join(str(self.solidlsp_dir), "language_servers", "static")