Skip to main content
Glama
groovy_language_server.py12.7 kB
""" Provides Groovy specific instantiation of the LanguageServer class. Contains various configurations and settings specific to Groovy. """ import dataclasses import logging import os import pathlib import shlex from solidlsp.ls import SolidLanguageServer from solidlsp.ls_config import Language, LanguageServerConfig 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 log = logging.getLogger(__name__) @dataclasses.dataclass class GroovyRuntimeDependencyPaths: """ Stores the paths to the runtime dependencies of Groovy Language Server """ java_path: str java_home_path: str ls_jar_path: str groovy_home_path: str | None = None class GroovyLanguageServer(SolidLanguageServer): """ Provides Groovy specific instantiation of the LanguageServer class. Contains various configurations and settings specific to Groovy. """ def __init__(self, config: LanguageServerConfig, repository_root_path: str, solidlsp_settings: SolidLSPSettings): """ Creates a Groovy Language Server instance. This class is not meant to be instantiated directly. Use LanguageServer.create() instead. """ runtime_dependency_paths = self._setup_runtime_dependencies(solidlsp_settings) self.runtime_dependency_paths = runtime_dependency_paths # Get jar options from configuration ls_jar_options = [] if solidlsp_settings.ls_specific_settings: groovy_settings = solidlsp_settings.get_ls_specific_settings(Language.GROOVY) jar_options_str = groovy_settings.get("ls_jar_options", "") if jar_options_str: ls_jar_options = shlex.split(jar_options_str) log.info(f"Using Groovy LS JAR options from configuration: {jar_options_str}") # Create command to execute the Groovy Language Server cmd = [self.runtime_dependency_paths.java_path, "-jar", self.runtime_dependency_paths.ls_jar_path] cmd.extend(ls_jar_options) # Set environment variables including JAVA_HOME proc_env = {"JAVA_HOME": self.runtime_dependency_paths.java_home_path} super().__init__( config, repository_root_path, ProcessLaunchInfo(cmd=cmd, env=proc_env, cwd=repository_root_path), "groovy", solidlsp_settings, ) log.info(f"Starting Groovy Language Server with jar options: {ls_jar_options}") @classmethod def _setup_runtime_dependencies(cls, solidlsp_settings: SolidLSPSettings) -> GroovyRuntimeDependencyPaths: """ Setup runtime dependencies for Groovy Language Server and return paths. """ platform_id = PlatformUtils.get_platform_id() # Verify platform support assert ( platform_id.value.startswith("win-") or platform_id.value.startswith("linux-") or platform_id.value.startswith("osx-") ), "Only Windows, Linux and macOS platforms are supported for Groovy in multilspy at the moment" # Check if user specified custom Java home path java_home_path = None java_path = None if solidlsp_settings and solidlsp_settings.ls_specific_settings: groovy_settings = solidlsp_settings.get_ls_specific_settings(Language.GROOVY) custom_java_home = groovy_settings.get("ls_java_home_path") if custom_java_home: log.info(f"Using custom Java home path from configuration: {custom_java_home}") java_home_path = custom_java_home # Determine java executable path based on platform if platform_id.value.startswith("win-"): java_path = os.path.join(java_home_path, "bin", "java.exe") else: java_path = os.path.join(java_home_path, "bin", "java") # If no custom Java home path, download and use bundled Java if java_home_path is None: # Runtime dependency information runtime_dependencies = { "java": { "win-x64": { "url": "https://github.com/redhat-developer/vscode-java/releases/download/v1.42.0/java-win32-x64-1.42.0-561.vsix", "archiveType": "zip", "java_home_path": "extension/jre/21.0.7-win32-x86_64", "java_path": "extension/jre/21.0.7-win32-x86_64/bin/java.exe", }, "linux-x64": { "url": "https://github.com/redhat-developer/vscode-java/releases/download/v1.42.0/java-linux-x64-1.42.0-561.vsix", "archiveType": "zip", "java_home_path": "extension/jre/21.0.7-linux-x86_64", "java_path": "extension/jre/21.0.7-linux-x86_64/bin/java", }, "linux-arm64": { "url": "https://github.com/redhat-developer/vscode-java/releases/download/v1.42.0/java-linux-arm64-1.42.0-561.vsix", "archiveType": "zip", "java_home_path": "extension/jre/21.0.7-linux-aarch64", "java_path": "extension/jre/21.0.7-linux-aarch64/bin/java", }, "osx-x64": { "url": "https://github.com/redhat-developer/vscode-java/releases/download/v1.42.0/java-darwin-x64-1.42.0-561.vsix", "archiveType": "zip", "java_home_path": "extension/jre/21.0.7-macosx-x86_64", "java_path": "extension/jre/21.0.7-macosx-x86_64/bin/java", }, "osx-arm64": { "url": "https://github.com/redhat-developer/vscode-java/releases/download/v1.42.0/java-darwin-arm64-1.42.0-561.vsix", "archiveType": "zip", "java_home_path": "extension/jre/21.0.7-macosx-aarch64", "java_path": "extension/jre/21.0.7-macosx-aarch64/bin/java", }, }, } java_dependency = runtime_dependencies["java"][platform_id.value] static_dir = os.path.join(cls.ls_resources_dir(solidlsp_settings), "groovy_language_server") os.makedirs(static_dir, exist_ok=True) java_dir = os.path.join(static_dir, "java") os.makedirs(java_dir, exist_ok=True) java_home_path = os.path.join(java_dir, java_dependency["java_home_path"]) java_path = os.path.join(java_dir, java_dependency["java_path"]) if not os.path.exists(java_path): log.info(f"Downloading Java for {platform_id.value}...") FileUtils.download_and_extract_archive(java_dependency["url"], java_dir, java_dependency["archiveType"]) if not platform_id.value.startswith("win-"): os.chmod(java_path, 0o755) assert java_path and os.path.exists(java_path), f"Java executable not found at {java_path}" ls_jar_path = cls._find_groovy_ls_jar(solidlsp_settings) return GroovyRuntimeDependencyPaths(java_path=java_path, java_home_path=java_home_path, ls_jar_path=ls_jar_path) @classmethod def _find_groovy_ls_jar(cls, solidlsp_settings: SolidLSPSettings) -> str: """ Find Groovy Language Server JAR file """ if solidlsp_settings and solidlsp_settings.ls_specific_settings: groovy_settings = solidlsp_settings.get_ls_specific_settings(Language.GROOVY) config_jar_path = groovy_settings.get("ls_jar_path") if config_jar_path and os.path.exists(config_jar_path): log.info(f"Using Groovy LS JAR from configuration: {config_jar_path}") return config_jar_path # if JAR not found raise RuntimeError( "Groovy Language Server JAR not found. To use Groovy language support:\n" "Set 'ls_jar_path' in groovy settings in serena_config.yml:\n" " ls_specific_settings:\n" " groovy:\n" " ls_jar_path: '/path/to/groovy-language-server.jar'\n" " Ensure the JAR file is available at the configured path\n" ) @staticmethod def _get_initialize_params(repository_absolute_path: str) -> InitializeParams: """ Returns the initialize params for the Groovy Language Server. """ if not os.path.isabs(repository_absolute_path): repository_absolute_path = os.path.abspath(repository_absolute_path) root_uri = pathlib.Path(repository_absolute_path).as_uri() initialize_params = { "clientInfo": {"name": "Serena Groovy Client", "version": "1.0.0"}, "rootPath": repository_absolute_path, "rootUri": root_uri, "capabilities": { "textDocument": { "synchronization": {"dynamicRegistration": True, "didSave": True}, "completion": {"dynamicRegistration": True}, "hover": {"dynamicRegistration": True, "contentFormat": ["markdown", "plaintext"]}, "definition": {"dynamicRegistration": True}, "references": {"dynamicRegistration": True}, "documentSymbol": {"dynamicRegistration": True}, "workspaceSymbol": {"dynamicRegistration": True}, "signatureHelp": {"dynamicRegistration": True}, "rename": {"dynamicRegistration": True}, }, "workspace": { "workspaceFolders": True, }, }, "initializationOptions": { "settings": { "groovy": { "classpath": [], "diagnostics": {"enabled": True}, "completion": {"enabled": True}, } }, }, "processId": os.getpid(), "workspaceFolders": [ { "uri": root_uri, "name": os.path.basename(repository_absolute_path), } ], } return initialize_params # type: ignore def _start_server(self) -> None: """ Starts the Groovy Language Server """ def execute_client_command_handler(params: dict) -> list: return [] def do_nothing(params: dict) -> None: return def window_log_message(msg: dict) -> None: log.info(f"LSP: window/logMessage: {msg}") self.server.on_request("client/registerCapability", do_nothing) self.server.on_notification("language/status", do_nothing) self.server.on_notification("window/logMessage", window_log_message) self.server.on_request("workspace/executeClientCommand", execute_client_command_handler) self.server.on_notification("$/progress", do_nothing) self.server.on_notification("textDocument/publishDiagnostics", do_nothing) self.server.on_notification("language/actionableNotification", do_nothing) log.info("Starting Groovy server process") self.server.start() initialize_params = self._get_initialize_params(self.repository_root_path) log.info("Sending initialize request from LSP client to LSP server and awaiting response") init_response = self.server.send.initialize(initialize_params) capabilities = init_response["capabilities"] assert "textDocumentSync" in capabilities, "Server must support textDocumentSync" assert "hoverProvider" in capabilities, "Server must support hover" assert "completionProvider" in capabilities, "Server must support code completion" assert "signatureHelpProvider" in capabilities, "Server must support signature help" assert "definitionProvider" in capabilities, "Server must support go to definition" assert "referencesProvider" in capabilities, "Server must support find references" assert "documentSymbolProvider" in capabilities, "Server must support document symbols" assert "workspaceSymbolProvider" in capabilities, "Server must support workspace symbols" self.server.notify.initialized({}) self.completions_available.set()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/oraios/serena'

If you have feedback or need assistance with the MCP directory API, please join our Discord server