diff --git a/docs/02-usage/050_configuration.md b/docs/02-usage/050_configuration.md index 85bad8d4..aa34c3e8 100644 --- a/docs/02-usage/050_configuration.md +++ b/docs/02-usage/050_configuration.md @@ -281,6 +281,27 @@ Notes: - `GOFLAGS` (from the environment you start Serena in) may also affect the Go build context. Prefer `buildFlags` for tags. - Build context changes are only picked up when `gopls` starts. After changing `gopls_settings` (or relevant env vars like `GOFLAGS`), restart the Serena process (or server) that hosts the Go language server, or use your client's "Restart language server" action if it causes `gopls` to restart. +#### Java (`eclipse.jdt.ls`) + +The following settings are supported for the Java language server: + +| Setting | Default | Description | +|---|---|---| +| `maven_user_settings` | `~/.m2/settings.xml` | Path to Maven `settings.xml` | +| `gradle_user_home` | `~/.gradle` | Path to Gradle user home directory | +| `gradle_wrapper_enabled` | `false` | Use the project's Gradle wrapper (`gradlew`) instead of the bundled Gradle distribution. Enable this for projects with custom plugins or repositories. | +| `gradle_java_home` | `null` | Path to the JDK used by Gradle. When unset, Gradle uses the bundled JRE. | +| `use_system_java_home` | `false` | Use the system's `JAVA_HOME` environment variable for JDTLS itself. Enable this if your project requires a specific JDK vendor or version for Gradle's JDK checks. | + +Example for a project with custom Gradle plugins and JDK requirements: + +```yaml +ls_specific_settings: + java: + gradle_wrapper_enabled: true + use_system_java_home: true +``` + #### Kotlin Serena uses [JetBrains' Kotlin Language Server](https://github.com/Kotlin/kotlin-lsp) for Kotlin support. diff --git a/src/solidlsp/language_servers/eclipse_jdtls.py b/src/solidlsp/language_servers/eclipse_jdtls.py index 773776d9..09a3c32a 100644 --- a/src/solidlsp/language_servers/eclipse_jdtls.py +++ b/src/solidlsp/language_servers/eclipse_jdtls.py @@ -49,8 +49,9 @@ class EclipseJDTLS(SolidLanguageServer): You can configure the following options in ls_specific_settings (in serena_config.yml): - maven_user_settings: Path to Maven settings.xml file (default: ~/.m2/settings.xml) - gradle_user_home: Path to Gradle user home directory (default: ~/.gradle) - - Note: Gradle wrapper is disabled by default. Projects will use the bundled Gradle distribution. + - gradle_wrapper_enabled: Whether to use the project's Gradle wrapper (default: false) + - gradle_java_home: Path to JDK for Gradle (default: null, uses bundled JRE) + - use_system_java_home: Whether to use the system's JAVA_HOME for JDTLS itself (default: false) Example configuration in ~/.serena/serena_config.yml: ```yaml @@ -60,6 +61,9 @@ class EclipseJDTLS(SolidLanguageServer): # maven_user_settings: 'C:\\Users\\YourName\\.m2\\settings.xml' # Windows (use single quotes!) gradle_user_home: "/home/user/.gradle" # Unix/Linux/Mac # gradle_user_home: 'C:\\Users\\YourName\\.gradle' # Windows (use single quotes!) + gradle_wrapper_enabled: true # set to true for projects with custom plugins/repositories + gradle_java_home: "/path/to/jdk" # set to override Gradle's JDK + use_system_java_home: true # set to true to use system JAVA_HOME for JDTLS ``` """ @@ -346,7 +350,17 @@ class EclipseJDTLS(SolidLanguageServer): return cmd def create_launch_command_env(self) -> dict[str, str]: - return {"syntaxserver": "false", "JAVA_HOME": self.runtime_dependency_paths.jre_home_path} + use_system_java_home = self._custom_settings.get("use_system_java_home", False) + if use_system_java_home: + system_java_home = os.environ.get("JAVA_HOME") + if system_java_home: + log.info(f"Using system JAVA_HOME for JDTLS: {system_java_home}") + return {"syntaxserver": "false", "JAVA_HOME": system_java_home} + else: + log.warning("use_system_java_home is set but JAVA_HOME is not set in environment, falling back to bundled JRE") + java_home = self.runtime_dependency_paths.jre_home_path + log.info(f"Using bundled JRE for JDTLS: {java_home}") + return {"syntaxserver": "false", "JAVA_HOME": java_home} def _get_initialize_params(self, repository_absolute_path: str) -> InitializeParams: """ @@ -404,6 +418,27 @@ class EclipseJDTLS(SolidLanguageServer): gradle_user_home = None log.info(f"Gradle user home not found at default location ({default_gradle_home}), will use JDTLS defaults") + # Gradle wrapper: default to False to preserve existing behaviour + gradle_wrapper_enabled = self._custom_settings.get("gradle_wrapper_enabled", False) + log.info( + f"Gradle wrapper {'enabled' if gradle_wrapper_enabled else 'disabled'} (configurable via ls_specific_settings -> java -> gradle_wrapper_enabled)" + ) + + # Gradle Java home: default to None, which means the bundled JRE is used + gradle_java_home = self._custom_settings.get("gradle_java_home") + if gradle_java_home is not None: + if not os.path.exists(gradle_java_home): + error_msg = ( + f"Gradle Java home not found: {gradle_java_home}. " + f"Fix: update path in ~/.serena/serena_config.yml (ls_specific_settings -> java -> gradle_java_home), " + f"or remove the setting to use the bundled JRE" + ) + log.error(error_msg) + raise FileNotFoundError(error_msg) + log.info(f"Using Gradle Java home from custom location: {gradle_java_home}") + else: + log.info(f"Using bundled JRE for Gradle: {self.runtime_dependency_paths.jre_path}") + initialize_params = { "locale": "en", "rootPath": repository_absolute_path, @@ -609,10 +644,9 @@ class EclipseJDTLS(SolidLanguageServer): }, "gradle": { "enabled": True, - "wrapper": {"enabled": False}, + "wrapper": {"enabled": gradle_wrapper_enabled}, "version": None, "home": "abs(static/gradle-7.3.3)", - "java": {"home": "abs(static/launch_jres/21.0.7-linux-x86_64)"}, "offline": {"enabled": False}, "arguments": None, "jvmArguments": None, @@ -719,7 +753,7 @@ class EclipseJDTLS(SolidLanguageServer): gradle_settings = initialize_params["initializationOptions"]["settings"]["java"]["import"]["gradle"] # type: ignore gradle_settings["home"] = self.runtime_dependency_paths.gradle_path - gradle_settings["java"]["home"] = self.runtime_dependency_paths.jre_path + gradle_settings["java"] = {"home": gradle_java_home if gradle_java_home is not None else self.runtime_dependency_paths.jre_path} return cast(InitializeParams, initialize_params) def _start_server(self) -> None: