From 6faefb23026ee4e64a89c30a9069a4274283c914 Mon Sep 17 00:00:00 2001 From: cesarsotovalero Date: Tue, 9 Mar 2021 15:34:44 +0100 Subject: [PATCH] Fix https://github.com/castor-software/depclean/issues/35 --- README.md | 10 ++++----- .../DefaultProjectDependencyAnalyzer.java | 22 ++++++++++++++----- .../core/analysis/DependencyAnalyzer.java | 5 ++--- .../asm/DependencyClassFileVisitor.java | 1 - .../java/se/kth/depclean/DepCleanMojo.java | 12 +++++++++- 5 files changed, 34 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index d05aa406..5d6fc039 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,6 @@ You can configure the `pom.xml` file of your Maven project to use DepClean as pa The Maven plugin can be configured with the following additional parameters. - - | Name | Type | Description | |:----------|:-------------:| :-------------| | `` | `Set` | Add a list of dependencies, identified by their coordinates, to be ignored by DepClean during the analysis and considered as used dependencies. Useful to override incomplete result caused by bytecode-level analysis. ** @@ -77,6 +75,8 @@ Dependency format is:** `groupId:artifactId:version`.| | `` | `Set` | Add a list of scopes, to be ignored by DepClean during the analysis. Useful to not analyze dependencies with scopes that are not needed at runtime. ** Valid scopes are:** `compile`, `provided`, `test`, `runtime`, `system`, `import`. An Empty string indicates no scopes (default).| +| `` | `boolean` | If this is true, DepClean will not analyze the test classes in the project, and, therefore, the dependencies that are only used for testing will be considered unused. This parameter is useful to detect dependencies that have `compile` scope but are only used for testing. ** +Default value is:** `false`.| | `` | `boolean` | If this is true, DepClean creates a debloated version of the pom without unused dependencies called `debloated-pom.xml`, in the root of the project. ** Default value is:** `false`.| | `` | `boolean` | If this is true, DepClean creates a JSON file of the dependency tree along with metadata of each dependency. The file is called `depclean-results.json`, and is located in the root of the project. ** @@ -115,16 +115,14 @@ Of course, it is also possible to execute DepClean with parameters directly from can be executed directly as follows: ```bash -mvn se.kth.castor:depclean-maven-plugin:1.1.2-SNAPSHOT:depclean -Dfail.if.unused.direct=true -Dignore.scopes=provided, -test, -runtime,system,import +mvn se.kth.castor:depclean-maven-plugin:1.1.2:depclean -Dfail.if.unused.direct=true -Dignore.scopes=provided,test,runtime,system,import ``` ## Installing and building from source Prerequisites: -- [Java OpenJDK 8](https://openjdk.java.net) or above +- [Java OpenJDK 11](https://openjdk.java.net) or above - [Apache Maven](https://maven.apache.org/) In a terminal clone the repository and switch to the cloned folder: diff --git a/depclean-core/src/main/java/se/kth/depclean/core/analysis/DefaultProjectDependencyAnalyzer.java b/depclean-core/src/main/java/se/kth/depclean/core/analysis/DefaultProjectDependencyAnalyzer.java index e7c3d9ee..f841753c 100644 --- a/depclean-core/src/main/java/se/kth/depclean/core/analysis/DefaultProjectDependencyAnalyzer.java +++ b/depclean-core/src/main/java/se/kth/depclean/core/analysis/DefaultProjectDependencyAnalyzer.java @@ -39,7 +39,10 @@ @Component(role = ProjectDependencyAnalyzer.class) public class DefaultProjectDependencyAnalyzer implements ProjectDependencyAnalyzer { - public static final String SEPARATOR = "-------------------------------------------------------"; + /** + * If true, the project's classes in target/test-classes are not going to be analyzed. + */ + private boolean isIgnoredTest; /** * ClassAnalyzer @@ -55,6 +58,13 @@ public class DefaultProjectDependencyAnalyzer implements ProjectDependencyAnalyz private final Map> artifactUsedClassesMap = new HashMap<>(); + /** + * Ctor. + */ + public DefaultProjectDependencyAnalyzer(boolean isIgnoredTest) { + this.isIgnoredTest = isIgnoredTest; + } + /** * A map [dependency] -> [dependency classes]. */ @@ -144,12 +154,14 @@ public Map> buildArtifactClassMap(MavenProject project) th } private void buildProjectDependencyClasses(MavenProject project) throws IOException { - /* paths to project compiled classes */ + // Analyze src classes in the project String outputDirectory = project.getBuild().getOutputDirectory(); - String testOutputDirectory = project.getBuild().getTestOutputDirectory(); - /* construct the dependency classes */ collectDependencyClasses(outputDirectory); - collectDependencyClasses(testOutputDirectory); + // Analyze test classes in the project + if (!isIgnoredTest) { + String testOutputDirectory = project.getBuild().getTestOutputDirectory(); + collectDependencyClasses(testOutputDirectory); + } } private void buildDependenciesDependencyClasses(MavenProject project) throws IOException { diff --git a/depclean-core/src/main/java/se/kth/depclean/core/analysis/DependencyAnalyzer.java b/depclean-core/src/main/java/se/kth/depclean/core/analysis/DependencyAnalyzer.java index f265a07e..567a50fd 100644 --- a/depclean-core/src/main/java/se/kth/depclean/core/analysis/DependencyAnalyzer.java +++ b/depclean-core/src/main/java/se/kth/depclean/core/analysis/DependencyAnalyzer.java @@ -26,9 +26,8 @@ /** * Gets the set of classes referenced by a library given either as a jar file or an exploded directory. */ -public interface DependencyAnalyzer -{ - String ROLE = DependencyAnalyzer.class.getName(); +public interface DependencyAnalyzer { Set analyze(URL url) throws IOException; + } diff --git a/depclean-core/src/main/java/se/kth/depclean/core/analysis/asm/DependencyClassFileVisitor.java b/depclean-core/src/main/java/se/kth/depclean/core/analysis/asm/DependencyClassFileVisitor.java index d264875e..6bad5f01 100644 --- a/depclean-core/src/main/java/se/kth/depclean/core/analysis/asm/DependencyClassFileVisitor.java +++ b/depclean-core/src/main/java/se/kth/depclean/core/analysis/asm/DependencyClassFileVisitor.java @@ -85,7 +85,6 @@ public void visitClass(String className, InputStream in) { // inset edge in the graph based on the bytecode analysis DefaultCallGraph.addEdge(className, resultCollector.getDependencies()); - resultCollector.clearClasses(); } catch (IndexOutOfBoundsException | IOException e) { // some bug inside ASM causes an IOB exception. Log it and move on? diff --git a/depclean-maven-plugin/src/main/java/se/kth/depclean/DepCleanMojo.java b/depclean-maven-plugin/src/main/java/se/kth/depclean/DepCleanMojo.java index 1b2adfa9..64d46cf5 100644 --- a/depclean-maven-plugin/src/main/java/se/kth/depclean/DepCleanMojo.java +++ b/depclean-maven-plugin/src/main/java/se/kth/depclean/DepCleanMojo.java @@ -127,6 +127,15 @@ public class DepCleanMojo extends AbstractMojo { @Parameter(property = "ignore.scopes") private Set ignoreScopes; + /** + * If this is true, DepClean will not analyze the test sources in the project, + * and, therefore, the dependencies that are only used for testing will be considered + * unused. This property is useful to detect dependencies that have a compile scope but + * are only used during testing. Hence, these dependencies should have a test scope. + */ + @Parameter(property = "ignore.tests", defaultValue = "false") + private boolean ignoreTests; + /** * If this is true, and DepClean reported any unused direct dependency in the dependency tree, * then the project's build fails immediately after running DepClean. @@ -391,7 +400,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { /* Analyze dependencies usage status */ ProjectDependencyAnalysis projectDependencyAnalysis; - DefaultProjectDependencyAnalyzer dependencyAnalyzer = new DefaultProjectDependencyAnalyzer(); + DefaultProjectDependencyAnalyzer dependencyAnalyzer = new DefaultProjectDependencyAnalyzer(ignoreTests); try { projectDependencyAnalysis = dependencyAnalyzer.analyze(project); } catch (ProjectDependencyAnalyzerException e) { @@ -639,6 +648,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { /* Writing the JSON file with the debloat results */ if (createResultJson) { + printString("Creating depclean-results.json, please wait..."); String pathToJsonFile = project.getBasedir().getAbsolutePath() + File.separator + "depclean-results.json"; String treeFile = project.getBuild().getDirectory() + File.separator + "tree.txt"; /* Copy direct dependencies locally */