Skip to content

feat: add complexity metrics for Zig (#1923) - #2281

Merged
carlos-alm merged 2 commits into
mainfrom
feat/issue-1923-complexity-tier2
Aug 5, 2026
Merged

feat: add complexity metrics for Zig (#1923)#2281
carlos-alm merged 2 commits into
mainfrom
feat/issue-1923-complexity-tier2

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

Progress on #1923 — adds zig complexity/Halstead support (tier 2).

tree-sitter-zig's if_statement wraps its else branch in an else_clause node whose single named child is either a nested if_statement (else-if) or the terminal else body — confirmed by parsing if (..) {..} else if (..) {..} else {..} and inspecting the S-expression. This is Pattern A (JS/C#/Rust-style wrapper), even though the grammar internally tags that child with an alternative field name — the wrapper-node detection only checks the parent node's type, not field names, so that's immaterial.

and/or/orelse are keyword operators sharing the single generic binary_expression node type (confirmed by parsing a and b or c and a orelse b) — same shared-type pattern as Lua's and/or.

catch_expression (expr catch fallback, expr catch |err| { .. }) is treated as a branch/nesting node, the same treatment C/C++/ObjC/C# give catch_clause — its fallback can be an arbitrary block with its own control flow, not just a coalescing value. try_expression (try expr) is not a branch — it propagates the error up rather than branching locally, mirroring how Rust's ? operator is Halstead-only.

Wires COMPLEXITY_RULES/HALSTEAD_RULES (TS) and lang_rules()/halstead_rules() (native) for zig, plus a zig entry in both engines' comment-prefix tables (zig has no block comments, only //).

Verification

  • npm run lint — clean
  • npm test — 273/273 test files, 4430 passed, 30 skipped, 2 todo
  • cargo test --lib (crates/codegraph-core) — 753/753 passed
  • Native and WASM engines produce byte-identical codegraph complexity --health --json output on:
    • the existing tests/benchmarks/resolution/fixtures/zig/ fixture
    • a hand-built fixture covering if/else-if/else, while, for-range, switch with multi-value cases, orelse, catch (both expression and block-with-payload forms), and try

Remaining scope on #1923

Tier 1 (c, cpp, kotlin, swift, scala, bash) and CUDA were already done. Objective-C (tier 2) done in #2233. Dart is blocked on #2182 (grammar structural issue) — do not attempt until that's fixed. Remaining unattempted: haskell, ocaml, ocaml-interface, fsharp, fsharp-signature, gleam, clojure, julia, r, erlang, solidity, groovy, verilog.

Test plan

  • npm run lint
  • npm test
  • cargo test --lib in crates/codegraph-core
  • Native vs WASM diff on the zig resolution fixture and a hand-built fixture (identical output)

Progress on #1923 — adds zig complexity/Halstead support (tier 2).

tree-sitter-zig's if_statement wraps its else branch in an else_clause
node (Pattern A, same as JS/C#/Rust), confirmed by parsing if/else-if/else
and inspecting the S-expression. and/or/orelse are keyword operators
sharing the generic binary_expression node type, same shared-type pattern
as Lua's and/or. catch_expression (expr catch fallback, expr catch |err|
{...}) is treated as a branch/nesting node like C/C++/ObjC/C#'s
catch_clause, since its fallback can be an arbitrary block with its own
control flow. try_expression is Halstead-only (not a branch), mirroring
Rust's ? operator.

Wires COMPLEXITY_RULES/HALSTEAD_RULES (TS) and lang_rules()/halstead_rules()
(native) for zig, plus a zig entry in both engines' comment-prefix tables
(zig has no block comments, only //).

Verified native and WASM produce byte-identical codegraph complexity
--health --json output on the existing zig resolution fixture and a
hand-built fixture covering if/else-if/else, while, for-range, switch
with multi-value cases, orelse, catch (both expression and block-with-
payload forms), and try.

docs check acknowledged — README's language table tracks imports/exports/
call-sites/heritage/dataflow, not complexity; no per-language complexity
matrix exists in any of the three docs to update.
@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds Zig complexity and Halstead analysis to the TypeScript/WASM and native Rust engines.

  • Registers mirrored Zig complexity, nesting, logical-operator, and Halstead rule sets.
  • Adds Zig line-comment handling.
  • Adds unit cases for conditionals, loops, switches, error handling, and basic Halstead output.

Confidence Score: 5/5

The PR appears safe to merge, with only non-blocking regression-test completeness remaining.

The prior coverage thread remains partially outstanding despite the reply claiming it was fixed: the added branch cases are concrete, but the Zig Halstead assertion only checks for positive volume and the native cases never calculate Halstead, so the listed literal, call, field-access, and indexing classifications remain unverified; no blocking failure remains.

Files Needing Attention: tests/unit/complexity.test.ts and crates/codegraph-core/src/ast_analysis/complexity.rs

Important Files Changed

Filename Overview
src/ast-analysis/rules/zig.ts Defines the TypeScript/WASM Zig complexity and Halstead classifications.
crates/codegraph-core/src/ast_analysis/complexity.rs Adds mirrored native Zig metric rules, comment handling, and complexity cases.
src/ast-analysis/rules/index.ts Registers Zig in the TypeScript complexity and Halstead rule maps.
src/ast-analysis/metrics.ts Registers Zig's line-comment prefix for LOC calculations.
tests/unit/complexity.test.ts Adds TypeScript cases covering representative Zig control-flow constructs and basic metric generation.

Reviews (2): Last reviewed commit: "test: add regression coverage for Zig co..." | Re-trigger Greptile

// is NOT a branch — it propagates the error up rather than branching
// locally, mirroring how Rust's `?` operator is Halstead-only (rust.ts).

export const complexity: ComplexityRules = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Zig metric rules lack regression coverage

The new Zig branch and token classifications are not covered by committed automated cases for else-if, switch arms, catch, logical operators, literals, calls, and indexing. This leaves future grammar or rule changes able to silently alter Zig complexity, Halstead, or maintainability metrics in either engine.

Knowledge Base Used:

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added regression coverage in the follow-up commit: 6 TS cases in tests/unit/complexity.test.ts (else-if, while+orelse, for-range+multi-value switch, catch with error-payload block, try-is-not-a-branch, Halstead volume) and 5 mirrored Rust cases in complexity.rs's test module. Expected values were computed by running the actual engine against each snippet (not hand-derived), then baked into the assertions.

Addresses Greptile feedback on #2281: the new Zig branch/token
classifications (else-if, switch arms with multi-value cases, catch with
error-payload block, orelse, try) had no committed automated cases,
leaving future grammar or rule changes able to silently alter Zig metrics
in either engine. Mirrors the existing ObjC test blocks in both
tests/unit/complexity.test.ts and complexity.rs's test module. Expected
values computed by running the actual engine against each snippet, not
hand-derived.
@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai

@carlos-alm
carlos-alm merged commit c54105a into main Aug 5, 2026
36 checks passed
@carlos-alm
carlos-alm deleted the feat/issue-1923-complexity-tier2 branch August 5, 2026 07:01
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 5, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant