Summary
The AST cache key does not include the tree-sitter grammar version. After upgrading a grammar package (for example tree-sitter-swift 0.7.2 → 0.7.4), extract() keeps returning the results produced by the old grammar for every file whose content and path are unchanged. That includes results the new grammar would have fixed.
cache_dir() namespaces AST entries by graphify's own version and cache schema (ast/v{version}-s{schema}). file_hash() covers the file content and its relative path. Neither of these changes when only the grammar package changes.
Reproduction (graphifyy 0.9.80)
src/Badge.swift:
final class Badge {
#if os(iOS)
func iosOnly() {}
#endif
func update() {}
}
repro.py:
import sys
from importlib.metadata import version
from pathlib import Path
from graphify.extract import extract
root, cache = Path(sys.argv[1]), Path(sys.argv[2])
ast = extract([root / "Badge.swift"], cache_root=cache, root=root)
owned = sorted(e["target"] for e in ast["edges"] if e["relation"] == "method")
print(f"tree-sitter-swift {version('tree-sitter-swift')}: methods owned by Badge = {owned}")
Run it three times:
# 1) fresh cache, tree-sitter-swift 0.7.2 (cannot parse #if inside a type body)
tree-sitter-swift 0.7.2: methods owned by Badge = []
# 2) same cache, after upgrading to tree-sitter-swift 0.7.4
tree-sitter-swift 0.7.4: methods owned by Badge = []
# 3) empty cache, tree-sitter-swift 0.7.4
tree-sitter-swift 0.7.4: methods owned by Badge = ['badge_badge_iosonly', 'badge_badge_update']
Run 2 serves the 0.7.2 extraction from the cache, so the upgrade has no effect until the cache is deleted or the source file changes. Nothing reports that the cached entry came from a different grammar.
Impact
We found this while comparing two graphs built from the same Swift sources. One environment had upgraded tree-sitter-swift, but its warm cache still held the 0.7.2 results. As a result, roughly 400 members were detached from their types and their call edges were missing, even though the installed grammar parsed the files correctly.
Suggested fix
Include the version of the grammar used for each language in the AST cache namespace or key, for example the installed tree-sitter-<lang> distribution version and the tree-sitter runtime version. A content-only key is not enough, because the extractor's output depends on the grammar.
Workaround
Key cache_root by the grammar versions on the caller side, for example <cache>/ts{tree_sitter}-swift{tree_sitter_swift}.
Environment: graphifyy 0.9.80, tree-sitter 0.25.2, tree-sitter-swift 0.7.2 / 0.7.4, Python 3.11, macOS.
Summary
The AST cache key does not include the tree-sitter grammar version. After upgrading a grammar package (for example
tree-sitter-swift0.7.2 → 0.7.4),extract()keeps returning the results produced by the old grammar for every file whose content and path are unchanged. That includes results the new grammar would have fixed.cache_dir()namespaces AST entries by graphify's own version and cache schema (ast/v{version}-s{schema}).file_hash()covers the file content and its relative path. Neither of these changes when only the grammar package changes.Reproduction (graphifyy 0.9.80)
src/Badge.swift:repro.py:Run it three times:
Run 2 serves the 0.7.2 extraction from the cache, so the upgrade has no effect until the cache is deleted or the source file changes. Nothing reports that the cached entry came from a different grammar.
Impact
We found this while comparing two graphs built from the same Swift sources. One environment had upgraded
tree-sitter-swift, but its warm cache still held the 0.7.2 results. As a result, roughly 400 members were detached from their types and their call edges were missing, even though the installed grammar parsed the files correctly.Suggested fix
Include the version of the grammar used for each language in the AST cache namespace or key, for example the installed
tree-sitter-<lang>distribution version and thetree-sitterruntime version. A content-only key is not enough, because the extractor's output depends on the grammar.Workaround
Key
cache_rootby the grammar versions on the caller side, for example<cache>/ts{tree_sitter}-swift{tree_sitter_swift}.Environment: graphifyy 0.9.80, tree-sitter 0.25.2, tree-sitter-swift 0.7.2 / 0.7.4, Python 3.11, macOS.