fix(maven): refresh jdtls project configurations after a Maven reload (#446)

Reload All Maven Projects re-synced only the IDE's build model; jdtls kept its old import, so artifacts that became resolvable meanwhile (mvn install into ~/.m2) stayed missing until its workspace was cleared. After a successful Maven sync, jdtls now receives java/projectConfigurationsUpdate for every project's pom.xml (only if it is already running; failures are logged and don't fail the reload).

Fixes #436

Co-authored-by: a-rookie-of-C-language <[email protected]>
This commit is contained in:
arookieofcanda-rookie-of-C-language authored and GitHub committed 2026-10-30 19:33:24 +08:00
1 parent d277fc1522
commit 2b1add64db
2 files changed
+35 -2

No files matched your search

+17 -2
View File
@@ -123,12 +123,27 @@ pub async fn build_sync(
BuildTool::Maven => ide_build::sync_maven(&root, &cache, &options, &token, &progress)?,
BuildTool::Gradle => ide_build::sync_gradle(&root, &cache, &options, &token, &progress)?,
}
Ok(load(&root, &cache, &settings))
Ok::<BuildModel, IdeError>(load(&root, &cache, &settings))
})
.await
.map_err(join_err);
host.end_request(request);
result?
let model = result??;
if tool == BuildTool::Maven
&& let Some(maven) = &model.maven
{
// jdtls re-imports on pom changes but misses artifacts added to ~/.m2
// meanwhile ("missing artifact" stays until Invalidate Caches); asking it
// to update the project configurations re-resolves them (#436).
let lsp = project.lsp.clone();
let uris = maven.projects.iter().map(|p| ide_lsp::path_to_uri_string(&project.root.join(&p.pom))).collect();
tokio::spawn(async move {
if let Err(e) = lsp.java_update_project_configs(&project.root, uris).await {
tracing::debug!("java/projectConfigurationsUpdate: {e}");
}
});
}
Ok(model)
}
/// The POM declaring `dependency` for the Maven module `pom` (project-relative): the
+18
View File
@@ -225,6 +225,24 @@ impl LspManager {
}
}
/// Tells jdtls the build files of `uris` changed (`java/projectConfigurationsUpdate`),
/// so it re-imports their projects (e.g. after `~/.m2` gained an artifact it could
/// not resolve). Best-effort: skipped while jdtls is not already running.
pub async fn java_update_project_configs(&self, path: &Path, uris: Vec<String>) -> IdeResult<()> {
if uris.is_empty() {
return Ok(());
}
let java = LanguageId::new("java");
let Some(server) = self.servers_for(&java, path).into_iter().find(|s| s.name == SERVER) else {
return Ok(());
};
let Some(run) = server.running() else { return Ok(()) };
let identifiers: Vec<Value> = uris.iter().map(|u| json!({ "uri": u })).collect();
run.peer
.notify("java/projectConfigurationsUpdate", json!({ "identifiers": identifiers }))
.map_err(|e| crate::rpc_err(&server.name, "java/projectConfigurationsUpdate", e))
}
/// Incremental build of the jdtls workspace (`java/buildWorkspace`), so
/// class files are up to date before a launch.
pub async fn java_build(&self, path: &Path) -> IdeResult<JavaBuildStatus> {