Skip to content

Commit

Permalink
Maven: Improve dependency resolution (for example for annotation proc…
Browse files Browse the repository at this point in the history
…essors like lombok)

Resolution of processors also needs to take into account, that for
example the version for an artifact could be provided by
DependencyManagement.

Closes: apache#8054
Closes: apache#8041
  • Loading branch information
matthiasblaesing committed Dec 14, 2024
1 parent f00c1a4 commit 66446f5
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
Expand All @@ -39,6 +41,7 @@
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.InputLocation;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginExecution;
Expand Down Expand Up @@ -613,8 +616,10 @@ static class DependencyListBuilder implements ConfigurationBuilder<List<Dependen

private final String multiPropertyName;
private final String filterType;
private final DependencyManagement dependencyManagement;

public DependencyListBuilder(String multiPropertyName, String filterType) {
public DependencyListBuilder(DependencyManagement dependencyManagement, String multiPropertyName, String filterType) {
this.dependencyManagement = dependencyManagement;
this.multiPropertyName = multiPropertyName;
this.filterType = filterType;
}
Expand Down Expand Up @@ -652,21 +657,48 @@ public List<Dependency> build(Xpp3Dom configRoot, ExpressionEvaluator eval) {
item.setGroupId(g.getValue());
item.setLocation(PROP_GROUP_ID, (InputLocation)g.getInputLocation());
}

Dependency dependencyFromDependencyManagement = null;
if(dependencyManagement != null && dependencyManagement.getDependencies() != null) {
dependencyFromDependencyManagement =
dependencyManagement
.getDependencies()
.stream()
.filter(d -> {
return Objects.equals(item.getGroupId(), d.getGroupId())
&& Objects.equals(item.getArtifactId(), d.getArtifactId());
})
.findFirst()
.orElse(null);
}

if (v != null) {
item.setVersion(v.getValue());
item.setLocation(PROP_VERSION, (InputLocation)v.getInputLocation());
} else if (dependencyFromDependencyManagement != null) {
item.setVersion(dependencyFromDependencyManagement.getVersion());
item.setLocation(PROP_VERSION, dependencyFromDependencyManagement.getLocation(PROP_VERSION));
}
if (c != null) {
item.setClassifier(c.getValue());
item.setLocation(PROP_CLASSIFIER, (InputLocation)c.getInputLocation());
} else if (dependencyFromDependencyManagement != null) {
item.setClassifier(dependencyFromDependencyManagement.getClassifier());
item.setLocation(PROP_CLASSIFIER, dependencyFromDependencyManagement.getLocation(PROP_CLASSIFIER));
}
if (t != null) {
item.setType(t.getValue());
item.setLocation(PROP_TYPE, (InputLocation)t.getInputLocation());
} else if (dependencyFromDependencyManagement != null) {
item.setType(dependencyFromDependencyManagement.getType());
item.setLocation(PROP_TYPE, dependencyFromDependencyManagement.getLocation(PROP_TYPE));
}
if (s != null) {
item.setScope(s.getValue());
item.setLocation(PROP_SCOPE, (InputLocation)s.getInputLocation());
} else if (dependencyFromDependencyManagement != null) {
item.setScope(dependencyFromDependencyManagement.getType());
item.setLocation(PROP_TYPE, dependencyFromDependencyManagement.getLocation(PROP_TYPE));
}
coords.add(item);
}
Expand Down Expand Up @@ -793,7 +825,7 @@ public String getDefaultScope() {
}

MavenProject mavenProject = projectImpl.getOriginalMavenProject();
DependencyListBuilder bld = new DependencyListBuilder(query.getPathProperty(), query.getArtifactType());
DependencyListBuilder bld = new DependencyListBuilder(mavenProject.getDependencyManagement(), query.getPathProperty(), query.getArtifactType());
List<Dependency> coordinates = PluginPropertyUtils.getPluginPropertyBuildable(mavenProject, query.getPluginGroupId(), query.getPluginArtifactId(), query.getGoal(), bld);
if (coordinates == null) {
return null;
Expand Down Expand Up @@ -833,7 +865,7 @@ public String getDefaultScope() {
artifact = new DefaultArtifact(
coord.getGroupId(),
coord.getArtifactId(),
"",
(VersionRange) null,
coord.getScope() == null ? query.getDefaultScope() : coord.getScope(),
coord.getType(),
coord.getClassifier(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,18 @@
package org.netbeans.modules.maven.api;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.model.Dependency;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.junit.NbTestCase;
import org.openide.filesystems.FileObject;
Expand Down Expand Up @@ -202,6 +208,7 @@ public void testDependencyListBuilder() throws Exception {

// Matching filter for propertyItemName should yield correct result
PluginPropertyUtils.DependencyListBuilder bld = new PluginPropertyUtils.DependencyListBuilder(
null,
"annotationProcessorPaths",
null
);
Expand Down Expand Up @@ -266,10 +273,109 @@ public void testDependencyListBuilder() throws Exception {
// Filter with null value for propertyItemName should yield full list
Xpp3Dom configRoot2 = Xpp3DomBuilder.build(new StringReader(testPom2)).getChild("build").getChild("plugins").getChildren()[0].getChild("configuration");
PluginPropertyUtils.DependencyListBuilder bld2 = new PluginPropertyUtils.DependencyListBuilder(
null,
"annotationProcessorPaths",
null
);
List<Dependency> dependencies3 = bld2.build(configRoot2, PluginPropertyUtils.DUMMY_EVALUATOR);
assertEquals(2, dependencies3.size());
}

public void testDependencyBuilderWithDependencyManagement() throws IOException {
TestFileUtils.writeFile(d, "pom.xml",
"""
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>let.me.reproduce</groupId>
<artifactId>annotation-processor-netbeans-reproducer</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.36</version>
<classifier>dummy</classifier>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
"""
);
Project project = ProjectManager.getDefault().findProject(d);
assert project != null;
PluginPropertyUtils.PluginConfigPathParams query = new PluginPropertyUtils.PluginConfigPathParams("org.apache.maven.plugins", "maven-compiler-plugin", "annotationProcessorPaths");
query.setDefaultScope(Artifact.SCOPE_RUNTIME);
query.setGoal("runtime");
List<ArtifactResolutionException> errorList = new ArrayList<>();
List<Artifact> artifacts = PluginPropertyUtils.getPluginPathProperty(project, query, true, errorList);
assertNotNull(artifacts);
assert artifacts != null;
assertEquals(1, artifacts.size());
assertEquals("org.projectlombok", artifacts.get(0).getGroupId());
assertEquals("lombok", artifacts.get(0).getArtifactId());
assertEquals("1.18.36", artifacts.get(0).getVersion());
assertEquals("dummy", artifacts.get(0).getClassifier());
}

public void testDependencyBuilderWithoutVersion() throws IOException {
TestFileUtils.writeFile(d, "pom.xml",
"""
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>let.me.reproduce</groupId>
<artifactId>annotation-processor-netbeans-reproducer</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
"""
);
Project project = ProjectManager.getDefault().findProject(d);
assert project != null;
PluginPropertyUtils.PluginConfigPathParams query = new PluginPropertyUtils.PluginConfigPathParams("org.apache.maven.plugins", "maven-compiler-plugin", "annotationProcessorPaths");
query.setDefaultScope(Artifact.SCOPE_RUNTIME);
query.setGoal("runtime");
List<ArtifactResolutionException> errorList = new ArrayList<>();
List<Artifact> artifacts = PluginPropertyUtils.getPluginPathProperty(project, query, true, errorList);
assertNotNull(artifacts);
assert artifacts != null;
assertEquals(0, artifacts.size());
}
}

0 comments on commit 66446f5

Please sign in to comment.