Find duplicate code
Recipe ID
io.moderne.prethink.quality.FindDuplicateCodeArtifactio.moderne.recipe:rewrite-prethinkDetect duplicate and likely-duplicate code across the codebase by AST-subtree fingerprinting and MinHash/LSH method alignment (zero AI). Reports Type-1 (exact), Type-2 (renamed), and Type-3 (gapped: inserted/removed/edited statements) clone groups ranked by the volume of code that would collapse if the duplication were refactored away.
Single recipeProprietary
Add to your build
Get a download tokenThis recipe is Moderne licensed, so the token must belong to a Moderne customer. It replaces YOUR_DOWNLOAD_TOKEN below.
~/.gradle/gradle.properties
codeGenomeUsername=you@example.com
codeGenomeToken=YOUR_DOWNLOAD_TOKEN
build.gradle.kts
plugins {
id("org.openrewrite.rewrite") version("latest.release")
}
rewrite {
activeRecipe("io.moderne.prethink.quality.FindDuplicateCode")
}
repositories {
mavenCentral()
maven {
url = uri("https://artifacts.codegenomeproject.org/maven")
credentials {
username = providers.gradleProperty("codeGenomeUsername").get()
password = providers.gradleProperty("codeGenomeToken").get()
}
}
}
dependencies {
rewrite("io.moderne.recipe:rewrite-prethink:0.14.1")
}
Then run
./gradlew rewriteRunUsage
This recipe has no required configuration options. You’ll need the Moderne CLI configured before running the command below.
mod run . --recipe io.moderne.prethink.quality.FindDuplicateCodeIf the recipe isn’t available locally, install it with:
mod config recipes jar install io.moderne.recipe:rewrite-prethink:RELEASEOptions
| Name | Type | Description |
|---|---|---|
minNodes | Integer | Minimum number of AST nodes a subtree must contain to be considered for exact (Type-1) duplication. Larger values reduce noise. Defaults to 75. e.g. 75 |
minNodesType2 | Integer | Minimum number of AST nodes a subtree must contain to be considered for renamed (Type-2) duplication. Should be at least the Type-1 minimum because anonymization is noisier. Defaults to 110. e.g. 110 |
minOccurrences | Integer | Minimum number of occurrences for a fragment to be reported as a clone group. Defaults to 2. e.g. 2 |
detectType2 | Boolean | Whether to detect renamed (Type-2) clones in addition to exact (Type-1) clones. Defaults to true. e.g. true |
includeTestSources | Boolean | Whether to include test sources (paths under src/test). Defaults to false. e.g. false |
maxOccurrencesPerGroup | Integer | Cap on the number of individual occurrences reported per clone group. The true count is always reported; only the enumerated locations/rows are capped. Defaults to 200. e.g. 200 |
snippetMaxLines | Integer | Maximum number of lines of the representative fragment to include in the snippet. Defaults to 40. e.g. 40 |
minStatements | Integer | Minimum number of consecutive statements that must match to seed a statement-sequence clone. Defaults to 5. e.g. 5 |
gapBudget | Integer | Maximum number of statement edits (insertions, deletions, or substitutions) tolerated inside a statement-sequence clone (Type-3). 0 detects only exact/renamed runs; 1 (the default) also catches copy-paste-then-edit/insert/remove-one-statement. Higher values catch more divergent copies. e.g. 1 |
detectStatementSequences | Boolean | Whether to detect duplicated runs of consecutive statements (in addition to whole-subtree clones). Defaults to true. e.g. true |
suppressBoilerplate | Boolean | Whether to structurally suppress low-value boilerplate: getters/setters, equals/hashCode/toString, runs or blocks composed entirely of trivial data statements (constant declarations, map/collection population), and subtrees dominated by a large string-literal concatenation (embedded doc/JSON/prompt blobs). Suppressed fragments are still descended into, so genuine clones nested inside them are still found. Defaults to true. e.g. true |
detectSimilarMethods | Boolean | Whether to also detect gapped (Type-3) clones between whole methods that share no long run of identical statements, by aligning MinHash/LSH-similar method pairs. Catches copy-edited methods the statement-run detector misses because it needs a run of identical statements to anchor. Defaults to true. e.g. true |
Data tables
Structured output this recipe can produce.
- Duplicate codeGroups of duplicated code detected across the codebase by AST-subtree fingerprinting. One row per clone group; sort by redundant volume to surface the highest-value refactoring targets.
io.moderne.prethink.table.DuplicateCode - Duplicate code occurrencesOne row per individual occurrence of a duplicated fragment, with the machine coordinates a remediation recipe needs to locate and converge each clone. Join to the duplicate code data table on clone group id.
io.moderne.prethink.table.DuplicateCodeOccurrences - Source files that had resultsSource files that were modified by the recipe run.
org.openrewrite.table.SourcesFileResults - Source files that had search resultsSearch results that were found during the recipe run.
org.openrewrite.table.SearchResults - Source files that errored on a recipeThe details of all errors produced by a recipe run.
org.openrewrite.table.SourcesFileErrors - Recipe performanceStatistics used in analyzing the performance of recipes.
org.openrewrite.table.RecipeRunStats