Skip to content

Commit a4aa782

Browse files
gnodetclaude
andauthored
Remove invalid combine.self and combine.children attributes instead of converting them (#12160) (#12224)
Maven 3 silently ignored invalid combine.self and combine.children attribute values, so removing them entirely preserves actual Maven 3 behavior. Previously mvnup converted specific invalid values (e.g. combine.self="append" → "merge"), which could miss other invalid values and subtly changed semantics. Now both fixers detect any invalid value against the full set of valid values (combine.self: override/merge/remove; combine.children: append/merge), remove the attribute, and collect to a list before mutating to avoid potential stream processing issues. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 51e59bb commit a4aa782

2 files changed

Lines changed: 452 additions & 24 deletions

File tree

impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategy.java

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ public class CompatibilityFixStrategy extends AbstractUpgradeStrategy {
7777

7878
private static final Pattern EXPRESSION_PATTERN = Pattern.compile("\\$\\{([^}]+)}");
7979

80+
private static final Set<String> VALID_COMBINE_SELF_VALUES = Set.of(COMBINE_OVERRIDE, COMBINE_MERGE, "remove");
81+
82+
private static final Set<String> VALID_COMBINE_CHILDREN_VALUES = Set.of(COMBINE_APPEND, COMBINE_MERGE);
83+
8084
@Override
8185
public boolean isApplicable(UpgradeContext context) {
8286
UpgradeOptions options = getOptions(context);
@@ -165,44 +169,44 @@ public UpgradeResult doApply(UpgradeContext context, Map<Path, Document> pomMap)
165169

166170
/**
167171
* Fixes unsupported combine.children attribute values.
168-
* Maven 4 only supports 'append' and 'merge', not 'override'.
172+
* Maven 4 only supports 'append' and 'merge' (default is merge).
173+
* Invalid values are removed entirely since Maven 3 silently ignored them.
169174
*/
170175
private boolean fixUnsupportedCombineChildrenAttributes(Document pomDocument, UpgradeContext context) {
171-
boolean fixed = false;
172176
Element root = pomDocument.root();
173177

174-
// Find all elements with combine.children="override" and change to "merge"
175-
long fixedCombineChildrenCount = findElementsWithAttribute(root, COMBINE_CHILDREN, COMBINE_OVERRIDE)
176-
.peek(element -> {
177-
element.attributeObject(COMBINE_CHILDREN).value(COMBINE_MERGE);
178-
context.detail("Fixed: " + COMBINE_CHILDREN + "='" + COMBINE_OVERRIDE + "' → '" + COMBINE_MERGE
179-
+ "' in " + element.name());
180-
})
181-
.count();
182-
fixed |= fixedCombineChildrenCount > 0;
178+
List<Element> invalidElements = findElementsWithInvalidAttribute(
179+
root, COMBINE_CHILDREN, VALID_COMBINE_CHILDREN_VALUES)
180+
.toList();
183181

184-
return fixed;
182+
for (Element element : invalidElements) {
183+
String invalidValue = element.attribute(COMBINE_CHILDREN);
184+
element.removeAttribute(COMBINE_CHILDREN);
185+
context.detail(
186+
"Fixed: removed invalid " + COMBINE_CHILDREN + "='" + invalidValue + "' from " + element.name());
187+
}
188+
189+
return !invalidElements.isEmpty();
185190
}
186191

187192
/**
188193
* Fixes unsupported combine.self attribute values.
189-
* Maven 4 only supports 'override', 'merge', and 'remove' (default is merge), not 'append'.
194+
* Maven 4 only supports 'override', 'merge', and 'remove' (default is merge).
195+
* Invalid values are removed entirely since Maven 3 silently ignored them.
190196
*/
191197
private boolean fixUnsupportedCombineSelfAttributes(Document pomDocument, UpgradeContext context) {
192-
boolean fixed = false;
193198
Element root = pomDocument.root();
194199

195-
// Find all elements with combine.self="append" and change to "merge"
196-
long fixedCombineSelfCount = findElementsWithAttribute(root, COMBINE_SELF, COMBINE_APPEND)
197-
.peek(element -> {
198-
element.attributeObject(COMBINE_SELF).value(COMBINE_MERGE);
199-
context.detail("Fixed: " + COMBINE_SELF + "='" + COMBINE_APPEND + "' → '" + COMBINE_MERGE + "' in "
200-
+ element.name());
201-
})
202-
.count();
203-
fixed |= fixedCombineSelfCount > 0;
200+
List<Element> invalidElements = findElementsWithInvalidAttribute(root, COMBINE_SELF, VALID_COMBINE_SELF_VALUES)
201+
.toList();
204202

205-
return fixed;
203+
for (Element element : invalidElements) {
204+
String invalidValue = element.attribute(COMBINE_SELF);
205+
element.removeAttribute(COMBINE_SELF);
206+
context.detail("Fixed: removed invalid " + COMBINE_SELF + "='" + invalidValue + "' from " + element.name());
207+
}
208+
209+
return !invalidElements.isEmpty();
206210
}
207211

208212
/**
@@ -527,6 +531,20 @@ private Stream<Element> findElementsWithAttribute(Element element, String attrib
527531
.flatMap(child -> findElementsWithAttribute(child, attributeName, attributeValue)));
528532
}
529533

534+
/**
535+
* Recursively finds all elements with an attribute whose value is not in the set of valid values.
536+
*/
537+
private Stream<Element> findElementsWithInvalidAttribute(
538+
Element element, String attributeName, Set<String> validValues) {
539+
return Stream.concat(
540+
Stream.of(element).filter(e -> {
541+
String attr = e.attribute(attributeName);
542+
return attr != null && !validValues.contains(attr);
543+
}),
544+
element.childElements()
545+
.flatMap(child -> findElementsWithInvalidAttribute(child, attributeName, validValues)));
546+
}
547+
530548
/**
531549
* Helper methods extracted from BaseUpgradeGoal for compatibility fixes.
532550
*/

0 commit comments

Comments
 (0)