Skip to content

Commit

Permalink
Merge pull request #101 from ABHAY0O7/multi-module-support
Browse files Browse the repository at this point in the history
Multi module support
  • Loading branch information
tdurieux authored Aug 20, 2021
2 parents c7556f0 + 2a5c170 commit 3d95389
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ public void addDependencySize(final Path dependencyDirPath, final Logger logger)
SizeOfDependencies.put(file.getName(), FileUtils.sizeOf(file));
}
} else {
logger.warn("Dependencies where not copied locally");
logger.warn("Dependencies were not copied locally");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@
import se.kth.depclean.core.analysis.DefaultProjectDependencyAnalyzer;
import se.kth.depclean.core.analysis.ProjectDependencyAnalysis;
import se.kth.depclean.core.analysis.ProjectDependencyAnalyzerException;
import se.kth.depclean.util.ChangeDependencyResultUtils;
import se.kth.depclean.util.JarUtils;
import se.kth.depclean.util.MavenInvoker;
import se.kth.depclean.util.ResultsUtils;
import se.kth.depclean.util.json.ParsedDependencies;

/**
Expand All @@ -80,6 +82,16 @@ public class DepCleanMojo extends AbstractMojo {
private static final String SEPARATOR = "-------------------------------------------------------";
public static final String DIRECTORY_TO_COPY_DEPENDENCIES = "dependency";

/**
* A map [Module coordinates] -> [Depclean result].
*/
private static final Map<String, ResultsUtils> ModuleResult = new HashMap<>();

/**
* A set to store module id.
*/
private static final Set<String> ModuleDependency = new HashSet<>();

/**
* The Maven project to analyze.
*/
Expand Down Expand Up @@ -403,7 +415,7 @@ public final void execute() throws MojoExecutionException {
sizeOfDependencies.put(file.getName(), FileUtils.sizeOf(file));
}
} else {
log.warn("Dependencies where not copied locally");
log.warn("Dependencies were not copied locally");
}

/* Decompress dependencies */
Expand All @@ -424,10 +436,20 @@ public final void execute() throws MojoExecutionException {
return;
}

// Getting coordinates of all artifacts without version.
Set<String> allDependenciesCoordinates = new HashSet<>();
Set<Artifact> allArtifacts = project.getArtifacts();
for (Artifact artifact : allArtifacts) {
String coordinate = artifact.getGroupId() + ":"
+ artifact.getArtifactId() + ":"
+ artifact.getVersion();
allDependenciesCoordinates.add(coordinate);
}

Set<Artifact> usedTransitiveArtifacts = projectDependencyAnalysis.getUsedUndeclaredArtifacts();
Set<Artifact> usedDirectArtifacts = projectDependencyAnalysis.getUsedDeclaredArtifacts();
Set<Artifact> unusedDirectArtifacts = projectDependencyAnalysis.getUnusedDeclaredArtifacts();
Set<Artifact> unusedTransitiveArtifacts = project.getArtifacts();
Set<Artifact> unusedTransitiveArtifacts = new HashSet<>(allArtifacts);

unusedTransitiveArtifacts.removeAll(usedDirectArtifacts);
unusedTransitiveArtifacts.removeAll(usedTransitiveArtifacts);
Expand Down Expand Up @@ -526,6 +548,17 @@ public final void execute() throws MojoExecutionException {
}
}

// Adding module coordinates as a dependency.
String moduleId = project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion();

// Collecting the result.
ResultsUtils resultInfo = new ResultsUtils(
unusedDirectArtifactsCoordinates,
unusedInheritedArtifactsCoordinates,
unusedTransitiveArtifactsCoordinates);
// Mapping the result with module for further usage.
ModuleResult.put(moduleId, resultInfo);

/* Printing the results to the terminal */
printString(SEPARATOR);
printString(" D E P C L E A N A N A L Y S I S R E S U L T S");
Expand All @@ -548,6 +581,53 @@ public final void execute() throws MojoExecutionException {
ignoreDependencies.stream().forEach(s -> printString("\t" + s));
}

// Getting those dependencies from previous modules whose status might have been changed now.
Set<ChangeDependencyResultUtils> dependenciesResultChange = new HashSet<>();
for (String module : ModuleDependency) {
/* If the module is used as a dependency in the project,
then it will be present in allDependenciesCoordinates. */
if (allDependenciesCoordinates.contains(module)) {
// Getting the result of specified module.
ResultsUtils result = ModuleResult.get(module);
/* Build will only fail when status of any dependencies has been changed
from unused to used, so getting all the unused dependencies from the
previous modules and comparing that with all the used transitive
dependencies of the current module. */
Set<String> allUnusedDependency = result.getAllUnusedDependenciesCoordinates();
for (String usedDependency : usedTransitiveArtifactsCoordinates) {
if (allUnusedDependency.contains(usedDependency)) {
// This dependency status need to be changed.
dependenciesResultChange.add(
new ChangeDependencyResultUtils(usedDependency,
module,
result.getType(usedDependency)));
}
}
}
}

// Adding the module whose result has been collected. (Alert: This position is specific for adding it)
ModuleDependency.add(moduleId);

// Printing those dependencies to the terminal whose status needs to be changed.
if (!dependenciesResultChange.isEmpty()) {
printString("\n" + SEPARATOR);
getLog().info("DEPENDENT MODULES FOUND");
printString("Due to dependent modules, the debloated result of some dependencies"
+ " from previous modules has been changed now.");
printString("The dependency-module details of such dependencies with the"
+ " new results are as follows :\n");
int serialNumber = 0;
for (ChangeDependencyResultUtils result : dependenciesResultChange) {
printString("\t" + ++serialNumber + ") ModuleCoordinates : " + result.getModule());
printString("\t DependencyCoordinates : " + result.getDependencyCoordinate());
printString("\t OldType : " + result.getType());
printString("\t NewType : " + result.getNewType());
printString("");
}
printString(SEPARATOR);
}

/* Fail the build if there are unused direct dependencies */
if (failIfUnusedDirect && !unusedDirectArtifactsCoordinates.isEmpty()) {
throw new MojoExecutionException(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package se.kth.depclean.util;

import java.util.Objects;

/**
* This will help in changing the status of the dependencies involved in
* dependent modules of a multi-module java project.
*/
public class ChangeDependencyResultUtils {

private final String dependencyCoordinate;
private final String module;
private final String type;

/**
* Ctor.
*
* @param dependencyCoordinate Target dependency.
* @param module Target module.
* @param type Debloat status.
*/
public ChangeDependencyResultUtils(final String dependencyCoordinate,
final String module,
final String type) {
this.dependencyCoordinate = dependencyCoordinate;
this.module = module;
this.type = type;
}

// Getters -------------------------------------------------------------
public String getDependencyCoordinate() {
return dependencyCoordinate;
}

public String getModule() {
return module;
}

public String getType() {
return type;
}

/**
* Return the new type (status) of the dependency.
*
* @return New type
*/
public String getNewType() {
// Changing the status of debloat.
String newType;
if (Objects.equals(type, "unusedDirect")) {
newType = "usedDirect";
} else if (Objects.equals(type, "unusedTransitive")) {
newType = "usedTransitive";
} else {
newType = "usedInherited";
}
return newType;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package se.kth.depclean.util;

import java.util.HashSet;
import java.util.Set;

/**
* Collects the data from the report generated by depclean on any module of the project.
*/
public class ResultsUtils {

private final Set<String> unusedDirectArtifactsCoordinates;
private final Set<String> unusedInheritedArtifactsCoordinates;
private final Set<String> unusedTransitiveArtifactsCoordinates;
private final Set<String> allUnusedDependenciesCoordinates = new HashSet<>();

/**
* Ctor.
*/
public ResultsUtils(final Set<String> unusedDirectArtifactsCoordinates,
final Set<String> unusedInheritedArtifactsCoordinates,
final Set<String> unusedTransitiveArtifactsCoordinates) {
this.unusedDirectArtifactsCoordinates = unusedDirectArtifactsCoordinates;
this.unusedInheritedArtifactsCoordinates = unusedInheritedArtifactsCoordinates;
this.unusedTransitiveArtifactsCoordinates = unusedTransitiveArtifactsCoordinates;
}

// Getters ------------------------------------------------------------------------------

/**
* Collect all the unused dependencies from the provided result.
*
* @return A set of all unused dependencies
*/
public Set<String> getAllUnusedDependenciesCoordinates() {
/* Collecting only the unused dependencies, cause in multi-module analysis, build
will only fail when any unused dependencies iof one module is used by another. */
allUnusedDependenciesCoordinates.addAll(unusedDirectArtifactsCoordinates);
allUnusedDependenciesCoordinates.addAll(unusedInheritedArtifactsCoordinates);
allUnusedDependenciesCoordinates.addAll(unusedTransitiveArtifactsCoordinates);
return allUnusedDependenciesCoordinates;
}

/**
* To get the type (status) of a dependency.
*
* @param coordinates The dependency.
* @return Type (status)
*/
public String getType(final String coordinates) {
if (unusedDirectArtifactsCoordinates.contains(coordinates)) {
return "unusedDirect";
} else if (unusedTransitiveArtifactsCoordinates.contains(coordinates)) {
return "unusedTransitive";
} else {
return "unusedInherited";
}
}
}

0 comments on commit 3d95389

Please sign in to comment.