diff --git a/CHANGELOG.md b/CHANGELOG.md
index fb76d126..473f2625 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,7 @@ Status of the `main` branch. Changes prior to the next official version change w
* Language Servers:
- Elixir (`elixir-tools/next-ls`): Fix deadlock in monorepo projects where `mix.exs` lives in a subdirectory. The server now searches immediate subdirectories when no `mix.exs` is found at the repository root. #1444
- Java (`eclipse.jdt.ls`): Add upstream JDTLS mode for offline / restricted-network use. Setting both `jdtls_path` and `lombok_path` in `ls_specific_settings.java` makes Serena use an existing upstream JDTLS installation (e.g. `brew install jdtls`) and the system JDK 21+, skipping the ~500 MB vscode-java VSIX, Gradle, and IntelliCode downloads. New related setting `java_home` lets the user override the JDK used to launch JDTLS. Default behavior unchanged — the JDTLS workspace hash is preserved bit-for-bit for users on the default route, so existing project caches are reused without a one-time reindex; the launcher path is mixed into the hash only when `jdtls_path` is set, isolating upstream installations from the default workspace. #1415
+ - Java (eclipse.jdt.ls): Lombok-generated methods (getters/setters, builder(), equals/hashCode/toString, etc.) are now included in symbol-based tools (find_symbol, get_symbols_overview, edits). Added lombok_show_generated setting (default: on) to toggle this. Updated bundled vscode-java to 1.54.0-923. Issue #1432.
- Add **Angular** (experimental) via a dual-server architecture: `@angular/language-server` (ngserver) handles standalone `.html` template files, while a companion `typescript-language-server` with `@angular/language-service` loaded as a tsserver plugin handles all `.ts` operations including inline templates. Provides type-aware navigation between templates and component classes. Requires Node.js, npm, and `@angular/core` installed in the project (`npm install` in the project root). Subsumes `typescript`+`html` for `.ts`/`.html` files when active; SCSS is not subsumed.
- Add **HTML** (experimental) using `vscode-html-language-server` from the `vscode-langservers-extracted` npm package. Provides in-file element/id symbols via documentSymbol; cross-file references are not meaningful for HTML. Also used as a companion server by the Angular LS for plain HTML documentSymbol support.
- Add **SCSS / Sass / CSS** (experimental) using [some-sass-language-server](https://github.com/wkillerud/some-sass). Handles `.scss`, `.sass`, and `.css` through one server, with full `@use`/`@forward` workspace-wide go-to-definition and find-references for variables, mixins, and functions across Sass files. The `.css` path uses the same `vscode-css-languageservice` engine that powers the standalone CSS LS; CSS feature toggles default off upstream and are flipped on at startup so symbols, hover, completion, and syntax-level diagnostics work for plain CSS as well.
diff --git a/docs/02-usage/050_configuration.md b/docs/02-usage/050_configuration.md
index 99388485..c1183b05 100644
--- a/docs/02-usage/050_configuration.md
+++ b/docs/02-usage/050_configuration.md
@@ -589,8 +589,9 @@ The following settings are supported for the Java language server:
| `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. |
| `gradle_version` | `8.14.2` | (vscode-java mode only) Override the Gradle distribution version Serena downloads by default. |
-| `vscode_java_version` | `1.42.0-561` | (vscode-java mode only) Override the bundled `vscode-java` runtime bundle version Serena downloads by default. |
+| `vscode_java_version` | `1.54.0-923` | (vscode-java mode only) Override the bundled `vscode-java` runtime bundle version Serena downloads by default. |
| `intellicode_version` | `1.2.30` | (vscode-java mode only) Override the IntelliCode VSIX version Serena downloads by default. |
+| `lombok_show_generated` | `true` | Show Lombok-generated methods (`getX/setX`, `builder()`, `equals/hashCode/toString`, `withX`, fluent accessors) in `find_symbol`, `get_symbols_overview` and the symbol-edit tools. Set to `false` to restore the previous JDTLS default and hide the synthetic methods (e.g. when `@Data` classes pollute the outline with too many getters/setters). Requires JDTLS commit `b2d8952` / `vscode-java >= 1.53.0`; the bundled default already meets this. |
| `jdtls_xmx` | `3G` | Maximum heap size for the JDTLS server JVM. |
| `jdtls_xms` | `100m` | Initial heap size for the JDTLS server JVM. |
| `intellicode_xmx` | `1G` | (vscode-java mode only) Maximum heap size for the IntelliCode embedded JVM. |
@@ -613,7 +614,7 @@ Example: upstream-jdtls mode (offline / corporate network):
ls_specific_settings:
java:
jdtls_path: "/opt/homebrew/Cellar/jdtls/1.50.0/libexec"
- lombok_path: "/Users/me/.m2/repository/org/projectlombok/lombok/1.18.36/lombok-1.18.36.jar"
+ lombok_path: "/Users/me/.m2/repository/org/projectlombok/lombok/1.18.38/lombok-1.18.38.jar"
# java_home: "/opt/homebrew/opt/openjdk@21" # optional
```
diff --git a/src/solidlsp/language_servers/eclipse_jdtls.py b/src/solidlsp/language_servers/eclipse_jdtls.py
index 646174a5..5ab570a8 100644
--- a/src/solidlsp/language_servers/eclipse_jdtls.py
+++ b/src/solidlsp/language_servers/eclipse_jdtls.py
@@ -38,6 +38,7 @@ INTELLICODE_ALLOWED_HOSTS = (
"download.visualstudio.microsoft.com",
)
+
# Version pinning convention (read this before bumping anything below):
#
# INITIAL_* — the very first version we shipped runtime-dependency support for, paired with
@@ -62,6 +63,22 @@ INTELLICODE_ALLOWED_HOSTS = (
# custom_settings and the matching cached subdir is picked up without re-downloading.
# - INITIAL_* and DEFAULT_* hold identical literals when first introduced; they diverge on
# the first DEFAULT_* bump and stay independent thereafter.
+@dataclasses.dataclass(frozen=True)
+class VsixResourcePaths:
+ """
+ Paths to resources inside the vscode-java VSIX archive. These vary between vscode-java
+ releases (JRE bundle, Lombok jar, Equinox launcher all have versioned filenames inside
+ the VSIX), so we pin them per-version alongside SHA256 — bumping the VSIX version means
+ bumping these too. Without this, a user requesting a non-DEFAULT pinned version would
+ extract the right archive but then crash on FileNotFoundError trying to find the wrong
+ JRE / Lombok / launcher inside it.
+ """
+
+ jre_version: str # e.g. "21.0.7"; expanded to extension/jre/{jre_version}-{platform-suffix}
+ lombok_jar_basename: str # e.g. "lombok-1.18.36.jar"
+ equinox_launcher_basename: str # e.g. "org.eclipse.equinox.launcher_1.7.0.v20250424-1814.jar"
+
+
INITIAL_VSCODE_JAVA_VERSION = "1.42.0-561"
INITIAL_VSCODE_JAVA_SHA256_BY_PLATFORM = {
"osx-arm64": "bc00c2699d4b8d478eb9a1621db9d6d3a12ea0dcc247a9cd8040e8ac19c03933",
@@ -70,14 +87,26 @@ INITIAL_VSCODE_JAVA_SHA256_BY_PLATFORM = {
"linux-x64": "7660b7b527be6fda46a917966b34d828e7416d5cc84287b29b88e7b99c1737f9",
"win-x64": "ef195b45bd260976ad2e84618f4044b5d7248deed41d647573f0ee22c4233df3",
}
-DEFAULT_VSCODE_JAVA_VERSION = "1.42.0-561"
+INITIAL_VSCODE_JAVA_PATHS = VsixResourcePaths(
+ jre_version="21.0.7",
+ lombok_jar_basename="lombok-1.18.36.jar",
+ equinox_launcher_basename="org.eclipse.equinox.launcher_1.7.0.v20250424-1814.jar",
+)
+# Bumped from 1.42.0-561 to surface Lombok-generated methods (#1432); brings JDTLS commit b2d8952
+# (java.symbols.includeGeneratedCode), JRE 21.0.10, Lombok 1.18.39 and Equinox launcher 1.7.100.
+DEFAULT_VSCODE_JAVA_VERSION = "1.54.0-923"
DEFAULT_VSCODE_JAVA_SHA256_BY_PLATFORM = {
- "osx-arm64": "bc00c2699d4b8d478eb9a1621db9d6d3a12ea0dcc247a9cd8040e8ac19c03933",
- "osx-x64": "03ae1db1a22c15561a620f1b722d6797d35d4faaa7c4666dbe6ca2715089852f",
- "linux-arm64": "e15bc9b2a665d3453203402621b5441062aa41b0ec2d140661f439326fd248c1",
- "linux-x64": "7660b7b527be6fda46a917966b34d828e7416d5cc84287b29b88e7b99c1737f9",
- "win-x64": "ef195b45bd260976ad2e84618f4044b5d7248deed41d647573f0ee22c4233df3",
+ "osx-arm64": "c54c45cb0d2579d8e0a4ddeb24d4a9dd0b460d07d9366adea2b38a1da22a463c",
+ "osx-x64": "dfc98abc4e54165a78372e280242a039671729b1b03420608df3b10c6b629fb6",
+ "linux-arm64": "e2bb22c427d90da8dbb1afff72ff1e2dce38d50b76deb02d7bc313a330a1330c",
+ "linux-x64": "9d4b15da54e25a0192f9bac073f086c015397d3676623b68dbf83a5dbaf5132b",
+ "win-x64": "66f3914987edeccfee8a2558470e0fde4f8c4154232ff4baa5d73373ebc819d4",
}
+DEFAULT_VSCODE_JAVA_PATHS = VsixResourcePaths(
+ jre_version="21.0.10",
+ lombok_jar_basename="lombok-1.18.39-4050.jar",
+ equinox_launcher_basename="org.eclipse.equinox.launcher_1.7.100.v20251111-0406.jar",
+)
INITIAL_INTELLICODE_VERSION = "1.2.30"
INITIAL_INTELLICODE_SHA256 = "7f61a7f96d101cdf230f96821be3fddd8f890ebfefb3695d18beee43004ae251"
@@ -156,8 +185,16 @@ class EclipseJDTLS(SolidLanguageServer):
- jdtls_xms: Initial heap size for the JDTLS server JVM (default: "100m")
- intellicode_xmx: Maximum heap size for the IntelliCode embedded JVM (default: "1G")
- intellicode_xms: Initial heap size for the IntelliCode embedded JVM (default: "100m")
+ - lombok_show_generated: Show Lombok-generated methods (getX/setX/builder()/...) in document
+ symbols by sending java.symbols.includeGeneratedCode=true to JDTLS (default: true).
+ Set to false for @Data-heavy projects where the extra getters/setters are noise.
+ Requires JDTLS commit b2d8952+ (vscode-java >= 1.53.0); older servers ignore the
+ key silently. See eclipse-jdtls/eclipse.jdt.ls#3706 and serena #1432.
- gradle_version: Override the pinned Gradle distribution version downloaded by Serena
- - vscode_java_version: Override the pinned vscode-java runtime bundle version downloaded by Serena
+ - vscode_java_version: Override the pinned vscode-java runtime bundle version downloaded by Serena.
+ Pinned versions: "1.54.0-923" (default) and "1.42.0-561" (legacy / initial). Other versions
+ are not supported in default VSIX mode (the resource paths inside the archive change between
+ releases); use upstream-jdtls mode for arbitrary versions.
- intellicode_version: Override the pinned IntelliCode VSIX version downloaded by Serena
Example configuration for upstream JDTLS mode (no downloads, suitable for offline/corporate):
@@ -184,8 +221,9 @@ class EclipseJDTLS(SolidLanguageServer):
jdtls_xms: "100m" # initial heap size for the JDTLS server JVM
intellicode_xmx: "1G" # maximum heap size for the IntelliCode embedded JVM
intellicode_xms: "100m" # initial heap size for the IntelliCode embedded JVM
+ lombok_show_generated: true # show Lombok-generated methods in document symbols (default true)
gradle_version: "8.14.2"
- vscode_java_version: "1.42.0-561"
+ vscode_java_version: "1.54.0-923" # also accepts pinned legacy "1.42.0-561"
intellicode_version: "1.2.30"
```
"""
@@ -305,6 +343,23 @@ class EclipseJDTLS(SolidLanguageServer):
return DEFAULT_INTELLICODE_SHA256
return None
+ # Resolve internal VSIX paths (JRE / Lombok / launcher filenames). For pinned versions
+ # these are known; for any other user-supplied version we bail out — guessing would
+ # silently produce broken paths at JDTLS launch time, which is a worse UX than failing
+ # fast here with a pointer to upstream-JDTLS mode (which doesn't need pinned paths).
+ if vscode_java_version == INITIAL_VSCODE_JAVA_VERSION:
+ vsix_paths = INITIAL_VSCODE_JAVA_PATHS
+ elif vscode_java_version == DEFAULT_VSCODE_JAVA_VERSION:
+ vsix_paths = DEFAULT_VSCODE_JAVA_PATHS
+ else:
+ raise SolidLSPException(
+ f"Resource paths inside the vscode-java {vscode_java_version} VSIX are not pinned in serena "
+ f"(known: {INITIAL_VSCODE_JAVA_VERSION}, {DEFAULT_VSCODE_JAVA_VERSION}). "
+ f"Either remove the 'vscode_java_version' override (defaults to {DEFAULT_VSCODE_JAVA_VERSION}), "
+ f"or use upstream JDTLS mode by setting both 'jdtls_path' and 'lombok_path' in "
+ f"ls_specific_settings.java (no pinning required)."
+ )
+
runtime_dependencies: dict[str, dict[str, dict[str, object]]] = {
"gradle": {
"platform-agnostic": {
@@ -329,10 +384,10 @@ class EclipseJDTLS(SolidLanguageServer):
"relative_extraction_path": vscode_java_dirname,
"sha256": vscode_java_sha("osx-arm64"),
"allowed_hosts": VSCODE_JAVA_ALLOWED_HOSTS,
- "jre_home_path": "extension/jre/21.0.7-macosx-aarch64",
- "jre_path": "extension/jre/21.0.7-macosx-aarch64/bin/java",
- "lombok_jar_path": "extension/lombok/lombok-1.18.36.jar",
- "jdtls_launcher_jar_path": "extension/server/plugins/org.eclipse.equinox.launcher_1.7.0.v20250424-1814.jar",
+ "jre_home_path": f"extension/jre/{vsix_paths.jre_version}-macosx-aarch64",
+ "jre_path": f"extension/jre/{vsix_paths.jre_version}-macosx-aarch64/bin/java",
+ "lombok_jar_path": f"extension/lombok/{vsix_paths.lombok_jar_basename}",
+ "jdtls_launcher_jar_path": f"extension/server/plugins/{vsix_paths.equinox_launcher_basename}",
"jdtls_readonly_config_path": "extension/server/config_mac_arm",
},
"osx-x64": {
@@ -341,10 +396,10 @@ class EclipseJDTLS(SolidLanguageServer):
"relative_extraction_path": vscode_java_dirname,
"sha256": vscode_java_sha("osx-x64"),
"allowed_hosts": VSCODE_JAVA_ALLOWED_HOSTS,
- "jre_home_path": "extension/jre/21.0.7-macosx-x86_64",
- "jre_path": "extension/jre/21.0.7-macosx-x86_64/bin/java",
- "lombok_jar_path": "extension/lombok/lombok-1.18.36.jar",
- "jdtls_launcher_jar_path": "extension/server/plugins/org.eclipse.equinox.launcher_1.7.0.v20250424-1814.jar",
+ "jre_home_path": f"extension/jre/{vsix_paths.jre_version}-macosx-x86_64",
+ "jre_path": f"extension/jre/{vsix_paths.jre_version}-macosx-x86_64/bin/java",
+ "lombok_jar_path": f"extension/lombok/{vsix_paths.lombok_jar_basename}",
+ "jdtls_launcher_jar_path": f"extension/server/plugins/{vsix_paths.equinox_launcher_basename}",
"jdtls_readonly_config_path": "extension/server/config_mac",
},
"linux-arm64": {
@@ -353,10 +408,10 @@ class EclipseJDTLS(SolidLanguageServer):
"relative_extraction_path": vscode_java_dirname,
"sha256": vscode_java_sha("linux-arm64"),
"allowed_hosts": VSCODE_JAVA_ALLOWED_HOSTS,
- "jre_home_path": "extension/jre/21.0.7-linux-aarch64",
- "jre_path": "extension/jre/21.0.7-linux-aarch64/bin/java",
- "lombok_jar_path": "extension/lombok/lombok-1.18.36.jar",
- "jdtls_launcher_jar_path": "extension/server/plugins/org.eclipse.equinox.launcher_1.7.0.v20250424-1814.jar",
+ "jre_home_path": f"extension/jre/{vsix_paths.jre_version}-linux-aarch64",
+ "jre_path": f"extension/jre/{vsix_paths.jre_version}-linux-aarch64/bin/java",
+ "lombok_jar_path": f"extension/lombok/{vsix_paths.lombok_jar_basename}",
+ "jdtls_launcher_jar_path": f"extension/server/plugins/{vsix_paths.equinox_launcher_basename}",
"jdtls_readonly_config_path": "extension/server/config_linux_arm",
},
"linux-x64": {
@@ -365,10 +420,10 @@ class EclipseJDTLS(SolidLanguageServer):
"relative_extraction_path": vscode_java_dirname,
"sha256": vscode_java_sha("linux-x64"),
"allowed_hosts": VSCODE_JAVA_ALLOWED_HOSTS,
- "jre_home_path": "extension/jre/21.0.7-linux-x86_64",
- "jre_path": "extension/jre/21.0.7-linux-x86_64/bin/java",
- "lombok_jar_path": "extension/lombok/lombok-1.18.36.jar",
- "jdtls_launcher_jar_path": "extension/server/plugins/org.eclipse.equinox.launcher_1.7.0.v20250424-1814.jar",
+ "jre_home_path": f"extension/jre/{vsix_paths.jre_version}-linux-x86_64",
+ "jre_path": f"extension/jre/{vsix_paths.jre_version}-linux-x86_64/bin/java",
+ "lombok_jar_path": f"extension/lombok/{vsix_paths.lombok_jar_basename}",
+ "jdtls_launcher_jar_path": f"extension/server/plugins/{vsix_paths.equinox_launcher_basename}",
"jdtls_readonly_config_path": "extension/server/config_linux",
},
"win-x64": {
@@ -377,10 +432,10 @@ class EclipseJDTLS(SolidLanguageServer):
"relative_extraction_path": vscode_java_dirname,
"sha256": vscode_java_sha("win-x64"),
"allowed_hosts": VSCODE_JAVA_ALLOWED_HOSTS,
- "jre_home_path": "extension/jre/21.0.7-win32-x86_64",
- "jre_path": "extension/jre/21.0.7-win32-x86_64/bin/java.exe",
- "lombok_jar_path": "extension/lombok/lombok-1.18.36.jar",
- "jdtls_launcher_jar_path": "extension/server/plugins/org.eclipse.equinox.launcher_1.7.0.v20250424-1814.jar",
+ "jre_home_path": f"extension/jre/{vsix_paths.jre_version}-win32-x86_64",
+ "jre_path": f"extension/jre/{vsix_paths.jre_version}-win32-x86_64/bin/java.exe",
+ "lombok_jar_path": f"extension/lombok/{vsix_paths.lombok_jar_basename}",
+ "jdtls_launcher_jar_path": f"extension/server/plugins/{vsix_paths.equinox_launcher_basename}",
"jdtls_readonly_config_path": "extension/server/config_win",
},
},
@@ -883,6 +938,15 @@ class EclipseJDTLS(SolidLanguageServer):
intellicode_xmx = self._custom_settings.get("intellicode_xmx", "1G")
intellicode_xms = self._custom_settings.get("intellicode_xms", "100m")
+ # Lombok-generated symbols (getX/setX/builder()/equals/hashCode/toString/...): JDTLS filters
+ # these out of documentSymbol results by default. Without them, find_symbol/get_symbols_overview
+ # return only user-written sources, which breaks navigation around @Data/@Builder/@Getter/@Setter
+ # classes. Default to True so agentic workflows can find_symbol -> replace_symbol_body on generated
+ # members. Requires JDTLS commit b2d8952 or newer (vscode-java >= 1.53.0, or upstream JDTLS
+ # snapshot after 2026-02-24); older servers ignore the unknown preference key silently.
+ # See eclipse-jdtls/eclipse.jdt.ls#3706.
+ lombok_show_generated = self._custom_settings.get("lombok_show_generated", True)
+
# Gradle wrapper: default to False to preserve existing behaviour
gradle_wrapper_enabled = self._custom_settings.get("gradle_wrapper_enabled", False)
log.info(
@@ -1096,9 +1160,10 @@ class EclipseJDTLS(SolidLanguageServer):
"defaultMojoExecutionAction": "ignore",
},
"workspaceCacheLimit": 90,
- "runtimes": [
- {"name": "JavaSE-21", "path": "static/vscode-java/extension/jre/21.0.7-linux-x86_64", "default": True}
- ],
+ # Placeholder; the real `runtimes` array is overwritten below from
+ # self.runtime_dependency_paths.jre_home_path (works for both default
+ # VSIX mode and upstream-jdtls mode, which uses the system JDK).
+ "runtimes": [],
},
"trace": {"server": "verbose"},
"import": {
@@ -1162,7 +1227,11 @@ class EclipseJDTLS(SolidLanguageServer):
"references": {"includeAccessors": True, "includeDecompiledSources": True},
"typeHierarchy": {"lazyLoad": False},
"settings": {"url": None},
- "symbols": {"includeSourceMethodDeclarations": False},
+ "symbols": {
+ "includeSourceMethodDeclarations": False,
+ # Surface Lombok-generated methods in document symbols (#1432).
+ "includeGeneratedCode": lombok_show_generated,
+ },
"inlayHints": {"parameterNames": {"enabled": "literals", "exclusions": []}},
"codeAction": {"sortMembers": {"avoidVolatileChanges": True}},
"compile": {
diff --git a/test/resources/repos/java/test_repo/pom.xml b/test/resources/repos/java/test_repo/pom.xml
index 672f990e..facb5368 100644
--- a/test/resources/repos/java/test_repo/pom.xml
+++ b/test/resources/repos/java/test_repo/pom.xml
@@ -11,8 +11,18 @@
21
21
3.13.0
+ 1.18.38
-
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
@@ -22,6 +32,13 @@
21
21
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
diff --git a/test/resources/repos/java/test_repo/src/main/java/test_repo/DefaultGreeter.java b/test/resources/repos/java/test_repo/src/main/java/test_repo/DefaultGreeter.java
new file mode 100644
index 00000000..8ed25b1a
--- /dev/null
+++ b/test/resources/repos/java/test_repo/src/main/java/test_repo/DefaultGreeter.java
@@ -0,0 +1,13 @@
+package test_repo;
+
+class DefaultGreeter implements LombokModel.Greeter {
+ @Override
+ public String greet() {
+ return "hi";
+ }
+
+ @Override
+ public String farewell() {
+ return "bye";
+ }
+}
diff --git a/test/resources/repos/java/test_repo/src/main/java/test_repo/FluentLombokModel.java b/test/resources/repos/java/test_repo/src/main/java/test_repo/FluentLombokModel.java
new file mode 100644
index 00000000..8b448707
--- /dev/null
+++ b/test/resources/repos/java/test_repo/src/main/java/test_repo/FluentLombokModel.java
@@ -0,0 +1,14 @@
+package test_repo;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+/** Verifies prefix-stripped fluent accessors generated by @Accessors(fluent=true). */
+@Getter
+@Setter
+@Accessors(fluent = true)
+public class FluentLombokModel {
+ private String host;
+ private String tag;
+}
diff --git a/test/resources/repos/java/test_repo/src/main/java/test_repo/LombokModel.java b/test/resources/repos/java/test_repo/src/main/java/test_repo/LombokModel.java
new file mode 100644
index 00000000..f003d51a
--- /dev/null
+++ b/test/resources/repos/java/test_repo/src/main/java/test_repo/LombokModel.java
@@ -0,0 +1,27 @@
+package test_repo;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.With;
+import lombok.experimental.Delegate;
+
+@Data
+@Builder(toBuilder = true)
+@With
+@AllArgsConstructor
+@NoArgsConstructor
+public class LombokModel {
+ private String name;
+ private int age;
+
+ /** Lombok @Delegate forwards every method of Greeter to delegate.* (covers @Delegate generation). */
+ public interface Greeter {
+ String greet();
+ String farewell();
+ }
+
+ @Delegate
+ private final Greeter delegate = new DefaultGreeter();
+}
diff --git a/test/solidlsp/java/test_java_basic.py b/test/solidlsp/java/test_java_basic.py
index 4c50c3c4..b9b78d84 100644
--- a/test/solidlsp/java/test_java_basic.py
+++ b/test/solidlsp/java/test_java_basic.py
@@ -96,3 +96,55 @@ class TestJavaLanguageServer:
f"Found malformed symbols: {[format_symbol_for_assert(sym) for sym in malformed_symbols]}",
pytrace=False,
)
+
+ @pytest.mark.parametrize("language_server", [Language.JAVA], indirect=True)
+ def test_lombok_generated_methods_visible_by_default(self, language_server: SolidLanguageServer) -> None:
+ """Generated Lombok methods must appear in document symbols across the common annotations.
+
+ Default `lombok_show_generated=True` sends `java.symbols.includeGeneratedCode=true` to JDTLS,
+ which disables the SourceMethod-isGenerated filter in DocumentSymbolHandler. Without it,
+ find_symbol/get_symbols_overview cannot reach Lombok-synthesised methods at all (#1432).
+ Covers @Data, @Builder(toBuilder=true), @With, @AllArgsConstructor, @NoArgsConstructor,
+ @Delegate and @Accessors(fluent=true) — every method-generating annotation listed in the
+ issue plus fluent prefix-stripped accessors and @Delegate forwarders.
+ """
+
+ def _names_by_kind(doc, kind: int) -> set[str]:
+ return {sym.get("name") for sym in doc.get_all_symbols_and_roots()[0] if sym.get("kind") == kind}
+
+ SYMBOL_KIND_CLASS = 5
+ SYMBOL_KIND_METHOD = 6
+ SYMBOL_KIND_CONSTRUCTOR = 9
+
+ # ---- LombokModel: @Data + @Builder(toBuilder=true) + @With + ctors + @Delegate -------
+ lombok_path = os.path.join("src", "main", "java", "test_repo", "LombokModel.java")
+ lombok_doc = language_server.request_document_symbols(lombok_path)
+
+ lombok_methods = _names_by_kind(lombok_doc, SYMBOL_KIND_METHOD)
+ # @Data getters/setters (prefixed) + canonical Object overrides
+ for expected in ("getName", "getAge", "setName", "setAge", "equals", "hashCode", "toString"):
+ assert expected in lombok_methods, f"@Data did not surface {expected!r}; got: {sorted(lombok_methods)}"
+ # @Builder(toBuilder=true): static factory + instance toBuilder + inner build()
+ for expected in ("builder", "toBuilder", "build"):
+ assert expected in lombok_methods, f"@Builder did not surface {expected!r}; got: {sorted(lombok_methods)}"
+ # @With: copy-with methods
+ for expected in ("withName", "withAge"):
+ assert expected in lombok_methods, f"@With did not surface {expected!r}; got: {sorted(lombok_methods)}"
+ # @Delegate: forwarder methods for every method of the delegate target
+ for expected in ("greet", "farewell"):
+ assert expected in lombok_methods, f"@Delegate did not surface forwarder {expected!r}; got: {sorted(lombok_methods)}"
+
+ # @Builder generates an inner builder class
+ lombok_classes = _names_by_kind(lombok_doc, SYMBOL_KIND_CLASS)
+ assert "LombokModelBuilder" in lombok_classes, f"@Builder inner class missing; got: {sorted(lombok_classes)}"
+
+ # @AllArgsConstructor + @NoArgsConstructor surface as ctor symbols (kind=9)
+ lombok_ctors = _names_by_kind(lombok_doc, SYMBOL_KIND_CONSTRUCTOR)
+ assert "LombokModel" in lombok_ctors, f"Lombok ctors missing; got ctors {sorted(lombok_ctors)}"
+
+ # ---- FluentLombokModel: @Accessors(fluent=true) - prefix-stripped accessors ---------
+ fluent_path = os.path.join("src", "main", "java", "test_repo", "FluentLombokModel.java")
+ fluent_doc = language_server.request_document_symbols(fluent_path)
+ fluent_methods = _names_by_kind(fluent_doc, SYMBOL_KIND_METHOD)
+ for expected in ("host", "tag"):
+ assert expected in fluent_methods, f"@Accessors(fluent=true) did not surface {expected!r}; got: {sorted(fluent_methods)}"