Command Palette

Search for a command to run…

ZarynZaryn
Core concepts·2 min read

Semantic (AST) diffing

zev sdiff compares Zig code by function (added, removed, signature or body changed) from the compiler's own parser, not lines of text.

`zev sdiff` computes a structural diff for Zig source files by parsing both versions with `std.zig.Ast` — Zig's own compiler-grade AST parser — rather than comparing text lines. ## What it detects For each top-level or struct-method function, zev extracts its name, a normalized signature (parameter types and return type, read directly from the parsed source), and a hash of its body's source text. Comparing old and new versions of a file produces one of: - **`added`** — a function present only in the new version - **`removed`** — a function present only in the old version - **`signature_changed`** — same function name, different parameter types or return type - **`body_changed`** — same name, same signature, different body - **`likely_rename`** — a function that disappeared under one name and reappeared under another with an identical body hash A real example, run through the actual `zev sdiff` command: ``` ≈ fn body_will_change body changed ≈ fn sig_will_change signature changed: (i32) i32 -> (i32, i32) i32 ↔ fn calc -> calculate_total identical body - fn will_be_removed removed + fn brand_new_function added ``` ## How rename detection works, and its honest limit A rename is detected by matching a disappeared function against an appeared one with an identical body hash — genuinely reliable when a function is renamed without also changing its implementation. If a function's name and its body both change in the same edit, it is reported as a plain removal and addition, not a rename, because there is no reliable signal connecting the two versions in that case. Duplicate function names are handled deliberately conservatively: if a name appears more than once in either version of a file (for example, two different structs each defining their own `init`), that name is excluded from direct matching entirely and falls through to rename detection or added/removed, rather than risk pairing the wrong two functions together under a shared name. ## Where this fits in Semantic diffing is wired into zev's existing `FileDiff`/`SemanticChange` infrastructure, the same structure a simpler, text-pattern-based diff already used for other languages. Zig files are dispatched to the AST-based diff; every other supported language continues to use the existing text-heuristic path. If a Zig file fails to parse cleanly — mid-edit syntax errors, for instance — the AST diff falls back to that same text heuristic automatically, so a diff is still produced rather than nothing at all.