Skip to content

Commit

Permalink
fix: handle different project dependency configs (#107)
Browse files Browse the repository at this point in the history
Co-authored-by: Arthur McGibbon <arthur.mcgibbon@h3im.com>
  • Loading branch information
Arthurm1 and Arthur McGibbon authored Dec 21, 2023
1 parent b77ecfd commit 79dfd62
Show file tree
Hide file tree
Showing 43 changed files with 426 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
import java.io.Serializable;

/**
* Represents a project dependency.
* Represents a build target dependency.
* In Java this is a project:sourceset dependency on a project:sourceset.
*/
public interface GradleProjectDependency extends Serializable {
public interface BuildTargetDependency extends Serializable {
public String getProjectPath();

public String getSourceSetName();
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public interface GradleSourceSet extends Serializable {
/**
* Project dependencies.
*/
public Set<GradleProjectDependency> getProjectDependencies();
public Set<BuildTargetDependency> getBuildTargetDependencies();

/**
* has tests defined.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

package com.microsoft.java.bs.gradle.model.impl;

import java.util.Objects;

import com.microsoft.java.bs.gradle.model.BuildTargetDependency;
import com.microsoft.java.bs.gradle.model.GradleSourceSet;

/**
* Default implementation of {@link BuildTargetDependency}.
*/
public class DefaultBuildTargetDependency implements BuildTargetDependency {
private static final long serialVersionUID = 1L;

private String projectPath;

private String sourceSetName;

public DefaultBuildTargetDependency(String projectPath, String sourceSetName) {
this.projectPath = projectPath;
this.sourceSetName = sourceSetName;
}

public DefaultBuildTargetDependency(GradleSourceSet sourceSet) {
this(sourceSet.getProjectPath(), sourceSet.getSourceSetName());
}


/**
* Copy constructor.
*
* @param buildTargetDependency the other instance to copy from.
*/
public DefaultBuildTargetDependency(BuildTargetDependency buildTargetDependency) {
this.projectPath = buildTargetDependency.getProjectPath();
this.sourceSetName = buildTargetDependency.getSourceSetName();
}

public String getProjectPath() {
return projectPath;
}

public void setProjectPath(String projectPath) {
this.projectPath = projectPath;
}

public String getSourceSetName() {
return sourceSetName;
}

public void setSourceSetName(String sourceSetName) {
this.sourceSetName = sourceSetName;
}

@Override
public int hashCode() {
return Objects.hash(projectPath, sourceSetName);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
DefaultBuildTargetDependency other = (DefaultBuildTargetDependency) obj;
return Objects.equals(projectPath, other.projectPath)
&& Objects.equals(sourceSetName, other.sourceSetName);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import java.util.stream.Collectors;

import com.microsoft.java.bs.gradle.model.GradleModuleDependency;
import com.microsoft.java.bs.gradle.model.GradleProjectDependency;
import com.microsoft.java.bs.gradle.model.BuildTargetDependency;
import com.microsoft.java.bs.gradle.model.GradleSourceSet;

/**
Expand Down Expand Up @@ -59,7 +59,7 @@ public class DefaultGradleSourceSet implements GradleSourceSet {

private Set<GradleModuleDependency> moduleDependencies;

private Set<GradleProjectDependency> projectDependencies;
private Set<BuildTargetDependency> buildTargetDependencies;

private boolean hasTests;

Expand Down Expand Up @@ -92,8 +92,8 @@ public DefaultGradleSourceSet(GradleSourceSet gradleSourceSet) {
this.compilerArgs = gradleSourceSet.getCompilerArgs();
this.moduleDependencies = gradleSourceSet.getModuleDependencies().stream()
.map(DefaultGradleModuleDependency::new).collect(Collectors.toSet());
this.projectDependencies = gradleSourceSet.getProjectDependencies().stream()
.map(DefaultGradleProjectDependency::new).collect(Collectors.toSet());
this.buildTargetDependencies = gradleSourceSet.getBuildTargetDependencies().stream()
.map(DefaultBuildTargetDependency::new).collect(Collectors.toSet());
this.hasTests = gradleSourceSet.hasTests();
}

Expand Down Expand Up @@ -257,12 +257,12 @@ public void setModuleDependencies(Set<GradleModuleDependency> moduleDependencies
this.moduleDependencies = moduleDependencies;
}

public Set<GradleProjectDependency> getProjectDependencies() {
return projectDependencies;
public Set<BuildTargetDependency> getBuildTargetDependencies() {
return buildTargetDependencies;
}

public void setProjectDependencies(Set<GradleProjectDependency> projectDependencies) {
this.projectDependencies = projectDependencies;
public void setBuildTargetDependencies(Set<BuildTargetDependency> buildTargetDependencies) {
this.buildTargetDependencies = buildTargetDependencies;
}

public boolean hasTests() {
Expand All @@ -280,7 +280,7 @@ public int hashCode() {
generatedSourceDirs, sourceOutputDir, compileClasspath,
resourceDirs, resourceOutputDir, javaHome, javaVersion,
gradleVersion, sourceCompatibility, targetCompatibility,
compilerArgs, moduleDependencies, projectDependencies,
compilerArgs, moduleDependencies, buildTargetDependencies,
hasTests);
}

Expand Down Expand Up @@ -316,7 +316,7 @@ public boolean equals(Object obj) {
&& Objects.equals(targetCompatibility, other.targetCompatibility)
&& Objects.equals(compilerArgs, other.compilerArgs)
&& Objects.equals(moduleDependencies, other.moduleDependencies)
&& Objects.equals(projectDependencies, other.projectDependencies)
&& Objects.equals(buildTargetDependencies, other.buildTargetDependencies)
&& hasTests == other.hasTests;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.LinkedList;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
Expand All @@ -25,24 +24,29 @@
import java.util.stream.Stream;

import org.gradle.api.Project;
import org.gradle.api.file.CopySpec;
import org.gradle.api.file.Directory;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.SourceDirectorySet;
import org.gradle.api.internal.tasks.compile.DefaultJavaCompileSpec;
import org.gradle.api.internal.tasks.compile.JavaCompilerArgumentsBuilder;
import org.gradle.api.internal.file.copy.DefaultCopySpec;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.TaskCollection;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import org.gradle.api.tasks.compile.CompileOptions;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.api.tasks.testing.Test;
import org.gradle.plugins.ide.internal.tooling.java.DefaultInstalledJdk;
import org.gradle.tooling.provider.model.ToolingModelBuilder;
import org.gradle.util.GradleVersion;

import com.microsoft.java.bs.gradle.model.BuildTargetDependency;
import com.microsoft.java.bs.gradle.model.GradleSourceSet;
import com.microsoft.java.bs.gradle.model.GradleSourceSets;
import com.microsoft.java.bs.gradle.model.impl.DefaultBuildTargetDependency;
import com.microsoft.java.bs.gradle.model.impl.DefaultGradleSourceSet;
import com.microsoft.java.bs.gradle.model.impl.DefaultGradleSourceSets;
import com.microsoft.java.bs.gradle.plugin.dependency.DependencyCollector;
Expand Down Expand Up @@ -156,13 +160,69 @@ public Object buildAll(String modelName, Project rootProject) {
}
}

// map all output dirs to their source sets
Map<File, DefaultGradleSourceSet> outputsToSourceSet = new HashMap<>();
for (DefaultGradleSourceSet sourceSet : sourceSetMap.values()) {
if (sourceSet.getSourceOutputDir() != null) {
outputsToSourceSet.put(sourceSet.getSourceOutputDir(), sourceSet);
}
if (sourceSet.getResourceOutputDir() != null) {
outputsToSourceSet.put(sourceSet.getResourceOutputDir(), sourceSet);
}
}
// map all output jars to their source sets
for (Project project : allProject) {

SourceSetContainer sourceSets = getSourceSetContainer(project);
if (sourceSets == null || sourceSets.isEmpty()) {
continue;
}

// dependencies
// get all archive tasks for this project and find the dirs that are included in the archive
TaskCollection<AbstractArchiveTask> archiveTasks =
project.getTasks().withType(AbstractArchiveTask.class);
for (AbstractArchiveTask archiveTask : archiveTasks) {
Set<Object> archiveSourcePaths = getArchiveSourcePaths(archiveTask.getRootSpec());
for (Object sourcePath : archiveSourcePaths) {
sourceSets.forEach(sourceSet -> {
DefaultGradleSourceSet gradleSourceSet = sourceSetMap.get(sourceSet);
if (gradleSourceSet == null) {
return;
}

if (sourceSet.getOutput().equals(sourcePath)) {
File archiveFile;
if (GradleVersion.current().compareTo(GradleVersion.version("5.1")) >= 0) {
archiveFile = archiveTask.getArchiveFile().get().getAsFile();
} else {
archiveFile = archiveTask.getArchivePath();
}
outputsToSourceSet.put(archiveFile, gradleSourceSet);
}
});
}
}
}

// match any classpath entries to other project's output dirs/jars to create dependencies
for (DefaultGradleSourceSet sourceSet : sourceSetMap.values()) {
Set<BuildTargetDependency> dependencies = new HashSet<>();
for (File file : sourceSet.getCompileClasspath()) {
DefaultGradleSourceSet otherSourceSet = outputsToSourceSet.get(file);
if (otherSourceSet != null) {
dependencies.add(new DefaultBuildTargetDependency(otherSourceSet));
}
}
sourceSet.setBuildTargetDependencies(dependencies);
}

for (Project project : allProject) {
SourceSetContainer sourceSets = getSourceSetContainer(project);
if (sourceSets == null || sourceSets.isEmpty()) {
continue;
}

// module dependencies
sourceSets.forEach(sourceSet -> {
DefaultGradleSourceSet gradleSourceSet = sourceSetMap.get(sourceSet);
if (gradleSourceSet == null) {
Expand All @@ -172,7 +232,6 @@ public Object buildAll(String modelName, Project rootProject) {
exclusionFromDependencies);
collector.collectByConfigurationNames(getClasspathConfigurationNames(sourceSet));
gradleSourceSet.setModuleDependencies(collector.getModuleDependencies());
gradleSourceSet.setProjectDependencies(collector.getProjectDependencies());
});
}

Expand Down Expand Up @@ -207,6 +266,36 @@ private String createUniqueDisplayName(DefaultGradleSourceSet sourceSet,
return usedName;
}

private Set<Object> getArchiveSourcePaths(CopySpec copySpec) {
Set<Object> sourcePaths = new HashSet<>();
if (copySpec instanceof DefaultCopySpec) {
DefaultCopySpec defaultCopySpec = (DefaultCopySpec) copySpec;
sourcePaths.addAll(defaultCopySpec.getSourcePaths());
// DefaultCopySpec#getChildren changed from Iterable to Collection
if (GradleVersion.current().compareTo(GradleVersion.version("6.2")) >= 0) {
for (CopySpec child : defaultCopySpec.getChildren()) {
sourcePaths.addAll(getArchiveSourcePaths(child));
}
} else {
try {
Method getChildren = defaultCopySpec.getClass().getMethod("getChildren");
Object children = getChildren.invoke(defaultCopySpec);
if (children instanceof Iterable) {
for (Object child : (Iterable<?>) children) {
if (child instanceof CopySpec) {
sourcePaths.addAll(getArchiveSourcePaths((CopySpec) child));
}
}
}
} catch (NoSuchMethodException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) {
// cannot get archive information
}
}
}
return sourcePaths;
}

private SourceSetContainer getSourceSetContainer(Project project) {
if (!project.getPlugins().hasPlugin("java")) {
return null;
Expand Down
Loading

0 comments on commit 79dfd62

Please sign in to comment.