Skip to content

feat: add complexity metrics for Objective-C (#1923) - #2233

Merged
carlos-alm merged 1 commit into
mainfrom
feat/issue-1923-complexity-objc
Aug 3, 2026
Merged

feat: add complexity metrics for Objective-C (#1923)#2233
carlos-alm merged 1 commit into
mainfrom
feat/issue-1923-complexity-objc

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

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

tree-sitter-objc extends tree-sitter-c: if/else/for/while/switch/case/logical-operator/conditional-expression node kinds are byte-identical to plain C (confirmed by parsing sample ObjC control flow and inspecting the S-expression), including the same else_clause wrapper (Pattern A). Wires COMPLEXITY_RULES/HALSTEAD_RULES (TS) and lang_rules()/halstead_rules() (native) for objc, extending C's rule shape with:

  • method_definition (the -/+ method body) added to functionNodes alongside function_definition
  • catch_clause (from @try/@catch/@finally) treated as a branch/nesting node, the same treatment C++'s catch_clause already gets
  • message_expression/selector_expression treated as compound Halstead operators, mirroring call_expression

Also fixes a native/WASM divergence this surfaced: the native ObjC extractor's handle_method ran complexity/CFG analysis unconditionally on both method_declaration (an @interface/@protocol signature, which never has a body) and method_definition, producing a spurious trivial complexity entry (cognitive 0, cyclomatic 1) for every interface declaration that duplicated the real method_definition entry under the same dotted name. Gated both on actual body presence and set bodyless accordingly; ported the same explicit bodyless signal to the TS/WASM extractor for defense-in-depth (its hasFuncBody skip logic otherwise relies on an endLine > line heuristic that a multi-line bodyless signature could slip past).

Verification

  • npm run lint — clean
  • npm test — 267/267 test files, 4335 passed, 30 skipped, 2 todo
  • cargo test --lib (crates/codegraph-core) — 707/707 passed
  • Native and WASM engines produce byte-identical codegraph complexity --health --json output on a hand-built fixture covering if/else-if/else, classic and fast-enumeration for loops, switch/case, @try/@catch/@finally, ternary, and message sends.

Remaining scope on #1923

Tier 1 (c, cpp, kotlin, swift, scala, bash) and CUDA were already done. Dart is blocked on #2182 (grammar structural issue) — do not attempt until that's fixed. Remaining unattempted: zig, 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 a hand-built ObjC fixture (identical output)

tree-sitter-objc extends tree-sitter-c: if/else/for/while/switch/case/
logical-operator/conditional-expression node kinds are byte-identical
to plain C (confirmed by parsing sample ObjC control flow and
inspecting the S-expression), including the same else_clause wrapper
(Pattern A). Wires COMPLEXITY_RULES/HALSTEAD_RULES (TS) and
lang_rules()/halstead_rules() (native) for 'objc', extending C's rule
shape with method_definition (the `-`/`+` method body) in
functionNodes and catch_clause (from @try/@catch/@finally) as a
branch/nesting node, the same treatment C++'s catch_clause already
gets. message_expression/selector_expression are treated as compound
Halstead operators, mirroring call_expression.

Also fixes a native/WASM divergence this surfaced: the native ObjC
extractor's handle_method ran complexity/CFG analysis unconditionally
on both method_declaration (an @interface/@protocol signature, which
never has a body) and method_definition, producing a spurious trivial
complexity entry (cognitive 0, cyclomatic 1) for every interface
declaration that duplicated the real method_definition entry under
the same dotted name. Gated both on actual body presence and set
bodyless accordingly; ported the same explicit bodyless signal to the
TS/WASM extractor for defense-in-depth (its hasFuncBody skip logic
otherwise relies on an endLine>line heuristic that a multi-line
bodyless signature could slip past).

Verified native and WASM produce byte-identical `codegraph complexity
--health --json` output on a hand-built fixture covering if/else-if/
else, classic and fast-enumeration for loops, switch/case, @try/
@catch/@finally, ternary, and message sends.

No README/CLAUDE.md/ROADMAP.md changes needed — none of them enumerate
per-language complexity-metric coverage (docs check acknowledged).

Refs #1923

Impact: 1 functions changed, 2 affected
@greptile-apps

greptile-apps Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds Objective-C complexity, Halstead, LOC, and maintainability metrics across the native and WASM analysis paths while preventing bodyless method declarations from receiving spurious complexity and CFG results.

  • Adds mirrored Objective-C complexity and Halstead rule sets in Rust and TypeScript.
  • Registers Objective-C for complexity, Halstead, and C-style LOC handling.
  • Marks method declarations as bodyless and gates native complexity/CFG generation on an actual method body.
  • Adds Objective-C control-flow and native/WASM parity tests.

Confidence Score: 5/5

The PR appears safe to merge, with native and WASM Objective-C metric behavior consistently wired and no actionable defect identified.

The mirrored rule sets classify the covered Objective-C constructs consistently, and explicit body detection prevents declaration-only methods from receiving complexity or CFG results.

Important Files Changed

Filename Overview
crates/codegraph-core/src/ast_analysis/complexity.rs Adds native Objective-C complexity, Halstead, and LOC rules with focused control-flow tests.
crates/codegraph-core/src/extractors/objc.rs Gates native method metrics and CFG on body presence and records explicit bodyless state.
src/ast-analysis/rules/c.ts Adds TypeScript Objective-C complexity and Halstead rules mirroring the native implementation.
src/ast-analysis/rules/index.ts Registers Objective-C in the WASM complexity and Halstead rule maps.
src/extractors/objc.ts Adds explicit bodyless signaling so declaration signatures are excluded from downstream analysis.
tests/unit/complexity.test.ts Covers Objective-C methods, control flow, exception handling, Halstead output, and DFS/visitor parity.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Source["Objective-C source"] --> Parse["tree-sitter-objc"]
  Parse --> Native["Native Rust extractor"]
  Parse --> Wasm["TypeScript/WASM extractor"]
  Native --> BodyCheck["Detect compound_statement"]
  Wasm --> Bodyless["Set explicit bodyless flag"]
  BodyCheck --> Metrics["Complexity + Halstead + LOC + MI"]
  BodyCheck --> CFG["CFG"]
  Bodyless --> Visitor["Shared analysis visitors"]
  Visitor --> Metrics
  Metrics --> Definition["Attach results to bodied definitions"]
  CFG --> Definition
Loading

Reviews (1): Last reviewed commit: "feat: add complexity metrics for Objecti..." | Re-trigger Greptile

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

1 functions changed4 callers affected across 3 files

  • handleMethodDecl in src/extractors/objc.ts:199 (4 transitive callers)

@carlos-alm

Copy link
Copy Markdown
Contributor Author

Thanks for the review — 5/5 confidence, no actionable defects, nothing further to address here.

@carlos-alm
carlos-alm merged commit 53cc62d into main Aug 3, 2026
33 checks passed
@carlos-alm
carlos-alm deleted the feat/issue-1923-complexity-objc branch August 3, 2026 10:50
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 3, 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