← All recipes
Moderne licensed

Find duplicate code

Recipe IDio.moderne.prethink.quality.FindDuplicateCode
Artifactio.moderne.recipe:rewrite-prethink

Detect 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

Usage

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.FindDuplicateCode

If the recipe isn’t available locally, install it with:

mod config recipes jar install io.moderne.recipe:rewrite-prethink:0.11.1

Options

NameTypeDescription
minNodesIntegerMinimum 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
minNodesType2IntegerMinimum 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
minOccurrencesIntegerMinimum number of occurrences for a fragment to be reported as a clone group. Defaults to 2.
e.g. 2
detectType2BooleanWhether to detect renamed (Type-2) clones in addition to exact (Type-1) clones. Defaults to true.
e.g. true
includeTestSourcesBooleanWhether to include test sources (paths under src/test). Defaults to false.
e.g. false
maxOccurrencesPerGroupIntegerCap 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
snippetMaxLinesIntegerMaximum number of lines of the representative fragment to include in the snippet. Defaults to 40.
e.g. 40
minStatementsIntegerMinimum number of consecutive statements that must match to seed a statement-sequence clone. Defaults to 5.
e.g. 5
gapBudgetIntegerMaximum 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
detectStatementSequencesBooleanWhether to detect duplicated runs of consecutive statements (in addition to whole-subtree clones). Defaults to true.
e.g. true
suppressBoilerplateBooleanWhether 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
detectSimilarMethodsBooleanWhether 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