Current section
Files
Jump to
Current section
Files
lib/ex_dna.ex
defmodule ExDNA do
@moduledoc """
Code duplication detector for Elixir, powered by native AST analysis.
ExDNA understands code structure, not just text. It normalizes variable names,
abstracts literals, and compares AST subtrees — so renamed copies and
near-miss clones are caught too. Each clone comes with a concrete refactoring
suggestion.
## Quick start
report = ExDNA.analyze("lib/")
report.clones #=> [%ExDNA.Detection.Clone{}, ...]
report.stats #=> %{files_analyzed: 42, total_clones: 3, ...}
## Clone types
- **Type I** — exact copies (modulo whitespace/comments)
- **Type II** — renamed variables and/or changed literals
- **Type III** — near-miss clones (similar structure ± edits)
## Configuration
Pass options to `analyze/1` or configure in `.ex_dna.exs`:
%{
min_mass: 30,
min_similarity: 0.85,
paths: ["lib/"],
ignore: ["lib/my_app_web/templates/**"]
}
See the README for the full option reference.
"""
alias ExDNA.{Config, Detection, Report}
@type path_or_paths :: String.t() | [String.t()]
@doc """
Analyze files for code duplication.
Accepts a path string, a list of paths, or a keyword list of options.
## Options
* `:paths` — list of file/directory paths to scan (default: `["lib/"]`)
* `:min_mass` — minimum AST node count for a fragment to be considered (default: `#{Config.default(:min_mass)}`)
* `:min_similarity` — similarity threshold 0.0–1.0 (default: `#{Config.default(:min_similarity)}`)
* `:ignore` — list of glob patterns to exclude
* `:reporters` — list of reporter modules (default: `[ExDNA.Reporter.Console]`)
## Examples
ExDNA.analyze("lib/")
ExDNA.analyze(paths: ["lib/", "test/"], min_mass: 20)
"""
@spec analyze(path_or_paths() | keyword()) :: Report.t()
def analyze(path_or_opts \\ [])
def analyze(path) when is_binary(path), do: analyze(paths: [path])
def analyze(opts) when is_list(opts) do
config = Config.new(opts)
config
|> Detection.Detector.run()
|> Report.new(config)
end
end