GTLocator¶
Extract symbol-level ground truth changes (functions, classes, methods) from SWE-bench unified diff patches. Identifies which symbols were modified, added, or deleted.
Supports Python, Go, Rust, C/C++, C#, Java, Ruby, PHP, Kotlin, Swift, Scala, Lua, JavaScript, and TypeScript.
How It Works¶
- Clone repo and checkout
base_commit - Extract symbols from affected files using tree-sitter chunkers
- Apply patch
- Extract symbols again
- Compare before/after to classify changes as modified, added, or deleted
Change detection uses three-level filtering: - Set difference → added/deleted symbols - Line count change → modified (cheapest check) - Line range overlap + content diff → modified (only when lengths match)
Prerequisites¶
tree-sitter-language-pack(bundled with CodeNib, provides parsers for all supported languages)git(for cloning and checking out repos)
Usage¶
from codenib.dataset.gt_locate import GTLocator
locator = GTLocator(work_dir="/data/repos")
result = locator.analyze_instance({
"instance_id": "django__django-12345",
"repo": "django/django",
"base_commit": "abc123",
"patch": "--- a/file.py\n+++ b/file.py\n@@ -10,3 +10,5 @@\n...",
})
Parameters:
work_dir(str, optional): Directory for cloning repos. Default:~/.codenib/tmp(auto-cleaned oncleanup())language(str, optional): Force a specific language instead of auto-detecting from file extensions
Output:
{
"instance_id": "django__django-12345",
"target_files": ["django/db/models/query.py"],
"code_blocks": [{
"file_path": "django/db/models/query.py",
"symbol": "QuerySet.filter()",
"start_line": 100, # 1-based
"end_line": 120,
"symbol_type": "method",
"change_type": "modified",
}],
"symbols_modified": ["django/db/models/query.py:QuerySet.filter()"],
"symbols_added": [],
"symbols_deleted": [],
"error": None,
}
Symbol naming: file:func(), file:Class, file:Class.method(). Line numbers in output are 1-based.
Lightweight Usage¶
# Just extract affected file paths from a patch (no clone needed)
files = locator.get_target_files(patch_content)
# ["django/db/models/query.py", "django/db/models/manager.py"]
# Extract changed line ranges from a patch
ranges = locator.get_changed_line_ranges(patch_content)
# {"django/db/models/query.py": [(100, 105), (200, 210)]}