This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch maven-4.0.x
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/maven-4.0.x by this push:
     new f877d83664 Fix MavenStaxReader location reporting for properties 
(#11402) (#11404)
f877d83664 is described below

commit f877d836646af63207aa31859e6251f74a918ce7
Author: Guillaume Nodet <[email protected]>
AuthorDate: Thu Nov 6 19:31:53 2025 +0100

    Fix MavenStaxReader location reporting for properties (#11402) (#11404)
    
    The location for properties (Map elements) was being captured AFTER calling
    nextText(), which moves the parser position past the element. This resulted
    in incorrect location information.
    
    This commit fixes the timing of location capture for properties by saving
    the line and column numbers BEFORE calling nextText().
    
    Changes:
    - Modified src/mdo/reader-stax.vm to capture location before nextText() for 
properties
    - Added comprehensive unit tests for location reporting:
      * testLocationReportingForElements() - tests regular elements with exact 
line/column numbers
      * testLocationReportingForAttributes() - tests XML attributes (root, 
child.scm.connection.inherit.append.path)
        Note: Attributes get the location of their containing element since 
XMLStreamReader doesn't
        provide individual attribute positions
      * testLocationReportingForListElements() - tests list elements (modules) 
with exact line/column numbers
    
    (cherry picked from commit 6f5c8378538557fd51b14b03d6bfd57751fb3bbf)
---
 .../apache/maven/model/v4/MavenStaxReaderTest.java | 141 +++++++++++++++++++++
 src/mdo/reader-stax.vm                             |   8 +-
 2 files changed, 147 insertions(+), 2 deletions(-)

diff --git 
a/impl/maven-support/src/test/java/org/apache/maven/model/v4/MavenStaxReaderTest.java
 
b/impl/maven-support/src/test/java/org/apache/maven/model/v4/MavenStaxReaderTest.java
index d88c3522e1..b8cf040603 100644
--- 
a/impl/maven-support/src/test/java/org/apache/maven/model/v4/MavenStaxReaderTest.java
+++ 
b/impl/maven-support/src/test/java/org/apache/maven/model/v4/MavenStaxReaderTest.java
@@ -22,6 +22,9 @@
 
 import java.io.StringReader;
 
+import org.apache.maven.api.model.Dependency;
+import org.apache.maven.api.model.InputLocation;
+import org.apache.maven.api.model.InputSource;
 import org.apache.maven.api.model.Model;
 import org.junit.jupiter.api.Test;
 
@@ -140,6 +143,144 @@ void testPluginConfigurationAllowsOtherNamespaces() 
throws XMLStreamException {
         assertEquals("http://maven.apache.org/POM/4.0.0";, 
model.getNamespaceUri());
     }
 
+    @Test
+    void testLocationReportingForElements() throws Exception {
+        String xml = "<project>\n"
+                + "  <modelVersion>4.0.0</modelVersion>\n"
+                + "  <groupId>org.example</groupId>\n"
+                + "  <artifactId>test-artifact</artifactId>\n"
+                + "  <version>1.0.0</version>\n"
+                + "  <dependencies>\n"
+                + "    <dependency>\n"
+                + "      <groupId>junit</groupId>\n"
+                + "      <artifactId>junit</artifactId>\n"
+                + "      <version>4.13.2</version>\n"
+                + "    </dependency>\n"
+                + "  </dependencies>\n"
+                + "</project>";
+
+        MavenStaxReader reader = new MavenStaxReader();
+        reader.setAddLocationInformation(true);
+        Model model = reader.read(new StringReader(xml), true, new 
InputSource("test.xml", null));
+
+        // Check root element location - should point to <project> tag on line 
1, column 1
+        InputLocation projectLocation = model.getLocation("");
+        assertNotNull(projectLocation, "Project location should not be null");
+        assertEquals(1, projectLocation.getLineNumber(), "Project should start 
at line 1");
+        assertEquals(1, projectLocation.getColumnNumber(), "Project should 
start at column 1");
+
+        // Check modelVersion location - should point to <modelVersion> tag on 
line 2, column 3
+        InputLocation modelVersionLocation = model.getLocation("modelVersion");
+        assertNotNull(modelVersionLocation, "ModelVersion location should not 
be null");
+        assertEquals(2, modelVersionLocation.getLineNumber(), "ModelVersion 
should start at line 2");
+        assertEquals(3, modelVersionLocation.getColumnNumber(), "ModelVersion 
should start at column 3");
+
+        // Check groupId location - should point to <groupId> tag on line 3, 
column 3
+        InputLocation groupIdLocation = model.getLocation("groupId");
+        assertNotNull(groupIdLocation, "GroupId location should not be null");
+        assertEquals(3, groupIdLocation.getLineNumber(), "GroupId should start 
at line 3");
+        assertEquals(3, groupIdLocation.getColumnNumber(), "GroupId should 
start at column 3");
+
+        // Check dependencies location - should point to <dependencies> tag on 
line 6, column 3
+        InputLocation dependenciesLocation = model.getLocation("dependencies");
+        assertNotNull(dependenciesLocation, "Dependencies location should not 
be null");
+        assertEquals(6, dependenciesLocation.getLineNumber(), "Dependencies 
should start at line 6");
+        assertEquals(3, dependenciesLocation.getColumnNumber(), "Dependencies 
should start at column 3");
+
+        // Check dependency location - should point to <dependency> tag on 
line 7, column 5
+        Dependency dependency = model.getDependencies().get(0);
+        InputLocation dependencyLocation = dependency.getLocation("");
+        assertNotNull(dependencyLocation, "Dependency location should not be 
null");
+        assertEquals(7, dependencyLocation.getLineNumber(), "Dependency should 
start at line 7");
+        assertEquals(5, dependencyLocation.getColumnNumber(), "Dependency 
should start at column 5");
+
+        // Check dependency groupId location - should point to <groupId> tag 
on line 8, column 7
+        InputLocation depGroupIdLocation = dependency.getLocation("groupId");
+        assertNotNull(depGroupIdLocation, "Dependency groupId location should 
not be null");
+        assertEquals(8, depGroupIdLocation.getLineNumber(), "Dependency 
groupId should start at line 8");
+        assertEquals(7, depGroupIdLocation.getColumnNumber(), "Dependency 
groupId should start at column 7");
+    }
+
+    @Test
+    void testLocationReportingForAttributes() throws Exception {
+        String xml = "<project root=\"true\">\n"
+                + "  <modelVersion>4.0.0</modelVersion>\n"
+                + "  <groupId>org.example</groupId>\n"
+                + "  <artifactId>test-artifact</artifactId>\n"
+                + "  <version>1.0.0</version>\n"
+                + "  <scm 
child.scm.connection.inherit.append.path=\"false\">\n"
+                + "    
<connection>scm:git:https://github.com/example/repo.git</connection>\n"
+                + "  </scm>\n"
+                + "</project>";
+
+        MavenStaxReader reader = new MavenStaxReader();
+        reader.setAddLocationInformation(true);
+        Model model = reader.read(new StringReader(xml), true, new 
InputSource("test.xml", null));
+
+        // Check project root attribute - attributes get the location of their 
containing element
+        // since XMLStreamReader doesn't provide individual attribute positions
+        InputLocation rootLocation = model.getLocation("root");
+        assertNotNull(rootLocation, "Root attribute location should not be 
null");
+        assertEquals(1, rootLocation.getLineNumber(), "Root attribute should 
be on line 1 (element line)");
+        assertEquals(1, rootLocation.getColumnNumber(), "Root attribute should 
point to column 1 (element column)");
+        assertTrue(model.isRoot(), "Root should be true");
+
+        // Check scm element location
+        InputLocation scmLocation = model.getScm().getLocation("");
+        assertNotNull(scmLocation, "SCM location should not be null");
+        assertEquals(6, scmLocation.getLineNumber(), "SCM should start at line 
6");
+        assertEquals(3, scmLocation.getColumnNumber(), "SCM should start at 
column 3");
+
+        // Check scm child.scm.connection.inherit.append.path attribute
+        // Like all attributes, it gets the location of its containing element
+        InputLocation scmInheritLocation = 
model.getScm().getLocation("child.scm.connection.inherit.append.path");
+        assertNotNull(scmInheritLocation, "SCM inherit attribute location 
should not be null");
+        assertEquals(6, scmInheritLocation.getLineNumber(), "SCM inherit 
attribute should be on line 6 (element line)");
+        assertEquals(
+                3,
+                scmInheritLocation.getColumnNumber(),
+                "SCM inherit attribute should point to column 3 (element 
column)");
+        assertEquals("false", 
model.getScm().getChildScmConnectionInheritAppendPath());
+    }
+
+    @Test
+    void testLocationReportingForListElements() throws Exception {
+        String xml = "<project>\n"
+                + "  <modelVersion>4.0.0</modelVersion>\n"
+                + "  <modules>\n"
+                + "    <module>module1</module>\n"
+                + "    <module>module2</module>\n"
+                + "    <module>module3</module>\n"
+                + "  </modules>\n"
+                + "</project>";
+
+        MavenStaxReader reader = new MavenStaxReader();
+        reader.setAddLocationInformation(true);
+        Model model = reader.read(new StringReader(xml), true, new 
InputSource("test.xml", null));
+
+        // Check modules location - should point to <modules> tag on line 3, 
column 3
+        InputLocation modulesLocation = model.getLocation("modules");
+        assertNotNull(modulesLocation, "Modules location should not be null");
+        assertEquals(3, modulesLocation.getLineNumber(), "Modules should start 
at line 3");
+        assertEquals(3, modulesLocation.getColumnNumber(), "Modules should 
start at column 3");
+
+        // Check individual module locations
+        InputLocation module1Location = modulesLocation.getLocation(0);
+        assertNotNull(module1Location, "Module 1 location should not be null");
+        assertEquals(4, module1Location.getLineNumber(), "Module 1 should 
start at line 4");
+        assertEquals(5, module1Location.getColumnNumber(), "Module 1 should 
start at column 5");
+
+        InputLocation module2Location = modulesLocation.getLocation(1);
+        assertNotNull(module2Location, "Module 2 location should not be null");
+        assertEquals(5, module2Location.getLineNumber(), "Module 2 should 
start at line 5");
+        assertEquals(5, module2Location.getColumnNumber(), "Module 2 should 
start at column 5");
+
+        InputLocation module3Location = modulesLocation.getLocation(2);
+        assertNotNull(module3Location, "Module 3 location should not be null");
+        assertEquals(6, module3Location.getLineNumber(), "Module 3 should 
start at line 6");
+        assertEquals(5, module3Location.getColumnNumber(), "Module 3 should 
start at column 5");
+    }
+
     private Model fromXml(String xml) throws XMLStreamException {
         MavenStaxReader reader = new MavenStaxReader();
         return reader.read(new StringReader(xml), true, null);
diff --git a/src/mdo/reader-stax.vm b/src/mdo/reader-stax.vm
index 06aee9bc54..09d43a6bb8 100644
--- a/src/mdo/reader-stax.vm
+++ b/src/mdo/reader-stax.vm
@@ -425,10 +425,14 @@ public class ${className} {
         #end
                     while (parser.nextTag() == XMLStreamReader.START_ELEMENT) {
                         String key = parser.getLocalName();
+        #if ( $locationTracking )
+                        int propLine = parser.getLocation().getLineNumber();
+                        int propColumn = 
parser.getLocation().getColumnNumber();
+        #end
                         String value = nextText(parser, strict).trim();
         #if ( $locationTracking )
                         if (addLocationInformation) {
-                            locations.put(key, new 
InputLocation(parser.getLocation().getLineNumber(), 
parser.getLocation().getColumnNumber(), inputSrc));
+                            locations.put(key, new InputLocation(propLine, 
propColumn, inputSrc));
                         }
         #end
                         ${field.name}.put(key, value);
@@ -700,7 +704,7 @@ public class ${className} {
     private XmlNode buildXmlNode(XMLStreamReader parser, InputSource inputSrc) 
throws XMLStreamException {
         return XmlService.read(parser,
                 addLocationInformation
-                        ? p -> new 
InputLocation(parser.getLocation().getLineNumber(), 
parser.getLocation().getColumnNumber(), inputSrc)
+                        ? p -> new 
InputLocation(p.getLocation().getLineNumber(), 
p.getLocation().getColumnNumber(), inputSrc)
                         : null);
     }
 #else

Reply via email to