fix(java): show Lombok generated members in Structure (#2046)

Refs #2026

The Java defaults left JDT LS's generated-symbol filter on, so Lombok getters, setters, constructors, builder methods and logger fields were missing from Structure and File Structure. Enable `java.symbols.includeGeneratedCode`; generated entries now appear and navigate to their field or annotation. Adds a real-JDT LS regression test (manual, ignored by default).
Цей коміт міститься в:
l0ng-ai authored and GitHub committed 2026-11-08 02:40:20 +08:00
1 джерело bb99c7c4d1
коміт 27e73ea2cb
3 files changed
+95

No files matched your search

+28
Переглянути файл
@@ -0,0 +1,28 @@
package demo;
@lombok.Data
@lombok.Builder
class User {
private String name;
private int age;
}
@lombok.Getter
@lombok.Setter
@lombok.RequiredArgsConstructor
class Profile {
private final String id;
private String name;
}
@lombok.extern.java.Log
class Logged {
void write() { log.info("hello"); }
}
class PlainUser {
private String name;
PlainUser(String name) { this.name = name; }
String getName() { return name; }
void setName(String name) { this.name = name; }
}
+66
Переглянути файл
@@ -112,6 +112,72 @@ async fn kmp_lsp_java_end_to_end() {
tokio::time::timeout(Duration::from_secs(10), mgr.shutdown_all()).await.unwrap();
}
#[tokio::test(flavor = "multi_thread")]
#[ignore = "requires jdtls on PATH and a compatible JDK"]
async fn lombok_generated_members_appear_in_document_symbols() {
let dir = tempfile::tempdir().unwrap();
let root = dunce::canonicalize(dir.path()).unwrap();
let source = include_str!("fixtures/LombokSymbols.java");
let path = root.join("src/demo/LombokSymbols.java");
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
std::fs::write(&path, source).unwrap();
let agent = dunce::canonicalize(
Path::new(env!("CARGO_MANIFEST_DIR")).join("../../java/lombok/lombok-1.18.48-openidea.3.jar"),
)
.unwrap();
std::fs::write(
root.join(".project"),
"<projectDescription><name>lombok-symbols</name><buildSpec><buildCommand>\
<name>org.eclipse.jdt.core.javabuilder</name></buildCommand></buildSpec><natures>\
<nature>org.eclipse.jdt.core.javanature</nature></natures></projectDescription>",
)
.unwrap();
let library = agent.to_string_lossy().replace('&', "&amp;").replace('"', "&quot;").replace('<', "&lt;");
std::fs::write(
root.join(".classpath"),
format!(
"<classpath><classpathentry kind=\"src\" path=\"src\"/>\
<classpathentry kind=\"con\" path=\"org.eclipse.jdt.launching.JRE_CONTAINER\"/>\
<classpathentry kind=\"lib\" path=\"{library}\"/>\
<classpathentry kind=\"output\" path=\"bin\"/></classpath>"
),
)
.unwrap();
let mut java = LanguageRegistry::load(None).unwrap().get(&LanguageId::new("java")).unwrap();
java.language_servers.retain(|s| s.name == "jdtls");
let server = &mut java.language_servers[0];
if let Ok(bin) = std::env::var("OPENIDEA_TEST_JDTLS") {
server.command = bin;
}
server.args.extend([
"-data".into(),
root.join("workspace").to_string_lossy().into_owned(),
format!("--jvm-arg=-javaagent:{}", agent.display()),
]);
let (mgr, _) = manager(&root, LanguageRegistry::from_configs(vec![java]));
let doc = DocId::next();
mgr.did_open(doc, &path, &LanguageId::new("java"), 1, source);
let expected: &[(&str, &[&str])] = &[
("User", &["getName()", "setName(String)", "getAge()", "setAge(int)", "User(String, int)", "builder()"]),
("UserBuilder", &["name(String)", "age(int)", "build()"]),
("Profile", &["Profile(String)", "getId()", "getName()", "setName(String)"]),
("Logged", &["log", "write()"]),
("PlainUser", &["PlainUser(String)", "getName()", "setName(String)"]),
];
fn has_members(items: &[ide_core::OutlineItem], owner: &str, names: &[&str]) -> bool {
items.iter().any(|item| {
(item.name == owner && names.iter().all(|n| item.children.iter().any(|c| c.name == *n)))
|| has_members(&item.children, owner, names)
})
}
retry("Lombok document symbols", Duration::from_secs(120), || async {
let items = mgr.document_symbols(doc).await.ok().flatten()?;
expected.iter().all(|(owner, names)| has_members(&items, owner, names)).then_some(())
})
.await;
tokio::time::timeout(Duration::from_secs(10), mgr.shutdown_all()).await.unwrap();
}
#[tokio::test(flavor = "multi_thread")]
#[ignore = "requires jdtls on PATH and a compatible JDK"]
async fn intellij_java_formatter_preserves_manual_breaks_and_wraps_long_lines() {
+1
Переглянути файл
@@ -44,6 +44,7 @@ maven = { downloadSources = true, updateSnapshots = false }
eclipse = { downloadSources = true }
references = { includeDecompiledSources = true }
signatureHelp = { enabled = true }
symbols = { includeGeneratedCode = true }
configuration = { updateBuildConfiguration = "automatic" }
project = { referencedLibraries = ["lib/**/*.jar"] }
# Generated code (implement methods, getters, toString…) indents like the editor (`indent` above).