Detection Methods
Detection Methods
Section titled “Detection Methods”Controlled with -m / --detection-methods:
| Method | Flag | Description |
|---|---|---|
| Suffix tree | -m art-dupl (default) |
Ukkonen’s algorithm on serialized ASTs — finds structural clones |
| Hash-based | -m hash |
Rolling hash on file content — faster, different tradeoffs |
| Combined | -m "hash,art-dupl" |
Runs both in parallel, deduplicates results |
Suffix Tree (Default)
Section titled “Suffix Tree (Default)”The suffix tree method is the core of art-dupl. It:
- Parses source files into ASTs
- Serializes ASTs into unified token sequences
- Builds a compressed suffix tree (Ukkonen’s algorithm with O(1) map-based transitions)
- Finds repeated subsequences above the threshold
This finds exact structural clones that regex-based tools miss.
Hash-Based
Section titled “Hash-Based”The hash method uses XXH3 streaming hash on file content. It’s faster but operates at the content level, not the AST level. Useful for quick scans of large codebases.
Combined
Section titled “Combined”Run both methods simultaneously via goroutines. Results are deduplicated. Best coverage at the cost of more computation.
Matching Modes
Section titled “Matching Modes”Three mutually exclusive modes control how identifiers are matched:
Semantic (Default)
Section titled “Semantic (Default)”art-dupl --semantic .Alpha-normalizes local identifiers (params, receiver, body variables, closures) to canonical names (v0, v1, …) before hashing. This detects Type 2 renamed clones — functions with identical structure but different variable names.
func (s *Server) handle()matchesfunc (c *Client) process()a.String()does NOT matchb.Error()(different method names)- Selectors and field names are NOT normalized (API surface must match)
art-dupl --exact .Matches identifier names verbatim. Only finds Type 1 exact clones — copy-paste duplications where names are identical.
Structural
Section titled “Structural”art-dupl --structural .Ignores all identifier names. Matches by AST shape only. The loosest mode — a.String() matches b.Error(). Useful for raw structural pattern analysis but produces more noise.
Clone Type Classification
Section titled “Clone Type Classification”art-dupl labels each clone group by type:
| Type | Description | Detected by |
|---|---|---|
| Type 1 | Exact — identical names | Exact mode |
| Type 2 | Renamed — alpha-normalized match | Semantic mode (default) |
| Type 3 | Near-miss — structural with minor differences | Structural mode |
Classification appears in JSON, SARIF, and --rich-text output.
Semantic Encoding
Section titled “Semantic Encoding”Internally, each AST node is encoded as:
[24-bit identifier/operator hash][8-bit base AST node type]Both Exact and Semantic modes hash identifiers. Structural mode ignores them. When comparing node types programmatically, always use golang.DecodeBaseType(node.Type) — never compare raw node.Type values.