From 83eb1ce2bad601451f7d06bd626699cd742bc6fc Mon Sep 17 00:00:00 2001 From: arookieofc Date: Fri, 30 Oct 2026 19:20:06 +0800 Subject: [PATCH] fix(maven): list profiles inherited from parent POMs (#425) A module can activate its parents' profiles with -P, but the Maven model listed only the profiles declared in the module's own POM. Profiles are now collected from the POM and its ancestors (with their activeByDefault state). Co-authored-by: a-rookie-of-C-language <186315048+a-rookie-of-C-language@users.noreply.github.com> --- crates/ide-build/src/maven.rs | 49 ++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/crates/ide-build/src/maven.rs b/crates/ide-build/src/maven.rs index ae03adad..2c0e3f8f 100644 --- a/crates/ide-build/src/maven.rs +++ b/crates/ide-build/src/maven.rs @@ -401,6 +401,9 @@ struct Inherited { managed: Vec, plugins: Vec, managed_plugins: Vec, + /// ``, `activeByDefault`: profiles of the POM and its ancestors — + /// Maven lets a child enable a parent's profiles with `-P`. + profiles: Vec<(String, bool)>, } fn merge_by(base: &mut Vec, own: &[T], key: impl Fn(&T) -> String) { @@ -523,6 +526,11 @@ impl Resolver { merge_by(&mut ctx.deps, &p.deps, RawDep::key); merge_plugins(&mut ctx.plugins, &p.plugins); } + merge_by( + &mut ctx.profiles, + &pom.profiles.iter().map(|p| (p.id.clone(), p.active_by_default)).collect::>(), + |(id, _)| id.clone(), + ); // Managed dependencies: own entries win; imported BOMs fill the gaps. let props = self.properties_for(&pom, &ctx, &dir); let mut imported: Vec = Vec::new(); @@ -935,9 +943,10 @@ pub(crate) fn load_with_repo(root: &Path, local_repo: Option) -> MavenM .or_else(|| pom.compiler_release.as_deref().map(i)) .and_then(|v| java_version(&v)); - for p in &pom.profiles { - if !model.profiles.iter().any(|x| x.id == p.id) { - model.profiles.push(MavenProfile { id: p.id.clone(), active_by_default: p.active_by_default }); + // The project can activate the profiles of its own POM and its ancestors'. + for (id, active) in &ctx.profiles { + if !model.profiles.iter().any(|x| x.id == *id) { + model.profiles.push(MavenProfile { id: id.clone(), active_by_default: *active }); } } let artifact_id = i(&pom.artifact_id); @@ -954,7 +963,7 @@ pub(crate) fn load_with_repo(root: &Path, local_repo: Option) -> MavenM aggregated, plugins, dependencies, - profiles: pom.profiles.iter().map(|p| p.id.clone()).collect(), + profiles: ctx.profiles.iter().map(|(id, _)| id.clone()).collect(), java_version: jv, command: wrapper(root, &dir), options: Vec::new(), @@ -1280,9 +1289,41 @@ mod tests { let profiles: Vec<(&str, bool)> = model.profiles.iter().map(|p| (p.id.as_str(), p.active_by_default)).collect(); assert_eq!(profiles, [("dev", true), ("extra", false)]); assert_eq!(parent.profiles, ["dev", "extra"]); + assert_eq!(core.profiles, ["dev", "extra"], "a module inherits its parent's profiles"); assert!(model.projects.iter().all(|p| p.command == if cfg!(windows) { "mvn.cmd" } else { "mvn" })); } + #[test] + fn profiles_of_a_parent_pom_are_inherited() { + let tmp = tempfile::tempdir().unwrap(); + let root = tmp.path(); + write( + root, + "pom.xml", + r#"demoparent1.0 + pomchild + + jdk8 + jdk21true + + "#, + ); + write( + root, + "child/pom.xml", + r#"demoparent1.0 + child + own + "#, + ); + let model = load_with_repo(root, None); + let child = &model.projects[1]; + // `-Pjdk8` on the module activates the parent's profile, so it is listed. + assert_eq!(child.profiles, ["jdk8", "jdk21", "own"]); + let profiles: Vec<(&str, bool)> = model.profiles.iter().map(|p| (p.id.as_str(), p.active_by_default)).collect(); + assert_eq!(profiles, [("jdk8", false), ("jdk21", true), ("own", false)]); + } + #[test] fn parent_and_bom_from_the_local_repository_and_wrapper() { let tmp = tempfile::tempdir().unwrap();