From 2e3a14f4328d43c1b0fc39cf5370374a16026e22 Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Thu, 7 Sep 2023 13:05:06 -0400 Subject: [PATCH 1/4] track dependency usages by declaring class --- .../DefaultProjectDependencyAnalyzer.java | 53 +++++------ .../analyzer/DependencyAnalyzer.java | 17 +++- .../dependency/analyzer/DependencyUsage.java | 92 +++++++++++++++++++ .../analyzer/ProjectDependencyAnalysis.java | 56 ++++++----- .../analyzer/asm/ASMDependencyAnalyzer.java | 7 +- .../asm/DefaultAnnotationVisitor.java | 27 ++++-- .../analyzer/asm/DefaultClassVisitor.java | 73 ++++++++------- .../analyzer/asm/DefaultFieldVisitor.java | 14 ++- .../analyzer/asm/DefaultMethodVisitor.java | 87 +++++++++++------- .../analyzer/asm/DefaultSignatureVisitor.java | 16 +++- .../asm/DependencyClassFileVisitor.java | 36 +++++--- .../analyzer/asm/ResultCollector.java | 45 +++++---- .../analyzer/asm/DependencyVisitorTest.java | 21 ++--- 13 files changed, 365 insertions(+), 179 deletions(-) create mode 100644 src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyUsage.java diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java index 489afd16..914c805a 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java @@ -25,14 +25,7 @@ import java.io.File; import java.io.IOException; import java.net.URL; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -59,23 +52,25 @@ public class DefaultProjectDependencyAnalyzer implements ProjectDependencyAnalyz @Inject private DependencyAnalyzer dependencyAnalyzer; - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public ProjectDependencyAnalysis analyze(MavenProject project) throws ProjectDependencyAnalyzerException { try { Map> artifactClassMap = buildArtifactClassMap(project); - Set mainDependencyClasses = buildMainDependencyClasses(project); - Set testDependencyClasses = buildTestDependencyClasses(project); + Set mainDependencyClasses = buildMainDependencyClasses(project); + Set testDependencyClasses = buildTestDependencyClasses(project); - Set dependencyClasses = new HashSet<>(); + Set dependencyClasses = new HashSet<>(); dependencyClasses.addAll(mainDependencyClasses); dependencyClasses.addAll(testDependencyClasses); - Set testOnlyDependencyClasses = + Set testOnlyDependencyClasses = buildTestOnlyDependencyClasses(mainDependencyClasses, testDependencyClasses); - Map> usedArtifacts = buildUsedArtifacts(artifactClassMap, dependencyClasses); + Map> usedArtifacts = buildUsedArtifacts(artifactClassMap, dependencyClasses); Set mainUsedArtifacts = buildUsedArtifacts(artifactClassMap, mainDependencyClasses).keySet(); @@ -87,7 +82,7 @@ public ProjectDependencyAnalysis analyze(MavenProject project) throws ProjectDep Set usedDeclaredArtifacts = new LinkedHashSet<>(declaredArtifacts); usedDeclaredArtifacts.retainAll(usedArtifacts.keySet()); - Map> usedUndeclaredArtifactsWithClasses = new LinkedHashMap<>(usedArtifacts); + Map> usedUndeclaredArtifactsWithClasses = new LinkedHashMap<>(usedArtifacts); Set usedUndeclaredArtifacts = removeAll(usedUndeclaredArtifactsWithClasses.keySet(), declaredArtifacts); usedUndeclaredArtifactsWithClasses.keySet().retainAll(usedUndeclaredArtifacts); @@ -184,27 +179,27 @@ private Map> buildArtifactClassMap(MavenProject project) t return artifactClassMap; } - private static Set buildTestOnlyDependencyClasses( - Set mainDependencyClasses, Set testDependencyClasses) { - Set testOnlyDependencyClasses = new HashSet<>(testDependencyClasses); + private static Set buildTestOnlyDependencyClasses( + Set mainDependencyClasses, Set testDependencyClasses) { + Set testOnlyDependencyClasses = new HashSet<>(testDependencyClasses); testOnlyDependencyClasses.removeAll(mainDependencyClasses); return testOnlyDependencyClasses; } - private Set buildMainDependencyClasses(MavenProject project) throws IOException { + private Set buildMainDependencyClasses(MavenProject project) throws IOException { String outputDirectory = project.getBuild().getOutputDirectory(); return buildDependencyClasses(outputDirectory); } - private Set buildTestDependencyClasses(MavenProject project) throws IOException { + private Set buildTestDependencyClasses(MavenProject project) throws IOException { String testOutputDirectory = project.getBuild().getTestOutputDirectory(); return buildDependencyClasses(testOutputDirectory); } - private Set buildDependencyClasses(String path) throws IOException { + private Set buildDependencyClasses(String path) throws IOException { URL url = new File(path).toURI().toURL(); - return dependencyAnalyzer.analyze(url); + return dependencyAnalyzer.analyzeUsages(url); } private static Set buildDeclaredArtifacts(MavenProject project) { @@ -217,20 +212,20 @@ private static Set buildDeclaredArtifacts(MavenProject project) { return declaredArtifacts; } - private static Map> buildUsedArtifacts( - Map> artifactClassMap, Set dependencyClasses) { - Map> usedArtifacts = new HashMap<>(); + private static Map> buildUsedArtifacts( + Map> artifactClassMap, Set dependencyClasses) { + Map> usedArtifacts = new HashMap<>(); - for (String className : dependencyClasses) { - Artifact artifact = findArtifactForClassName(artifactClassMap, className); + for (DependencyUsage classUsage : dependencyClasses) { + Artifact artifact = findArtifactForClassName(artifactClassMap, classUsage.getDependencyClass()); if (artifact != null) { - Set classesFromArtifact = usedArtifacts.get(artifact); + Set classesFromArtifact = usedArtifacts.get(artifact); if (classesFromArtifact == null) { classesFromArtifact = new HashSet<>(); usedArtifacts.put(artifact, classesFromArtifact); } - classesFromArtifact.add(className); + classesFromArtifact.add(classUsage); } } diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyAnalyzer.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyAnalyzer.java index d366c6b7..7e7fa399 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyAnalyzer.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyAnalyzer.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.net.URL; import java.util.Set; +import java.util.stream.Collectors; /** * Gets the set of classes referenced by a library given either as a jar file or an exploded directory. @@ -36,5 +37,19 @@ public interface DependencyAnalyzer { * @return the set of class names referenced by the library * @throws IOException if an error occurs reading a JAR or .class file */ - Set analyze(URL url) throws IOException; + default Set analyze(URL url) throws IOException { + return analyzeUsages(url).stream() + .map(DependencyUsage::getDependencyClass) + .collect(Collectors.toSet()); + } + + /** + *

analyzeUsages.

+ * + * @param url the JAR file or directory to analyze + * @return the set of class names referenced by the library, paired with the + * classes declaring those references. + * @throws IOException if an error occurs reading a JAR or .class file + */ + Set analyzeUsages(URL url) throws IOException; } diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyUsage.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyUsage.java new file mode 100644 index 00000000..6b2109d2 --- /dev/null +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/DependencyUsage.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.shared.dependency.analyzer; + +/** + * Usage of a dependency class by a project class. + * + * @author Jonathan Haber + */ +public class DependencyUsage { + + private final String dependencyClass; + + private final String usedBy; + + public DependencyUsage(String dependencyClass, String usedBy) { + this.dependencyClass = dependencyClass; + this.usedBy = usedBy; + } + + /** + * @return the dependency class used by the project class + */ + public String getDependencyClass() { + return dependencyClass; + } + + /** + * @return the project class using the dependency class + */ + public String getUsedBy() { + return usedBy; + } + + /* + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + int hashCode = dependencyClass.hashCode(); + hashCode = (hashCode * 37) + usedBy.hashCode(); + + return hashCode; + } + + /* + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object object) { + if (object instanceof DependencyUsage) { + DependencyUsage usage = (DependencyUsage) object; + + return getDependencyClass().equals(usage.getDependencyClass()) + && getUsedBy().equals(usage.getUsedBy()); + } + + return false; + } + + /* + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuilder buffer = new StringBuilder(); + + buffer.append("dependencyClass=").append(getDependencyClass()); + buffer.append(","); + buffer.append("usedBy=").append(getUsedBy()); + + buffer.insert(0, "["); + buffer.insert(0, getClass().getName()); + + buffer.append("]"); + + return buffer.toString(); + } +} diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/ProjectDependencyAnalysis.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/ProjectDependencyAnalysis.java index 1f71550a..e8feceea 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/ProjectDependencyAnalysis.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/ProjectDependencyAnalysis.java @@ -18,14 +18,8 @@ */ package org.apache.maven.shared.dependency.analyzer; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; import org.apache.maven.artifact.Artifact; @@ -39,7 +33,7 @@ public class ProjectDependencyAnalysis { private final Set usedDeclaredArtifacts; - private final Map> usedUndeclaredArtifacts; + private final Map> usedUndeclaredArtifacts; private final Set unusedDeclaredArtifacts; @@ -49,13 +43,13 @@ public class ProjectDependencyAnalysis { *

Constructor for ProjectDependencyAnalysis.

*/ public ProjectDependencyAnalysis() { - this(null, (Map>) null, null, null); + this(null, (Map>) null, null, null); } /** *

Constructor for ProjectDependencyAnalysis to maintain compatibility with old API

* - * @param usedDeclaredArtifacts artifacts both used and declared + * @param usedDeclaredArtifacts artifacts both used and declared * @param usedUndeclaredArtifacts artifacts used but not declared * @param unusedDeclaredArtifacts artifacts declared but not used */ @@ -69,9 +63,9 @@ public ProjectDependencyAnalysis( /** *

Constructor for ProjectDependencyAnalysis.

* - * @param usedDeclaredArtifacts artifacts both used and declared - * @param usedUndeclaredArtifacts artifacts used but not declared - * @param unusedDeclaredArtifacts artifacts declared but not used + * @param usedDeclaredArtifacts artifacts both used and declared + * @param usedUndeclaredArtifacts artifacts used but not declared + * @param unusedDeclaredArtifacts artifacts declared but not used * @param testArtifactsWithNonTestScope artifacts only used in tests but not declared with test scope */ public ProjectDependencyAnalysis( @@ -88,7 +82,7 @@ public ProjectDependencyAnalysis( public ProjectDependencyAnalysis( Set usedDeclaredArtifacts, - Map> usedUndeclaredArtifacts, + Map> usedUndeclaredArtifacts, Set unusedDeclaredArtifacts, Set testArtifactsWithNonTestScope) { this.usedDeclaredArtifacts = safeCopy(usedDeclaredArtifacts); @@ -121,6 +115,20 @@ public Set getUsedUndeclaredArtifacts() { * @return artifacts used but not declared */ public Map> getUsedUndeclaredArtifactsWithClasses() { + Map> usedUndeclaredArtifactsWithClasses = new HashMap<>(); + + for (Map.Entry> entry : usedUndeclaredArtifacts.entrySet()) { + usedUndeclaredArtifactsWithClasses.put( + entry.getKey(), + entry.getValue().stream() + .map(DependencyUsage::getDependencyClass) + .collect(Collectors.toSet())); + } + + return usedUndeclaredArtifactsWithClasses; + } + + public Map> getUsedUndeclaredArtifactsWithUsages() { return safeCopy(usedUndeclaredArtifacts); } @@ -136,7 +144,7 @@ public Set getUnusedDeclaredArtifacts() { /** * Returns artifacts only used in tests but not declared with test scope. * - * @return artifacts only used in tests but not declared with test scope + * @return artifacts only used in tests but not declared with test scope */ public Set getTestArtifactsWithNonTestScope() { return safeCopy(testArtifactsWithNonTestScope); @@ -228,7 +236,9 @@ public int hashCode() { return hashCode; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public boolean equals(Object object) { if (object instanceof ProjectDependencyAnalysis) { @@ -294,29 +304,29 @@ private Set safeCopy(Set set) { return (set == null) ? Collections.emptySet() : Collections.unmodifiableSet(new LinkedHashSet<>(set)); } - private static Map> safeCopy(Map> origMap) { + private static Map> safeCopy(Map> origMap) { if (origMap == null) { return Collections.emptyMap(); } - Map> map = new HashMap<>(); + Map> map = new HashMap<>(); - for (Map.Entry> e : origMap.entrySet()) { + for (Map.Entry> e : origMap.entrySet()) { map.put(e.getKey(), Collections.unmodifiableSet(new LinkedHashSet<>(e.getValue()))); } return map; } - private static Map> mapWithKeys(Set keys) { + private static Map> mapWithKeys(Set keys) { if (keys == null) { return Collections.emptyMap(); } - Map> map = new HashMap<>(); + Map> map = new HashMap<>(); for (Artifact k : keys) { - map.put(k, Collections.emptySet()); + map.put(k, Collections.emptySet()); } return map; diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzer.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzer.java index efd4869e..8916cbad 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzer.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ASMDependencyAnalyzer.java @@ -27,6 +27,7 @@ import org.apache.maven.shared.dependency.analyzer.ClassFileVisitorUtils; import org.apache.maven.shared.dependency.analyzer.DependencyAnalyzer; +import org.apache.maven.shared.dependency.analyzer.DependencyUsage; /** * ASMDependencyAnalyzer @@ -36,13 +37,13 @@ @Named @Singleton public class ASMDependencyAnalyzer implements DependencyAnalyzer { - /** {@inheritDoc} */ + @Override - public Set analyze(URL url) throws IOException { + public Set analyzeUsages(URL url) throws IOException { DependencyClassFileVisitor visitor = new DependencyClassFileVisitor(); ClassFileVisitorUtils.accept(url, visitor); - return visitor.getDependencies(); + return visitor.getDependencyUsages(); } } diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultAnnotationVisitor.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultAnnotationVisitor.java index b5792731..1c7f4bf1 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultAnnotationVisitor.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultAnnotationVisitor.java @@ -31,39 +31,50 @@ public class DefaultAnnotationVisitor extends AnnotationVisitor { private final ResultCollector resultCollector; + private final String usedByClass; + /** *

Constructor for DefaultAnnotationVisitor.

* * @param resultCollector a {@link org.apache.maven.shared.dependency.analyzer.asm.ResultCollector} object. */ - public DefaultAnnotationVisitor(ResultCollector resultCollector) { + public DefaultAnnotationVisitor(ResultCollector resultCollector, String usedByClass) { super(Opcodes.ASM9); this.resultCollector = resultCollector; + this.usedByClass = usedByClass; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visit(final String name, final Object value) { if (value instanceof Type) { - resultCollector.addType((Type) value); + resultCollector.addType(usedByClass, (Type) value); } } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitEnum(final String name, final String desc, final String value) { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public AnnotationVisitor visitAnnotation(final String name, final String desc) { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); return this; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public AnnotationVisitor visitArray(final String name) { return this; diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultClassVisitor.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultClassVisitor.java index 2d683e6f..2d37c180 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultClassVisitor.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultClassVisitor.java @@ -18,12 +18,7 @@ */ package org.apache.maven.shared.dependency.analyzer.asm; -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; +import org.objectweb.asm.*; import org.objectweb.asm.signature.SignatureReader; import org.objectweb.asm.signature.SignatureVisitor; @@ -44,37 +39,41 @@ public class DefaultClassVisitor extends ClassVisitor { private final MethodVisitor methodVisitor; + private final String usedByClass; + /** *

Constructor for DefaultClassVisitor.

* - * @param signatureVisitor a {@link org.objectweb.asm.signature.SignatureVisitor} object. + * @param signatureVisitor a {@link org.objectweb.asm.signature.SignatureVisitor} object. * @param annotationVisitor a {@link org.objectweb.asm.AnnotationVisitor} object. - * @param fieldVisitor a {@link org.objectweb.asm.FieldVisitor} object. - * @param methodVisitor a {@link org.objectweb.asm.MethodVisitor} object. - * @param resultCollector a {@link org.apache.maven.shared.dependency.analyzer.asm.ResultCollector} object. + * @param fieldVisitor a {@link org.objectweb.asm.FieldVisitor} object. + * @param methodVisitor a {@link org.objectweb.asm.MethodVisitor} object. + * @param resultCollector a {@link org.apache.maven.shared.dependency.analyzer.asm.ResultCollector} object. */ public DefaultClassVisitor( SignatureVisitor signatureVisitor, AnnotationVisitor annotationVisitor, FieldVisitor fieldVisitor, MethodVisitor methodVisitor, - ResultCollector resultCollector) { + ResultCollector resultCollector, + String usedByClass) { super(Opcodes.ASM9); this.signatureVisitor = signatureVisitor; this.annotationVisitor = annotationVisitor; this.fieldVisitor = fieldVisitor; this.methodVisitor = methodVisitor; this.resultCollector = resultCollector; + this.usedByClass = usedByClass; } /** *

visit.

* - * @param version a int. - * @param access a int. - * @param name a {@link java.lang.String} object. - * @param signature a {@link java.lang.String} object. - * @param superName a {@link java.lang.String} object. + * @param version a int. + * @param access a int. + * @param name a {@link java.lang.String} object. + * @param signature a {@link java.lang.String} object. + * @param superName a {@link java.lang.String} object. * @param interfaces an array of {@link java.lang.String} objects. */ @Override @@ -86,33 +85,37 @@ public void visit( final String superName, final String[] interfaces) { if (signature == null) { - resultCollector.addName(superName); - resultCollector.addNames(interfaces); + resultCollector.addName(usedByClass, superName); + resultCollector.addNames(usedByClass, interfaces); } else { addSignature(signature); } } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); return annotationVisitor; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public FieldVisitor visitField( final int access, final String name, final String desc, final String signature, final Object value) { if (signature == null) { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); } else { addTypeSignature(signature); } if (value instanceof Type) { - resultCollector.addType((Type) value); + resultCollector.addType(usedByClass, (Type) value); } return fieldVisitor; @@ -121,10 +124,10 @@ public FieldVisitor visitField( /** *

visitMethod.

* - * @param access a int. - * @param name a {@link java.lang.String} object. - * @param desc a {@link java.lang.String} object. - * @param signature a {@link java.lang.String} object. + * @param access a int. + * @param name a {@link java.lang.String} object. + * @param desc a {@link java.lang.String} object. + * @param signature a {@link java.lang.String} object. * @param exceptions an array of {@link java.lang.String} objects. * @return a {@link org.objectweb.asm.MethodVisitor} object. */ @@ -132,26 +135,30 @@ public FieldVisitor visitField( public MethodVisitor visitMethod( final int access, final String name, final String desc, final String signature, final String[] exceptions) { if (signature == null) { - resultCollector.addMethodDesc(desc); + resultCollector.addMethodDesc(usedByClass, desc); } else { addSignature(signature); } - resultCollector.addNames(exceptions); + resultCollector.addNames(usedByClass, exceptions); return methodVisitor; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitNestHost(final String nestHost) { - resultCollector.addName(nestHost); + resultCollector.addName(usedByClass, nestHost); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitNestMember(final String nestMember) { - resultCollector.addName(nestMember); + resultCollector.addName(usedByClass, nestMember); } private void addSignature(final String signature) { diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultFieldVisitor.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultFieldVisitor.java index 6f7e1407..074e35e7 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultFieldVisitor.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultFieldVisitor.java @@ -33,22 +33,28 @@ public class DefaultFieldVisitor extends FieldVisitor { private final ResultCollector resultCollector; + private final String usedByClass; + /** *

Constructor for DefaultFieldVisitor.

* * @param annotationVisitor a {@link org.objectweb.asm.AnnotationVisitor} object. - * @param resultCollector a {@link org.apache.maven.shared.dependency.analyzer.asm.ResultCollector} object. + * @param resultCollector a {@link org.apache.maven.shared.dependency.analyzer.asm.ResultCollector} object. */ - public DefaultFieldVisitor(AnnotationVisitor annotationVisitor, ResultCollector resultCollector) { + public DefaultFieldVisitor( + AnnotationVisitor annotationVisitor, ResultCollector resultCollector, String usedByClass) { super(Opcodes.ASM9); this.annotationVisitor = annotationVisitor; this.resultCollector = resultCollector; + this.usedByClass = usedByClass; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); return annotationVisitor; } diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java index cdf0aa18..e567e578 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java @@ -18,12 +18,7 @@ */ package org.apache.maven.shared.dependency.analyzer.asm; -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.TypePath; +import org.objectweb.asm.*; import org.objectweb.asm.signature.SignatureReader; import org.objectweb.asm.signature.SignatureVisitor; @@ -40,68 +35,86 @@ public class DefaultMethodVisitor extends MethodVisitor { private final ResultCollector resultCollector; + private final String usedByClass; + /** *

Constructor for DefaultMethodVisitor.

* * @param annotationVisitor a {@link org.objectweb.asm.AnnotationVisitor} object. - * @param signatureVisitor a {@link org.objectweb.asm.signature.SignatureVisitor} object. - * @param resultCollector a {@link org.apache.maven.shared.dependency.analyzer.asm.ResultCollector} object. + * @param signatureVisitor a {@link org.objectweb.asm.signature.SignatureVisitor} object. + * @param resultCollector a {@link org.apache.maven.shared.dependency.analyzer.asm.ResultCollector} object. */ public DefaultMethodVisitor( - AnnotationVisitor annotationVisitor, SignatureVisitor signatureVisitor, ResultCollector resultCollector) { + AnnotationVisitor annotationVisitor, + SignatureVisitor signatureVisitor, + ResultCollector resultCollector, + String usedByClass) { super(Opcodes.ASM9); this.annotationVisitor = annotationVisitor; this.signatureVisitor = signatureVisitor; this.resultCollector = resultCollector; + this.usedByClass = usedByClass; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); return annotationVisitor; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); return annotationVisitor; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public AnnotationVisitor visitParameterAnnotation(final int parameter, final String desc, final boolean visible) { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); return annotationVisitor; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public AnnotationVisitor visitLocalVariableAnnotation( int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); return annotationVisitor; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitTypeInsn(final int opcode, final String desc) { if (desc.charAt(0) == '[') { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); } else { - resultCollector.addName(desc); + resultCollector.addName(usedByClass, desc); } } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { - resultCollector.addName(owner); + resultCollector.addName(usedByClass, owner); /* * NOTE: Merely accessing a field does not impose a direct dependency on its type. For example, the code line * java.lang.Object var = bean.field; does not directly depend on the type of the field. A direct @@ -110,33 +123,43 @@ public void visitFieldInsn(final int opcode, final String owner, final String na */ } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - resultCollector.addName(owner); + resultCollector.addName(usedByClass, owner); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitLdcInsn(final Object cst) { if (cst instanceof Type) { - resultCollector.addType((Type) cst); + resultCollector.addType(usedByClass, (Type) cst); } } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitMultiANewArrayInsn(final String desc, final int dims) { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) { - resultCollector.addName(type); + resultCollector.addName(usedByClass, type); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitLocalVariable( final String name, @@ -146,7 +169,7 @@ public void visitLocalVariable( final Label end, final int index) { if (signature == null) { - resultCollector.addDesc(desc); + resultCollector.addDesc(usedByClass, desc); } else { addTypeSignature(signature); } diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultSignatureVisitor.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultSignatureVisitor.java index d09bca37..89bd1a4a 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultSignatureVisitor.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultSignatureVisitor.java @@ -29,26 +29,32 @@ */ public class DefaultSignatureVisitor extends SignatureVisitor { private final ResultCollector resultCollector; + private final String usedByClass; /** *

Constructor for DefaultSignatureVisitor.

* * @param resultCollector a {@link org.apache.maven.shared.dependency.analyzer.asm.ResultCollector} object. */ - public DefaultSignatureVisitor(ResultCollector resultCollector) { + public DefaultSignatureVisitor(ResultCollector resultCollector, String usedByClass) { super(Opcodes.ASM9); this.resultCollector = resultCollector; + this.usedByClass = usedByClass; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitClassType(final String name) { - resultCollector.addName(name); + resultCollector.addName(usedByClass, name); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitInnerClassType(final String name) { - resultCollector.addName(name); + resultCollector.addName(usedByClass, name); } } diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyClassFileVisitor.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyClassFileVisitor.java index 8f701164..b37fea6c 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyClassFileVisitor.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyClassFileVisitor.java @@ -24,11 +24,8 @@ import org.apache.commons.io.IOUtils; import org.apache.maven.shared.dependency.analyzer.ClassFileVisitor; -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; +import org.apache.maven.shared.dependency.analyzer.DependencyUsage; +import org.objectweb.asm.*; import org.objectweb.asm.signature.SignatureVisitor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,7 +47,9 @@ public class DependencyClassFileVisitor implements ClassFileVisitor { */ public DependencyClassFileVisitor() {} - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void visitClass(String className, InputStream in) { try { @@ -59,15 +58,16 @@ public void visitClass(String className, InputStream in) { final Set constantPoolClassRefs = ConstantPoolParser.getConstantPoolClassReferences(byteCode); for (String string : constantPoolClassRefs) { - resultCollector.addName(string); + resultCollector.addName(className, string); } - AnnotationVisitor annotationVisitor = new DefaultAnnotationVisitor(resultCollector); - SignatureVisitor signatureVisitor = new DefaultSignatureVisitor(resultCollector); - FieldVisitor fieldVisitor = new DefaultFieldVisitor(annotationVisitor, resultCollector); - MethodVisitor mv = new DefaultMethodVisitor(annotationVisitor, signatureVisitor, resultCollector); - ClassVisitor classVisitor = - new DefaultClassVisitor(signatureVisitor, annotationVisitor, fieldVisitor, mv, resultCollector); + AnnotationVisitor annotationVisitor = new DefaultAnnotationVisitor(resultCollector, className); + SignatureVisitor signatureVisitor = new DefaultSignatureVisitor(resultCollector, className); + FieldVisitor fieldVisitor = new DefaultFieldVisitor(annotationVisitor, resultCollector, className); + MethodVisitor mv = + new DefaultMethodVisitor(annotationVisitor, signatureVisitor, resultCollector, className); + ClassVisitor classVisitor = new DefaultClassVisitor( + signatureVisitor, annotationVisitor, fieldVisitor, mv, resultCollector, className); reader.accept(classVisitor, 0); } catch (IOException exception) { @@ -90,4 +90,14 @@ public void visitClass(String className, InputStream in) { public Set getDependencies() { return resultCollector.getDependencies(); } + + /** + *

getDependencyUsages.

+ * + * @return the set of classes referenced by visited class files, paired with + * classes declaring the references. + */ + public Set getDependencyUsages() { + return resultCollector.getDependencyUsages(); + } } diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java index f42065fb..90701aaf 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java @@ -20,7 +20,9 @@ import java.util.HashSet; import java.util.Set; +import java.util.stream.Collectors; +import org.apache.maven.shared.dependency.analyzer.DependencyUsage; import org.objectweb.asm.Type; /** @@ -30,7 +32,7 @@ */ public class ResultCollector { - private final Set classes = new HashSet<>(); + private final Set classUsages = new HashSet<>(); /** *

getDependencies.

@@ -38,7 +40,18 @@ public class ResultCollector { * @return a {@link java.util.Set} object. */ public Set getDependencies() { - return classes; + return getDependencyUsages().stream() + .map(DependencyUsage::getDependencyClass) + .collect(Collectors.toSet()); + } + + /** + *

getDependencyUsages.

+ * + * @return a {@link java.util.Set} object. + */ + public Set getDependencyUsages() { + return classUsages; } /** @@ -46,7 +59,7 @@ public Set getDependencies() { * * @param name a {@link java.lang.String} object. */ - public void addName(String name) { + public void addName(final String usedByClass, String name) { if (name == null) { return; } @@ -65,21 +78,21 @@ public void addName(String name) { } // decode internal representation - add(name.replace('/', '.')); + add(usedByClass, name.replace('/', '.')); } - void addDesc(final String desc) { - addType(Type.getType(desc)); + void addDesc(final String usedByClass, final String desc) { + addType(usedByClass, Type.getType(desc)); } - void addType(final Type t) { + void addType(final String usedByClass, final Type t) { switch (t.getSort()) { case Type.ARRAY: - addType(t.getElementType()); + addType(usedByClass, t.getElementType()); break; case Type.OBJECT: - addName(t.getClassName()); + addName(usedByClass, t.getClassName()); break; default: @@ -91,30 +104,30 @@ void addType(final Type t) { * * @param name a {@link java.lang.String} object. */ - public void add(String name) { + public void add(final String usedByClass, final String name) { // inner classes have equivalent compilation requirement as container class if (name.indexOf('$') < 0) { - classes.add(name); + classUsages.add(new DependencyUsage(name, usedByClass)); } } - void addNames(final String[] names) { + void addNames(final String usedByClass, final String[] names) { if (names == null) { return; } for (String name : names) { - addName(name); + addName(usedByClass, name); } } - void addMethodDesc(final String desc) { - addType(Type.getReturnType(desc)); + void addMethodDesc(final String usedByClass, final String desc) { + addType(usedByClass, Type.getReturnType(desc)); Type[] types = Type.getArgumentTypes(desc); for (Type type : types) { - addType(type); + addType(usedByClass, type); } } } diff --git a/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyVisitorTest.java b/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyVisitorTest.java index 8ee3c449..ce23138d 100644 --- a/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyVisitorTest.java +++ b/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/DependencyVisitorTest.java @@ -20,13 +20,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.Attribute; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; +import org.objectweb.asm.*; import org.objectweb.asm.signature.SignatureVisitor; import static org.assertj.core.api.Assertions.assertThat; @@ -41,13 +35,16 @@ class DependencyVisitorTest { private DefaultClassVisitor visitor; private MethodVisitor mv; + private String usedByClass = "com.example.MyClass"; + @BeforeEach void setUp() { - AnnotationVisitor annotationVisitor = new DefaultAnnotationVisitor(resultCollector); - SignatureVisitor signatureVisitor = new DefaultSignatureVisitor(resultCollector); - FieldVisitor fieldVisitor = new DefaultFieldVisitor(annotationVisitor, resultCollector); - mv = new DefaultMethodVisitor(annotationVisitor, signatureVisitor, resultCollector); - visitor = new DefaultClassVisitor(signatureVisitor, annotationVisitor, fieldVisitor, mv, resultCollector); + AnnotationVisitor annotationVisitor = new DefaultAnnotationVisitor(resultCollector, usedByClass); + SignatureVisitor signatureVisitor = new DefaultSignatureVisitor(resultCollector, usedByClass); + FieldVisitor fieldVisitor = new DefaultFieldVisitor(annotationVisitor, resultCollector, usedByClass); + mv = new DefaultMethodVisitor(annotationVisitor, signatureVisitor, resultCollector, usedByClass); + visitor = new DefaultClassVisitor( + signatureVisitor, annotationVisitor, fieldVisitor, mv, resultCollector, usedByClass); } @Test From 227a10a23c25ce5402e6ce7480d4f0b802dc301f Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Thu, 21 Sep 2023 16:34:20 -0400 Subject: [PATCH 2/4] fix buildTestOnlyDependencyClasses by matching on dependencyClass, not usage hash --- .../analyzer/DefaultProjectDependencyAnalyzer.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java index 914c805a..4d26c9cf 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java @@ -28,6 +28,7 @@ import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.stream.Collectors; import org.apache.maven.artifact.Artifact; import org.apache.maven.project.MavenProject; @@ -182,7 +183,10 @@ private Map> buildArtifactClassMap(MavenProject project) t private static Set buildTestOnlyDependencyClasses( Set mainDependencyClasses, Set testDependencyClasses) { Set testOnlyDependencyClasses = new HashSet<>(testDependencyClasses); - testOnlyDependencyClasses.removeAll(mainDependencyClasses); + Set mainDepClassNames = mainDependencyClasses.stream() + .map(DependencyUsage::getDependencyClass) + .collect(Collectors.toSet()); + testOnlyDependencyClasses.removeIf(u -> mainDepClassNames.contains(u.getDependencyClass())); return testOnlyDependencyClasses; } From 6a6e02fdabc20e50b298fc8ad04e45cd50eb1a8c Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Fri, 31 May 2024 11:42:45 -0400 Subject: [PATCH 3/4] re-apply used by classes --- .../dependency/analyzer/asm/DefaultMethodVisitor.java | 6 +++--- .../shared/dependency/analyzer/asm/ResultCollector.java | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java index 85daa963..075cf107 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java @@ -18,8 +18,6 @@ */ package org.apache.maven.shared.dependency.analyzer.asm; -import java.util.Arrays; - import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Handle; import org.objectweb.asm.Label; @@ -30,6 +28,8 @@ import org.objectweb.asm.signature.SignatureReader; import org.objectweb.asm.signature.SignatureVisitor; +import java.util.Arrays; + /** * Computes the set of classes referenced by visited code. * Inspired by org.objectweb.asm.depend.DependencyVisitor in the ASM dependencies example. @@ -195,6 +195,6 @@ public void visitInvokeDynamicInsn( Arrays.stream(bootstrapMethodArguments) .filter(Type.class::isInstance) .map(Type.class::cast) - .forEach(resultCollector::addType); + .forEach(t -> resultCollector.addType(usedByClass, t)); } } diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java index 519daa50..4c7f3e8a 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java @@ -18,13 +18,13 @@ */ package org.apache.maven.shared.dependency.analyzer.asm; +import org.apache.maven.shared.dependency.analyzer.DependencyUsage; +import org.objectweb.asm.Type; + import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; -import org.apache.maven.shared.dependency.analyzer.DependencyUsage; -import org.objectweb.asm.Type; - /** *

ResultCollector class.

* @@ -92,7 +92,7 @@ void addType(final String usedByClass, final Type t) { break; case Type.METHOD: - addMethodDesc(t.getDescriptor()); + addMethodDesc(usedByClass, t.getDescriptor()); break; case Type.OBJECT: From 8a914c1d6c9a4e3b7768fcacb945226d86df679d Mon Sep 17 00:00:00 2001 From: Jared Stehler Date: Fri, 31 May 2024 11:45:37 -0400 Subject: [PATCH 4/4] spotless formatting --- .../analyzer/DefaultProjectDependencyAnalyzer.java | 5 +++-- .../dependency/analyzer/asm/DefaultMethodVisitor.java | 4 ++-- .../shared/dependency/analyzer/asm/ResultCollector.java | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java index 36f6d01b..c943a5b2 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/DefaultProjectDependencyAnalyzer.java @@ -25,8 +25,8 @@ import java.io.File; import java.io.IOException; import java.net.URL; -import java.util.Collection; import java.util.*; +import java.util.Collection; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; @@ -208,7 +208,8 @@ private Set buildTestDependencyClasses(MavenProject project, Cl return buildDependencyClasses(testOutputDirectory, excludedClasses); } - private Set buildDependencyClasses(String path, ClassesPatterns excludedClasses) throws IOException { + private Set buildDependencyClasses(String path, ClassesPatterns excludedClasses) + throws IOException { URL url = new File(path).toURI().toURL(); return dependencyAnalyzer.analyzeUsages(url, excludedClasses); diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java index 075cf107..c1b4ce7b 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/DefaultMethodVisitor.java @@ -18,6 +18,8 @@ */ package org.apache.maven.shared.dependency.analyzer.asm; +import java.util.Arrays; + import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Handle; import org.objectweb.asm.Label; @@ -28,8 +30,6 @@ import org.objectweb.asm.signature.SignatureReader; import org.objectweb.asm.signature.SignatureVisitor; -import java.util.Arrays; - /** * Computes the set of classes referenced by visited code. * Inspired by org.objectweb.asm.depend.DependencyVisitor in the ASM dependencies example. diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java index 4c7f3e8a..65e39373 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java @@ -18,13 +18,13 @@ */ package org.apache.maven.shared.dependency.analyzer.asm; -import org.apache.maven.shared.dependency.analyzer.DependencyUsage; -import org.objectweb.asm.Type; - import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; +import org.apache.maven.shared.dependency.analyzer.DependencyUsage; +import org.objectweb.asm.Type; + /** *

ResultCollector class.

*