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

gnodet pushed a commit to branch feature/gh-11904-dependency-id-attribute
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to 
refs/heads/feature/gh-11904-dependency-id-attribute by this push:
     new 3d4ddbec46 [GH-11904] Support managed-version formats in dependency id 
attribute
3d4ddbec46 is described below

commit 3d4ddbec46fa36cc1b3f45c6ad31d155f2a191ec
Author: Guillaume Nodet <[email protected]>
AuthorDate: Tue Jun 23 22:13:40 2026 +0200

    [GH-11904] Support managed-version formats in dependency id attribute
    
    Add support for 2-part `g:a` format and trailing-colon formats
    (`g:a:`, `g:a:type:`, `g:a:type:classifier:`) for dependencies
    whose version is provided by dependencyManagement. The trailing
    colon convention signals that version is managed, not missing.
    
    Leave aside inferred ids (`:a:` with inferred groupId) for now.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 api/maven-api-model/src/main/mdo/maven.mdo         |   8 +-
 .../invoker/mvnup/goals/DependencyIdStrategy.java  |  34 +++++--
 .../mvnup/goals/DependencyIdStrategyTest.java      | 104 ++++++++++++++++++++-
 .../maven/impl/model/DefaultModelNormalizer.java   |  31 +++---
 .../maven/impl/model/DefaultModelValidator.java    |   9 +-
 .../impl/model/DefaultModelNormalizerTest.java     |  54 +++++++++++
 .../impl/model/DefaultModelValidatorTest.java      |  24 +++++
 .../poms/validation/dependency-id-2parts-valid.xml |  11 +++
 .../dependency-id-trailing-colon-3parts-valid.xml  |  11 +++
 .../dependency-id-trailing-colon-4parts-valid.xml  |  11 +++
 .../dependency-id-trailing-colon-5parts-valid.xml  |  11 +++
 11 files changed, 275 insertions(+), 33 deletions(-)

diff --git a/api/maven-api-model/src/main/mdo/maven.mdo 
b/api/maven-api-model/src/main/mdo/maven.mdo
index 00681ebe4f..8501c35711 100644
--- a/api/maven-api-model/src/main/mdo/maven.mdo
+++ b/api/maven-api-model/src/main/mdo/maven.mdo
@@ -1211,9 +1211,13 @@
           <description>
             <![CDATA[
             Combined coordinates in one of the following formats:
+            {@code groupId:artifactId} (version managed),
             {@code groupId:artifactId:version},
-            {@code groupId:artifactId:type:version}, or
-            {@code groupId:artifactId:type:classifier:version}.
+            {@code groupId:artifactId:type:version},
+            {@code groupId:artifactId:type:classifier:version},
+            {@code groupId:artifactId:type:} (version managed, with type), or
+            {@code groupId:artifactId:type:classifier:} (version managed, with 
type and classifier).
+            A trailing {@code :} indicates the version is managed (i.e. 
provided by dependencyManagement).
             When specified, it is split into the corresponding fields during 
model normalization.
             The individual child elements should not be specified when using 
this attribute.
             @since Maven 4.2
diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/DependencyIdStrategy.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/DependencyIdStrategy.java
index 3b77c1e6bf..5efccfaec3 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/DependencyIdStrategy.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/DependencyIdStrategy.java
@@ -66,11 +66,14 @@
  * <dependency id="org.example:lib:1.0"/>
  * }</pre>
  *
- * <p>Supports three formats:
+ * <p>Supported formats (trailing {@code :} means version is managed):
  * <ul>
- *   <li>{@code g:a:v} (3-part, default type "jar")</li>
- *   <li>{@code g:a:type:v} (4-part, non-default type)</li>
- *   <li>{@code g:a:type:classifier:v} (5-part, with classifier)</li>
+ *   <li>{@code g:a} — version managed</li>
+ *   <li>{@code g:a:v} — default type "jar"</li>
+ *   <li>{@code g:a:type:} — non-default type, version managed</li>
+ *   <li>{@code g:a:type:v} — non-default type</li>
+ *   <li>{@code g:a:type:classifier:} — with classifier, version managed</li>
+ *   <li>{@code g:a:type:classifier:v} — with classifier</li>
  * </ul>
  *
  * <p>Also collapses exclusions from {@code <groupId>}/{@code <artifactId>} 
into {@code id="g:a"}.
@@ -210,7 +213,7 @@ private boolean collapseDependency(UpgradeContext context, 
Element dependency) {
         String artifactId = dependency.childText(ARTIFACT_ID);
         String version = dependency.childText(VERSION);
 
-        if (groupId == null || artifactId == null || version == null) {
+        if (groupId == null || artifactId == null) {
             return false;
         }
 
@@ -222,7 +225,9 @@ private boolean collapseDependency(UpgradeContext context, 
Element dependency) {
 
         removeChildElement(dependency, GROUP_ID);
         removeChildElement(dependency, ARTIFACT_ID);
-        removeChildElement(dependency, VERSION);
+        if (version != null) {
+            removeChildElement(dependency, VERSION);
+        }
 
         if (classifier != null) {
             removeChildElement(dependency, CLASSIFIER);
@@ -230,7 +235,6 @@ private boolean collapseDependency(UpgradeContext context, 
Element dependency) {
         } else if (type != null && !DEFAULT_TYPE.equals(type)) {
             removeChildElement(dependency, TYPE);
         } else if (type != null) {
-            // default type "jar" — remove it as it's implied
             removeChildElement(dependency, TYPE);
         }
 
@@ -280,11 +284,21 @@ private boolean collapseExclusion(UpgradeContext context, 
Element exclusion) {
     static String buildIdValue(String groupId, String artifactId, String 
version, String type, String classifier) {
         if (classifier != null && !classifier.isEmpty()) {
             String effectiveType = (type != null && !type.isEmpty()) ? type : 
DEFAULT_TYPE;
-            return groupId + ":" + artifactId + ":" + effectiveType + ":" + 
classifier + ":" + version;
+            if (version != null) {
+                return groupId + ":" + artifactId + ":" + effectiveType + ":" 
+ classifier + ":" + version;
+            } else {
+                return groupId + ":" + artifactId + ":" + effectiveType + ":" 
+ classifier + ":";
+            }
         } else if (type != null && !type.isEmpty() && 
!DEFAULT_TYPE.equals(type)) {
-            return groupId + ":" + artifactId + ":" + type + ":" + version;
-        } else {
+            if (version != null) {
+                return groupId + ":" + artifactId + ":" + type + ":" + version;
+            } else {
+                return groupId + ":" + artifactId + ":" + type + ":";
+            }
+        } else if (version != null) {
             return groupId + ":" + artifactId + ":" + version;
+        } else {
+            return groupId + ":" + artifactId;
         }
     }
 
diff --git 
a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/DependencyIdStrategyTest.java
 
b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/DependencyIdStrategyTest.java
index 5c8b9abc9c..3be91fb164 100644
--- 
a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/DependencyIdStrategyTest.java
+++ 
b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/DependencyIdStrategyTest.java
@@ -342,8 +342,8 @@ void shouldPreserveOptionalWhenCollapsing() {
         }
 
         @Test
-        @DisplayName("should skip dependency without version")
-        void shouldSkipDependencyWithoutVersion() {
+        @DisplayName("should collapse dependency without version to g:a")
+        void shouldCollapseDependencyWithoutVersion() {
             String pomXml = """
                 <?xml version="1.0" encoding="UTF-8"?>
                 <project xmlns="http://maven.apache.org/POM/4.2.0";>
@@ -370,9 +370,83 @@ void shouldSkipDependencyWithoutVersion() {
                     .childElement("dependency")
                     .orElseThrow();
 
-            assertNull(dependency.attribute("id"));
-            assertNotNull(DomUtils.findChildElement(dependency, "groupId"));
-            assertNotNull(DomUtils.findChildElement(dependency, "artifactId"));
+            assertEquals("org.example:lib", dependency.attribute("id"));
+            assertNull(DomUtils.findChildElement(dependency, "groupId"));
+            assertNull(DomUtils.findChildElement(dependency, "artifactId"));
+        }
+
+        @Test
+        @DisplayName("should collapse managed-version dependency with 
non-default type to g:a:type:")
+        void shouldCollapseManagedWithType() {
+            String pomXml = """
+                <?xml version="1.0" encoding="UTF-8"?>
+                <project xmlns="http://maven.apache.org/POM/4.2.0";>
+                    <modelVersion>4.2.0</modelVersion>
+                    <groupId>com.example</groupId>
+                    <artifactId>test</artifactId>
+                    <version>1.0</version>
+                    <dependencies>
+                        <dependency>
+                            <groupId>org.example</groupId>
+                            <artifactId>lib</artifactId>
+                            <type>pom</type>
+                        </dependency>
+                    </dependencies>
+                </project>
+                """;
+
+            Document doc = Document.of(pomXml);
+            UpgradeContext context = 
TestUtils.createMockContext(TestUtils.createOptionsWithModelVersion("4.2.0"));
+            strategy.doApply(context, new 
HashMap<>(Map.of(Paths.get("pom.xml"), doc)));
+
+            Element dependency = doc.root()
+                    .childElement("dependencies")
+                    .orElseThrow()
+                    .childElement("dependency")
+                    .orElseThrow();
+
+            assertEquals("org.example:lib:pom:", dependency.attribute("id"));
+            assertNull(DomUtils.findChildElement(dependency, "groupId"));
+            assertNull(DomUtils.findChildElement(dependency, "artifactId"));
+            assertNull(DomUtils.findChildElement(dependency, "type"));
+        }
+
+        @Test
+        @DisplayName("should collapse managed-version dependency with 
classifier to g:a:type:classifier:")
+        void shouldCollapseManagedWithClassifier() {
+            String pomXml = """
+                <?xml version="1.0" encoding="UTF-8"?>
+                <project xmlns="http://maven.apache.org/POM/4.2.0";>
+                    <modelVersion>4.2.0</modelVersion>
+                    <groupId>com.example</groupId>
+                    <artifactId>test</artifactId>
+                    <version>1.0</version>
+                    <dependencies>
+                        <dependency>
+                            <groupId>org.example</groupId>
+                            <artifactId>lib</artifactId>
+                            <type>jar</type>
+                            <classifier>sources</classifier>
+                        </dependency>
+                    </dependencies>
+                </project>
+                """;
+
+            Document doc = Document.of(pomXml);
+            UpgradeContext context = 
TestUtils.createMockContext(TestUtils.createOptionsWithModelVersion("4.2.0"));
+            strategy.doApply(context, new 
HashMap<>(Map.of(Paths.get("pom.xml"), doc)));
+
+            Element dependency = doc.root()
+                    .childElement("dependencies")
+                    .orElseThrow()
+                    .childElement("dependency")
+                    .orElseThrow();
+
+            assertEquals("org.example:lib:jar:sources:", 
dependency.attribute("id"));
+            assertNull(DomUtils.findChildElement(dependency, "groupId"));
+            assertNull(DomUtils.findChildElement(dependency, "artifactId"));
+            assertNull(DomUtils.findChildElement(dependency, "type"));
+            assertNull(DomUtils.findChildElement(dependency, "classifier"));
         }
 
         @Test
@@ -839,6 +913,11 @@ void shouldProcessOnly420PomsInMixedMap() {
     @DisplayName("buildIdValue")
     class BuildIdValueTests {
 
+        @Test
+        void twoPartFormat() {
+            assertEquals("g:a", DependencyIdStrategy.buildIdValue("g", "a", 
null, null, null));
+        }
+
         @Test
         void threePartFormat() {
             assertEquals("g:a:1.0", DependencyIdStrategy.buildIdValue("g", 
"a", "1.0", null, null));
@@ -869,5 +948,20 @@ void fivePartFormatWithNonDefaultType() {
         void fivePartFormatClassifierNoType() {
             assertEquals("g:a:jar:sources:1.0", 
DependencyIdStrategy.buildIdValue("g", "a", "1.0", null, "sources"));
         }
+
+        @Test
+        void fourPartTrailingColon() {
+            assertEquals("g:a:pom:", DependencyIdStrategy.buildIdValue("g", 
"a", null, "pom", null));
+        }
+
+        @Test
+        void fivePartTrailingColon() {
+            assertEquals("g:a:jar:sources:", 
DependencyIdStrategy.buildIdValue("g", "a", null, "jar", "sources"));
+        }
+
+        @Test
+        void fivePartTrailingColonClassifierNoType() {
+            assertEquals("g:a:jar:sources:", 
DependencyIdStrategy.buildIdValue("g", "a", null, null, "sources"));
+        }
     }
 }
diff --git 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelNormalizer.java
 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelNormalizer.java
index a36992f33f..e8b13988f0 100644
--- 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelNormalizer.java
+++ 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelNormalizer.java
@@ -199,11 +199,15 @@ private Profile expandProfileDependencyIds(Profile 
profile) {
 
     /**
      * Expands the {@code id} attribute on a dependency into its component 
fields.
-     * Supported formats:
+     * Supported formats (trailing {@code :} means version is managed):
      * <ul>
-     *   <li>{@code groupId:artifactId:version} (3 parts)</li>
-     *   <li>{@code groupId:artifactId:type:version} (4 parts)</li>
-     *   <li>{@code groupId:artifactId:type:classifier:version} (5 parts)</li>
+     *   <li>{@code groupId:artifactId} (version managed)</li>
+     *   <li>{@code groupId:artifactId:} (version managed, explicit trailing 
colon)</li>
+     *   <li>{@code groupId:artifactId:version}</li>
+     *   <li>{@code groupId:artifactId:type:} (version managed, with type)</li>
+     *   <li>{@code groupId:artifactId:type:version}</li>
+     *   <li>{@code groupId:artifactId:type:classifier:} (version managed, 
with type and classifier)</li>
+     *   <li>{@code groupId:artifactId:type:classifier:version}</li>
      * </ul>
      */
     Dependency expandDependencyId(Dependency d) {
@@ -212,8 +216,8 @@ Dependency expandDependencyId(Dependency d) {
             List<Exclusion> expanded = injectList(d.getExclusions(), 
this::expandExclusionId);
             return expanded != null ? d.withExclusions(expanded) : d;
         }
-        String[] parts = id.split(":");
-        if (parts.length < 3 || parts.length > 5) {
+        String[] parts = id.split(":", -1);
+        if (parts.length < 2 || parts.length > 5) {
             return d;
         }
         Dependency.Builder builder = Dependency.newBuilder(d, true);
@@ -225,30 +229,33 @@ Dependency expandDependencyId(Dependency d) {
             builder.artifactId(parts[1]);
         }
         switch (parts.length) {
+            case 2:
+                // g:a (version managed)
+                break;
             case 3:
-                // g:a:v
-                if (isNullOrEmpty(d.getVersion())) {
+                // g:a:v or g:a: (managed)
+                if (!parts[2].isEmpty() && isNullOrEmpty(d.getVersion())) {
                     builder.version(parts[2]);
                 }
                 break;
             case 4:
-                // g:a:type:v
+                // g:a:type:v or g:a:type: (managed)
                 if (isNullOrEmptyOrDefault(d.getType())) {
                     builder.type(parts[2]);
                 }
-                if (isNullOrEmpty(d.getVersion())) {
+                if (!parts[3].isEmpty() && isNullOrEmpty(d.getVersion())) {
                     builder.version(parts[3]);
                 }
                 break;
             case 5:
-                // g:a:type:classifier:v
+                // g:a:type:classifier:v or g:a:type:classifier: (managed)
                 if (isNullOrEmptyOrDefault(d.getType())) {
                     builder.type(parts[2]);
                 }
                 if (isNullOrEmpty(d.getClassifier())) {
                     builder.classifier(parts[3]);
                 }
-                if (isNullOrEmpty(d.getVersion())) {
+                if (!parts[4].isEmpty() && isNullOrEmpty(d.getVersion())) {
                     builder.version(parts[4]);
                 }
                 break;
diff --git 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java
 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java
index 72e65e1864..e4d5b26f99 100644
--- 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java
+++ 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java
@@ -1269,16 +1269,17 @@ private void 
validateDependencyIdAttribute(ModelProblemCollector problems, Depen
             return;
         }
         int colonCount = id.length() - id.replace(":", "").length();
-        if (colonCount < 2 || colonCount > 4) {
+        if (colonCount < 1 || colonCount > 4) {
             addViolation(
                     problems,
                     Severity.ERROR,
                     Version.V42,
                     prefix + "id",
                     null,
-                    "has invalid format '" + id + "', must be 
'groupId:artifactId:version', "
-                            + "'groupId:artifactId:type:version', or "
-                            + "'groupId:artifactId:type:classifier:version'.",
+                    "has invalid format '" + id + "', must be 
'groupId:artifactId[:]', "
+                            + "'groupId:artifactId:version', "
+                            + "'groupId:artifactId:type:[version]', or "
+                            + 
"'groupId:artifactId:type:classifier:[version]'.",
                     dependency);
             return;
         }
diff --git 
a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelNormalizerTest.java
 
b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelNormalizerTest.java
index e4a84dbbb3..8eca6c66ad 100644
--- 
a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelNormalizerTest.java
+++ 
b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelNormalizerTest.java
@@ -35,6 +35,30 @@ class DefaultModelNormalizerTest {
 
     private final DefaultModelNormalizer normalizer = new 
DefaultModelNormalizer();
 
+    @Test
+    void testExpandDependencyId2parts() {
+        Dependency dep = 
Dependency.newBuilder(false).id("org.example:lib").build();
+
+        Dependency result = normalizer.expandDependencyId(dep);
+
+        assertEquals("org.example", result.getGroupId());
+        assertEquals("lib", result.getArtifactId());
+        assertNull(result.getVersion());
+        assertNull(result.getId());
+    }
+
+    @Test
+    void testExpandDependencyId2partsTrailingColon() {
+        Dependency dep = 
Dependency.newBuilder(false).id("org.example:lib:").build();
+
+        Dependency result = normalizer.expandDependencyId(dep);
+
+        assertEquals("org.example", result.getGroupId());
+        assertEquals("lib", result.getArtifactId());
+        assertNull(result.getVersion());
+        assertNull(result.getId());
+    }
+
     @Test
     void testExpandDependencyId3parts() {
         Dependency dep =
@@ -62,6 +86,20 @@ void testExpandDependencyId4parts() {
         assertNull(result.getId());
     }
 
+    @Test
+    void testExpandDependencyId4partsTrailingColon() {
+        Dependency dep =
+                
Dependency.newBuilder(false).id("org.example:lib-b:pom:").build();
+
+        Dependency result = normalizer.expandDependencyId(dep);
+
+        assertEquals("org.example", result.getGroupId());
+        assertEquals("lib-b", result.getArtifactId());
+        assertEquals("pom", result.getType());
+        assertNull(result.getVersion());
+        assertNull(result.getId());
+    }
+
     @Test
     void testExpandDependencyId5parts() {
         Dependency dep = Dependency.newBuilder(false)
@@ -78,6 +116,22 @@ void testExpandDependencyId5parts() {
         assertNull(result.getId());
     }
 
+    @Test
+    void testExpandDependencyId5partsTrailingColon() {
+        Dependency dep = Dependency.newBuilder(false)
+                .id("org.example:lib-c:jar:sources:")
+                .build();
+
+        Dependency result = normalizer.expandDependencyId(dep);
+
+        assertEquals("org.example", result.getGroupId());
+        assertEquals("lib-c", result.getArtifactId());
+        assertEquals("jar", result.getType());
+        assertEquals("sources", result.getClassifier());
+        assertNull(result.getVersion());
+        assertNull(result.getId());
+    }
+
     @Test
     void testExpandDependencyIdDoesNotOverrideExistingFields() {
         Dependency dep = Dependency.newBuilder(false)
diff --git 
a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java
 
b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java
index 3514ee326f..f9e649cafb 100644
--- 
a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java
+++ 
b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelValidatorTest.java
@@ -1023,6 +1023,12 @@ void profileActivationConditionWithBasedirExpression() 
throws Exception {
         assertViolations(result, 0, 0, 0);
     }
 
+    @Test
+    void testDependencyId2partsValid() throws Exception {
+        SimpleProblemCollector result = 
validateFile("dependency-id-2parts-valid.xml");
+        assertViolations(result, 0, 0, 0);
+    }
+
     @Test
     void testDependencyId3partsValid() throws Exception {
         SimpleProblemCollector result = 
validateFile("dependency-id-3parts-valid.xml");
@@ -1041,6 +1047,24 @@ void testDependencyId5partsValid() throws Exception {
         assertViolations(result, 0, 0, 0);
     }
 
+    @Test
+    void testDependencyIdTrailingColon3partsValid() throws Exception {
+        SimpleProblemCollector result = 
validateFile("dependency-id-trailing-colon-3parts-valid.xml");
+        assertViolations(result, 0, 0, 0);
+    }
+
+    @Test
+    void testDependencyIdTrailingColon4partsValid() throws Exception {
+        SimpleProblemCollector result = 
validateFile("dependency-id-trailing-colon-4parts-valid.xml");
+        assertViolations(result, 0, 0, 0);
+    }
+
+    @Test
+    void testDependencyIdTrailingColon5partsValid() throws Exception {
+        SimpleProblemCollector result = 
validateFile("dependency-id-trailing-colon-5parts-valid.xml");
+        assertViolations(result, 0, 0, 0);
+    }
+
     @Test
     void testDependencyIdBadFormat() throws Exception {
         SimpleProblemCollector result = 
validateFile("dependency-id-bad-format.xml");
diff --git 
a/impl/maven-impl/src/test/resources/poms/validation/dependency-id-2parts-valid.xml
 
b/impl/maven-impl/src/test/resources/poms/validation/dependency-id-2parts-valid.xml
new file mode 100644
index 0000000000..3702648630
--- /dev/null
+++ 
b/impl/maven-impl/src/test/resources/poms/validation/dependency-id-2parts-valid.xml
@@ -0,0 +1,11 @@
+<project xmlns="http://maven.apache.org/POM/4.2.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.2.0 
https://maven.apache.org/xsd/maven-4.2.0.xsd";>
+  <modelVersion>4.2.0</modelVersion>
+  <groupId>test</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0</version>
+  <dependencies>
+    <dependency id="org.example:lib-a"/>
+  </dependencies>
+</project>
diff --git 
a/impl/maven-impl/src/test/resources/poms/validation/dependency-id-trailing-colon-3parts-valid.xml
 
b/impl/maven-impl/src/test/resources/poms/validation/dependency-id-trailing-colon-3parts-valid.xml
new file mode 100644
index 0000000000..a76ebe1741
--- /dev/null
+++ 
b/impl/maven-impl/src/test/resources/poms/validation/dependency-id-trailing-colon-3parts-valid.xml
@@ -0,0 +1,11 @@
+<project xmlns="http://maven.apache.org/POM/4.2.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.2.0 
https://maven.apache.org/xsd/maven-4.2.0.xsd";>
+  <modelVersion>4.2.0</modelVersion>
+  <groupId>test</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0</version>
+  <dependencies>
+    <dependency id="org.example:lib-a:"/>
+  </dependencies>
+</project>
diff --git 
a/impl/maven-impl/src/test/resources/poms/validation/dependency-id-trailing-colon-4parts-valid.xml
 
b/impl/maven-impl/src/test/resources/poms/validation/dependency-id-trailing-colon-4parts-valid.xml
new file mode 100644
index 0000000000..731c4d5c43
--- /dev/null
+++ 
b/impl/maven-impl/src/test/resources/poms/validation/dependency-id-trailing-colon-4parts-valid.xml
@@ -0,0 +1,11 @@
+<project xmlns="http://maven.apache.org/POM/4.2.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.2.0 
https://maven.apache.org/xsd/maven-4.2.0.xsd";>
+  <modelVersion>4.2.0</modelVersion>
+  <groupId>test</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0</version>
+  <dependencies>
+    <dependency id="org.example:lib-b:pom:"/>
+  </dependencies>
+</project>
diff --git 
a/impl/maven-impl/src/test/resources/poms/validation/dependency-id-trailing-colon-5parts-valid.xml
 
b/impl/maven-impl/src/test/resources/poms/validation/dependency-id-trailing-colon-5parts-valid.xml
new file mode 100644
index 0000000000..e169e92fa9
--- /dev/null
+++ 
b/impl/maven-impl/src/test/resources/poms/validation/dependency-id-trailing-colon-5parts-valid.xml
@@ -0,0 +1,11 @@
+<project xmlns="http://maven.apache.org/POM/4.2.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.2.0 
https://maven.apache.org/xsd/maven-4.2.0.xsd";>
+  <modelVersion>4.2.0</modelVersion>
+  <groupId>test</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0</version>
+  <dependencies>
+    <dependency id="org.example:lib-c:jar:sources:"/>
+  </dependencies>
+</project>

Reply via email to