mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-06 16:16:56 +00:00
feat(jdtls): surface Lombok-generated methods in document symbols, bump jdtls version (#1434)
* feat(jdtls): surface Lombok-generated methods in document symbols JDTLS' DocumentSymbolHandler filtered out every SourceMethod where JDTUtils.isGenerated() was true, so Lombok-synthesised methods (getX/setX, builder(), equals/hashCode/toString, withX, fluent accessors, ...) never reached the LSP client. As a result Serena's symbol-aware tools — find_symbol, get_symbols_overview, replace_symbol_body, insert_before_symbol, insert_after_symbol — could not see, address or edit any Lombok-generated member; only search_for_pattern / replace_content (text-based) worked. Upstream introduced an opt-in preference java.symbols.includeGeneratedCode in eclipse-jdtls/eclipse.jdt.ls#3706 (merged 2026-02-24) and surfaced it through redhat-developer/vscode-java#4335. First vscode-java release with the new JDTLS build is v1.53.0 (2026-02-26). Serena was pinned to v1.42.0-561, well before the fix existed. Changes: - New ls_specific_settings.java.lombok_show_generated setting (default true); forwarded to JDTLS as java.symbols.includeGeneratedCode in initialize params. Older servers ignore the unknown preference key silently. - Bump bundled vscode-java DEFAULT 1.42.0-561 -> 1.54.0-923 (brings JRE 21.0.10, Lombok 1.18.39 and Equinox launcher 1.7.100). INITIAL stays at 1.42.0-561, so per the per-version install-dir convention from #1438 the new build lands in vscode-java-1.54.0-923/ while legacy vscode-java/ caches and any explicit vscode_java_version: '1.42.0-561' override keep working. - New VsixResourcePaths dataclass + INITIAL/DEFAULT_VSCODE_JAVA_PATHS pin the JRE / Lombok / launcher filenames *inside* the VSIX. Without this, bumping the archive would break users on legacy 1.42.0-561 because resource paths inside the archive change between releases. Resolution mirrors SHA pinning: known versions get their pinned paths; any other version raises SolidLSPException with a pointer to upstream-jdtls mode (which derives paths dynamically and needs no pinning). - Drop dead 'static/vscode-java/...' placeholder in initialize params; the real runtimes[] is overwritten below from runtime_dependency_paths .jre_home_path, which is correct in both default-VSIX and upstream-jdtls modes. - Test fixtures: Lombok provided dep in test_repo/pom.xml plus LombokModel / FluentLombokModel / DefaultGreeter covering @Data, @Builder (toBuilder=true), @With, @Delegate, @AllArgsConstructor, @NoArgsConstructor and @Accessors(fluent=true). Regression test in test_java_basic.py asserts every generated-method shape lands in document symbols. Closes #1432
This commit is contained in:
1 parent
3122384822
commit
ba6170bab1
8 files changed
+229
-35
No files matched your search
@@ -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)}"
|
||||
Reference in new issue
Block a user