-
Notifications
You must be signed in to change notification settings - Fork 13
Add FindDuplicateClasses recipe #170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Adds a new recipe that detects classes appearing in multiple dependencies on the classpath, similar to basepom's duplicate-finder-maven-plugin. The recipe uses JavaSourceSet.gavToTypes to invert the GAV→types mapping and find types that appear in more than one dependency. Results are reported via a DuplicateClassesReport data table with project, source set, type name, and the dependencies containing the duplicate. Filters out module-info and package-info false positives from multi-release JARs. Fixes moderneinc/customer-requests#878
| import org.openrewrite.java.tree.JavaType; | ||
|
|
||
| import java.util.*; | ||
| import java.util.stream.Collectors; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| import java.util.stream.Collectors; | |
| import static java.util.Collections.emptyList; | |
| import static java.util.stream.Collectors.joining; |
src/main/java/org/openrewrite/java/dependencies/search/FindDuplicateClasses.java
Show resolved
Hide resolved
src/main/java/org/openrewrite/java/dependencies/search/FindDuplicateClasses.java
Show resolved
Hide resolved
|
|
||
| @Override | ||
| public Collection<? extends SourceFile> generate(Accumulator acc, ExecutionContext ctx) { | ||
| return Collections.emptyList(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return Collections.emptyList(); | |
| return emptyList(); |
JavaVisitor is more appropriate since Java source files are more likely to have the JavaSourceSet marker needed for duplicate detection.
| @Override | ||
| public String getDisplayName() { | ||
| return "Find duplicate classes on the classpath"; | ||
| } | ||
|
|
||
| @Override | ||
| public String getDescription() { | ||
| return "Detects classes that appear in multiple dependencies on the classpath. " + | ||
| "This is similar to what the Maven duplicate-finder-maven-plugin does. " + | ||
| "Duplicate classes can cause runtime issues when different versions " + | ||
| "of the same class are loaded."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @Override | |
| public String getDisplayName() { | |
| return "Find duplicate classes on the classpath"; | |
| } | |
| @Override | |
| public String getDescription() { | |
| return "Detects classes that appear in multiple dependencies on the classpath. " + | |
| "This is similar to what the Maven duplicate-finder-maven-plugin does. " + | |
| "Duplicate classes can cause runtime issues when different versions " + | |
| "of the same class are loaded."; | |
| String displayName = "Find duplicate classes on the classpath"; | |
| String description = "Detects classes that appear in multiple dependencies on the classpath. " + | |
| "This is similar to what the Maven duplicate-finder-maven-plugin does. " + | |
| "Duplicate classes can cause runtime issues when different versions " + | |
| "of the same class are loaded."; |
| String additionalDeps = gavs.size() > 2 | ||
| ? gavs.subList(2, gavs.size()).stream().collect(joining(", ")) | ||
| : ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| String additionalDeps = gavs.size() > 2 | |
| ? gavs.subList(2, gavs.size()).stream().collect(joining(", ")) | |
| : ""; | |
| String additionalDeps = gavs.size() > 2 ? | |
| gavs.subList(2, gavs.size()).stream().collect(joining(", ")) : | |
| ""; |
Summary
FindDuplicateClassesrecipe that detects classes appearing in multiple dependencies on the classpathDuplicateClassesReportdata table with project, source set, type name, and conflicting dependenciesmodule-infoandpackage-infofalse positives from multi-release JARsProblem
Duplicate classes on the classpath can cause runtime issues when different versions of the same class are loaded. The basepom
duplicate-finder-maven-pluginhelps detect this, but there was no OpenRewrite equivalent.Solution
The recipe uses
JavaSourceSet.gavToTypesto invert the GAV→types mapping and find types that appear in more than one dependency. ThegavToTypesmap is populated when the full classpath is scanned (e.g., via mod CLI orJavaSourceSet.build()), providing accurate dependency-to-type mappings.Test plan
Existing tests pass
New tests added using real SLF4J binding duplicates (logback-classic vs slf4j-nop)
Tests verify no false positives with single-dependency classpath
Fixes moderneinc/customer-requests#878