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