This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch mvnup in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/mvnup by this push: new 50fb32e5d6 Fix plugin formatting 50fb32e5d6 is described below commit 50fb32e5d6e106b244a942e7a7c7748bcf2a0e67 Author: Guillaume Nodet <gno...@gmail.com> AuthorDate: Wed Jun 4 02:52:24 2025 +0200 Fix plugin formatting --- .../maven/cling/invoker/mvnup/goals/JDomUtils.java | 50 ++++++++- .../mvnup/goals/PluginUpgradeStrategyTest.java | 114 +++++++++++++++++++++ 2 files changed, 163 insertions(+), 1 deletion(-) diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/JDomUtils.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/JDomUtils.java index 1b77a79e2f..4c12e20334 100644 --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/JDomUtils.java +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/JDomUtils.java @@ -216,15 +216,22 @@ public static Element insertNewElement(String name, Element root, int index) { root.addContent(index, newElement); addAppropriateSpacing(root, index, name, indent); + // Ensure the parent element has proper closing tag formatting + ensureProperClosingTagFormatting(root); + return newElement; } /** * Creates a new element with proper formatting. + * This method ensures that both the opening and closing tags are properly indented. */ private static Element createElement(String name, Namespace namespace, String indent) { Element newElement = new Element(name, namespace); - newElement.addContent("\n" + indent); + + // Add content with proper formatting for child elements and closing tag + newElement.addContent("\n" + indent); // Indentation for child content + return newElement; } @@ -248,6 +255,47 @@ private static void addAppropriateSpacing(Element root, int index, String elemen } } + /** + * Ensures that the parent element has proper closing tag formatting. + * This method checks if the last content of the element is properly indented + * and adds appropriate whitespace if needed. + */ + private static void ensureProperClosingTagFormatting(Element parent) { + List<Content> contents = parent.getContent(); + if (contents.isEmpty()) { + return; + } + + // Get the parent's indentation level + String parentIndent = detectParentIndentation(parent); + + // Check if the last content is a Text node with proper indentation + Content lastContent = contents.get(contents.size() - 1); + if (lastContent instanceof Text) { + String text = ((Text) lastContent).getText(); + // If the last text doesn't end with proper indentation for the closing tag + if (!text.endsWith("\n" + parentIndent)) { + // Remove the last text node and add a properly formatted one + parent.removeContent(lastContent); + parent.addContent(new Text("\n" + parentIndent)); + } + } else { + // If the last content is not a text node, add proper indentation for closing tag + parent.addContent(new Text("\n" + parentIndent)); + } + } + + /** + * Detects the indentation level of the parent element. + */ + private static String detectParentIndentation(Element element) { + Parent parent = element.getParent(); + if (parent instanceof Element) { + return detectIndentation((Element) parent); + } + return ""; + } + /** * Inserts a new content element with the given name and text content. * diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java index db327119f2..e84b426984 100644 --- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java +++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java @@ -19,6 +19,7 @@ package org.apache.maven.cling.invoker.mvnup.goals; import java.io.StringReader; +import java.io.StringWriter; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; @@ -31,6 +32,8 @@ import org.jdom2.Element; import org.jdom2.Namespace; import org.jdom2.input.SAXBuilder; +import org.jdom2.output.Format; +import org.jdom2.output.XMLOutputter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -578,4 +581,115 @@ void shouldProvideMeaningfulDescription() { assertTrue(description.toLowerCase().contains("plugin"), "Description should mention plugins"); } } + + @Nested + @DisplayName("XML Formatting") + class XmlFormattingTests { + + @Test + @DisplayName("should format pluginManagement with proper indentation") + void shouldFormatPluginManagementWithProperIndentation() throws Exception { + String pomXml = + """ + <?xml version="1.0" encoding="UTF-8"?> + <project xmlns="http://maven.apache.org/POM/4.0.0"> + <modelVersion>4.0.0</modelVersion> + <groupId>test</groupId> + <artifactId>test</artifactId> + <version>1.0.0</version> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.1</version> + </plugin> + </plugins> + </build> + </project> + """; + + Document document = saxBuilder.build(new StringReader(pomXml)); + Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document); + + UpgradeContext context = createMockContext(); + strategy.apply(context, pomMap); + + // Convert to string to check formatting + Format format = Format.getRawFormat(); + format.setLineSeparator(System.lineSeparator()); + XMLOutputter out = new XMLOutputter(format); + StringWriter writer = new StringWriter(); + out.output(document.getRootElement(), writer); + String result = writer.toString(); + + // Check that the plugin version was upgraded + assertTrue(result.contains("<version>3.2</version>"), "Plugin version should be upgraded to 3.2"); + + // Verify that the XML formatting is correct - no malformed closing tags + assertFalse(result.contains("</plugin></plugins>"), "Should not have malformed closing tags"); + assertFalse(result.contains("</plugins></pluginManagement>"), "Should not have malformed closing tags"); + + // Check that proper indentation is maintained + assertTrue(result.contains(" <build>"), "Build element should be properly indented"); + assertTrue(result.contains(" <plugins>"), "Plugins element should be properly indented"); + assertTrue(result.contains(" <plugin>"), "Plugin element should be properly indented"); + } + + @Test + @DisplayName("should format pluginManagement with proper indentation when added") + void shouldFormatPluginManagementWithProperIndentationWhenAdded() throws Exception { + // Use a POM that will trigger pluginManagement addition by having a plugin without version + String pomXml = + """ + <?xml version="1.0" encoding="UTF-8"?> + <project xmlns="http://maven.apache.org/POM/4.0.0"> + <modelVersion>4.0.0</modelVersion> + <groupId>test</groupId> + <artifactId>test</artifactId> + <version>1.0.0</version> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <!-- No version - should trigger pluginManagement addition --> + </plugin> + </plugins> + </build> + </project> + """; + + Document document = saxBuilder.build(new StringReader(pomXml)); + Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document); + + UpgradeContext context = createMockContext(); + strategy.apply(context, pomMap); + + // Convert to string to check formatting + Format format = Format.getRawFormat(); + format.setLineSeparator(System.lineSeparator()); + XMLOutputter out = new XMLOutputter(format); + StringWriter writer = new StringWriter(); + out.output(document.getRootElement(), writer); + String result = writer.toString(); + + // If pluginManagement was added, verify proper formatting + if (result.contains("<pluginManagement>")) { + // Verify that the XML formatting is correct - no malformed closing tags + assertFalse(result.contains("</plugin></plugins>"), "Should not have malformed closing tags"); + assertFalse(result.contains("</plugins></pluginManagement>"), "Should not have malformed closing tags"); + + // Check that proper indentation is maintained for pluginManagement + assertTrue( + result.contains(" <pluginManagement>"), "PluginManagement should be properly indented"); + assertTrue( + result.contains(" <plugins>"), + "Plugins in pluginManagement should be properly indented"); + assertTrue( + result.contains(" </pluginManagement>"), + "PluginManagement closing tag should be properly indented"); + } + } + } }