# How Code-Graph-RAG Handles Duplicate Code Definitions and Method Overloading

> Discover how Code-Graph-RAG tackles duplicate code and method overloading using line-number markers for precise clone detection and accurate call resolution.

- Repository: [Vitali Avagyan/code-graph-rag](https://github.com/vitali87/code-graph-rag)
- Tags: deep-dive
- Published: 2026-09-06

---

**Code-Graph-RAG treats duplicate code definitions—including method overloads—as distinct entities tagged with line-number markers, enabling precise detection of clones while preserving semantic relationships for accurate call resolution.**

This article explains the architectural approach used by [vitali87/code-graph-rag](https://github.com/vitali87/code-graph-rag) to identify, group, and resolve duplicate code definitions. The system handles everything from exact copy-paste clones to language-level overloading through a unified duplicate detection pipeline.

## Duplicate Detection Architecture

The duplicate detection system operates through two complementary strategies implemented in [[`codebase_rag/duplicates.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/duplicates.py)](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/duplicates.py).

### Exact-Copy Detection

Code-Graph-RAG first identifies **structurally identical** definitions by computing a **whole-AST fingerprint**—a cryptographic hash of the complete abstract syntax tree representation. Identical fingerprints guarantee identical code structure regardless of source location.

The `collect_duplicates()` function delegates to `_exact_groups()` for this phase:

```python

# codebase_rag/duplicates.py (lines 61-78)

def _exact_groups(members: list[Member]) -> list[DuplicateGroup]:
    fingerprint_map: dict[str, list[Member]] = defaultdict(list)
    for m in members:
        fp = m.structural_fingerprint()
        fingerprint_map[fp].append(m)
    # Groups with >1 member are exact duplicates

    return [
        DuplicateGroup(kind="exact", similarity=1.0, members=ms)
        for fp, ms in fingerprint_map.items()
        if len(ms) > 1
    ]

```

This approach is computationally efficient—**O(n)** for n definitions—and catches copy-paste duplication without false negatives.

### Similarity-Based Detection

For definitions that differ slightly (refactored parameters, renamed variables, modified bodies), Code-Graph-RAG employs **branch-fingerprint similarity** using Jaccard overlap:

```python

# codebase_rag/duplicates.py (lines 41-50)

def _similar_groups(
    members: list[Member],
    threshold: float = 0.6
) -> list[DuplicateGroup]:
    # Build prefix index for efficient candidate generation

    index = PrefixIndex(m.branch_fingerprint for m in members)
    candidates = _candidate_pairs(index, threshold)
    # Find maximal cliques of mutually similar members

    cliques = _maximal_cliques(candidates, members)
    return [
        DuplicateGroup(kind="similar", similarity=score, members=clique)
        for clique, score in cliques
    ]

```

The **AllPairs/PPJoin** indexing strategy reduces the search space from **O(n²)** to near-linear for typical codebases.

### Nested Member Pruning

To prevent false positives where an inner function appears "similar" to its containing outer function, the system drops contained members:

```python

# codebase_rag/duplicates.py

def _drop_contained_members(members: list[Member]) -> list[Member]:
    return [
        m for m in members
        if not any(_member_nested_in(other, m) for other in members)
    ]

```

This ensures that legitimate nesting relationships don't trigger spurious duplicate reports.

## The DUP_QN_MARKER System for Overloads

The core mechanism distinguishing duplicate definitions is the **`DUP_QN_MARKER`** suffix appended to qualified names.

### Marker Definition

Located in [[`codebase_rag/constants/core.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/constants/core.py)](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/constants/core.py):

```python

# codebase_rag/constants/core.py

DUP_QN_MARKER = "@"           # <qualified_name>@<start_line>

DUP_QN_COLUMN_MARKER = "_"    # Optional: @<line>_<column>

```

When a qualified name appears multiple times, each instance receives a unique marker encoding its source position.

### Parser Integration

Java method resolution demonstrates the marker application in [[`codebase_rag/parsers/java/method_resolver.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/parsers/java/method_resolver.py)](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/parsers/java/method_resolver.py):

```python

# codebase_rag/parsers/java/method_resolver.py

def _resolve_method_declaration(node: Tree, ctx: ParseContext) -> Method:
    natural_qn = f"{ctx.current_type}.{node.name}"
    start_line = node.start_point[0] + 1  # 1-indexed

    
    # Append duplicate marker for overloads

    if ctx.is_overloaded(natural_qn):
        variant = f"{natural_qn}{cs.DUP_QN_MARKER}{start_line}"
    else:
        variant = natural_qn
    
    return Method(qualified_name=variant, ...)

```

This guarantees that `Vehicle.start()` on line 45 and `Vehicle.start()` on line 78 become `Vehicle.start@45` and `Vehicle.start@78` respectively.

### Normalization for Semantic Comparison

Downstream components strip markers before hierarchical or signature-based comparisons:

```python

# codebase_rag/duplicates.py

import re
from codebase_rag.constants import core as cs

_DUP_QN_MARKER_RE = re.compile(
    re.escape(cs.DUP_QN_MARKER) + r"\d+(?:" 
    + re.escape(cs.DUP_QN_COLUMN_MARKER) + r"\d+)?$"
)

def _qn_normalized(qn: str) -> str:
    """Remove overload/duplicate markers for semantic comparison."""
    return _DUP_QN_MARKER_RE.sub("", qn)

```

**This dual representation enables both precision and flexibility**: the marked `qn` preserves identity for graph storage, while the normalized form enables type hierarchy and signature matching.

## Overload Resolution in Practice

The Java parser implements complete overload resolution through ranked candidate selection.

### Candidate Collection and Ranking

```python

# codebase_rag/parsers/java/method_resolver.py

def resolve_overload(
    base_qn: str,           # e.g., "Utils.toString"

    arg_types: tuple[str | None, ...],
    candidates: list[Method]
) -> Method | None:
    # Filter by normalized name

    overloads = [m for m in candidates 
                 if _qn_normalized(m.qn) == base_qn]
    
    # Score each candidate

    ranked = [
        (_overload_rank(m, arg_types), m) 
        for m in overloads
    ]
    ranked = [(score, m) for score, m in ranked if score is not None]
    
    return min(ranked, key=lambda x: x[0])[1] if ranked else None

def _overload_rank(method: Method, arg_types: tuple) -> int | None:
    params = method.parameter_types
    if len(params) != len(arg_types):
        return None  # Arity mismatch

    
    # Exact type matches score 0, inheritance distance scores higher

    score = sum(
        _inheritance_distance(arg, param) 
        for arg, param in zip(arg_types, params)
    )
    return score

```

The ranking algorithm prefers **exact signature matches** (score 0), then **closest inheritance distance** for polymorphic arguments.

### Python @overload Handling

For Python's `@overload` decorator pattern, the parser treats each stub as a distinct definition:

```python

# Example: Python overload stubs become separate graph nodes

from typing import overload

@overload
def process(data: bytes) -> str: ...

@overload
def process(data: str) -> bytes: ...

def process(data):  # Implementation (line 11)

    # runtime logic

    pass

```

**Graph representation:**
- `mymodule.process@3` → first overload (bytes → str)
- `mymodule.process@6` → second overload (str → bytes)  
- `mymodule.process@11@11` → implementation (note: implementation may also receive marker if name collision detected)

The duplicate detection engine groups these via `_qn_normalized()`, while call resolution uses argument type inference to select the appropriate overload stub.

## Duplicate Group Output Format

The final `DuplicateGroup` data structure carries complete provenance:

```python
@dataclass
class DuplicateGroup:
    kind: Literal["exact", "similar"]
    similarity: float  # 1.0 for exact, 0.0-1.0 for similar

    members: list[Member]
    # Metadata for diagnostics

    skipped_symbols: list[str] = field(default_factory=list)
    truncated: bool = False

```

This enables downstream tools to:
- Flag exact clones for refactoring prioritization
- Review similar code for abstraction opportunities
- Preserve overload relationships in API documentation

## Summary

- **Duplicate detection** operates through exact AST fingerprinting and Jaccard-based similarity analysis in [[`duplicates.py`](https://github.com/vitali87/code-graph-rag/blob/main/duplicates.py)](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/duplicates.py)
- **Overload differentiation** uses the `DUP_QN_MARKER` (`@`) suffix defined in [[`constants/core.py`](https://github.com/vitali87/code-graph-rag/blob/main/constants/core.py)](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/constants/core.py) to create unique qualified names for same-named definitions at different locations
- **Semantic preservation** via `_qn_normalized()` ensures type hierarchies and call resolution work correctly despite marker suffixes
- **Overload ranking** in [[`method_resolver.py`](https://github.com/vitali87/code-graph-rag/blob/main/method_resolver.py)](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/parsers/java/method_resolver.py) selects optimal candidates by signature matching and inheritance distance
- **Nested member pruning** prevents false positives from legitimate code nesting patterns

## Frequently Asked Questions

### How does Code-Graph-RAG distinguish between code clones and legitimate overloads?

Both clones and overloads receive `DUP_QN_MARKER` suffixes to create unique graph nodes. The distinction emerges in downstream processing: **clones** typically share fingerprints (exact) or high Jaccard similarity, while **overloads** have different signatures and participate in method resolution. The `_qn_normalized()` function treats them identically for type hierarchy queries.

### What happens when more than two definitions share the same qualified name?

The marker system scales arbitrarily. Each additional definition receives its own `<qn>@<line>` entry. The duplicate detection engine forms **maximal cliques** of similar definitions, so a method with five overloads creates a single group containing all five variants if they're structurally similar, or multiple groups if some variants diverge significantly.

### Does the marker system affect cross-language analysis?

The `DUP_QN_MARKER` constant is language-agnostic. Java, Python, and TypeScript parsers all apply the same convention, enabling unified duplicate detection across polyglot codebases. Language-specific overload rules (Java's subtyping vs. Python's nominal typing) are handled in their respective method resolvers before the generic duplicate grouping logic executes.

### Can duplicate detection be tuned for specific similarity thresholds?

Yes. The `_similar_groups()` function accepts a `threshold` parameter defaulting to `0.6`. Lower values detect more aggressive refactoring candidates; higher values restrict reports to near-identical code. This threshold propagates from CLI configuration through [[`duplicates.py`](https://github.com/vitali87/code-graph-rag/blob/main/duplicates.py)](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/duplicates.py) without requiring code changes.