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

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


The following commit(s) were added to refs/heads/master by this push:
     new 6f5c837853 Fix MavenStaxReader location reporting for properties 
(#11402)
6f5c837853 is described below

commit 6f5c8378538557fd51b14b03d6bfd57751fb3bbf
Author: Guillaume Nodet <[email protected]>
AuthorDate: Thu Nov 6 16:39:00 2025 +0100

    Fix MavenStaxReader location reporting for properties (#11402)
    
    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
---
 .../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..8f5b4c355f 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, 
InputSource.of("test.xml"));
+
+        // 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, 
InputSource.of("test.xml"));
+
+        // 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, 
InputSource.of("test.xml"));
+
+        // 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 00c42a78c0..730cbf89b0 100644
--- a/src/mdo/reader-stax.vm
+++ b/src/mdo/reader-stax.vm
@@ -427,10 +427,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, 
InputLocation.of(parser.getLocation().getLineNumber(), 
parser.getLocation().getColumnNumber(), inputSrc));
+                            locations.put(key, InputLocation.of(propLine, 
propColumn, inputSrc));
                         }
         #end
                         ${field.name}.put(key, value);
@@ -702,7 +706,7 @@ public class ${className} {
     private XmlNode buildXmlNode(XMLStreamReader parser, InputSource inputSrc) 
throws XMLStreamException {
         return XmlService.read(parser,
                 addLocationInformation
-                        ? p -> 
InputLocation.of(parser.getLocation().getLineNumber(), 
parser.getLocation().getColumnNumber(), inputSrc)
+                        ? p -> 
InputLocation.of(p.getLocation().getLineNumber(), 
p.getLocation().getColumnNumber(), inputSrc)
                         : null);
     }
 #else

Reply via email to