Out of 473 functions analyzed in eza-community/eza, 22 land in the critical band, and 21 sit in the ‘fire’ quadrant — meaning they’re complex and being actively edited at the same time. The top finding is render in src/output/code.rs, sitting at an activity-weighted risk score of 14.13 with zero days since its last change and one touch in the last 30 days — that’s a live regression risk, not a backlog item. Right behind it, deduce in src/options/view.rs scores 14.1 but sits in the ‘debt’ quadrant with 160 days since its last change and zero touches in the last 30 days, which tells a different story: this one is dormant structural debt with a ten-level nesting depth waiting to bite whoever touches it next.
The table below ranks functions by activity-weighted risk — a score that multiplies structural complexity by recent commit frequency. A function that is both hard to understand (high cyclomatic complexity) and actively changing is a higher priority than one that is complex but untouched. CC = cyclomatic complexity (independent execution paths); ND = max nesting depth; FO = fan-out (distinct callees).
Top 5 Hotspots
| Function | File | Risk | CC | ND | FO |
|---|---|---|---|---|---|
render | src/output/code.rs | 14.1 | 15 | 3 | 17 |
deduce | src/options/view.rs | 14.1 | 6 | 10 | 4 |
run | src/main.rs | 13.8 | 17 | 3 | 9 |
print_dirs | src/main.rs | 13.2 | 18 | 4 | 13 |
deduce | src/options/view.rs | 12.5 | 19 | 2 | 4 |
473 functions analyzed
Multiple return or throw paths dispersed through the body — each exit needs separate test coverage.Long Function×5Long Function
Function body is too long to review in a single pass; likely contains multiple distinct responsibilities.God Function×4God Function
Calls an unusually large number of distinct functions (high fan-out), making it the structural centre of gravity for a subsystem.Complex Branching×3Complex Branching
High cyclomatic complexity — many independent execution paths, each a potential bug surface and required test case.Deeply Nested×1Deeply Nested
Control structures nested 4+ levels deep, making it hard to reason about the full execution state at inner branches.
Seven of the top hotspots are flagged ‘exit heavy,’ five are ‘long function,’ and four are ‘god function.’ That distribution tells me eza’s risk isn’t a single bad file — it’s a pattern repeating across the CLI’s option-parsing and rendering layers, where functions accumulate early-return branches as more flags get supported.
render — src/output/code.rs
This is the top-ranked hotspot in the repo, and it’s in the ‘fire’ quadrant — actively changing right now, not sitting idle. The excerpt shows it building a code-statistics report: sorting languages, computing icon columns, formatting percentage strings, and picking styles conditionally based on colour and icon settings. A fan-out of 17 means it calls out to seventeen distinct functions — locale loading, icon lookup, cell formatting, string painting — a lot of surface area for one function to own. A cyclomatic complexity of 15 combined with that fan-out is what the ‘god function’ and ‘long function’ tags are picking up on. With one touch in the last 30 days and zero days since its last change, whatever is being iterated on here is happening this week, so I’d want a second reviewer on the next diff rather than waiting for a dedicated cleanup pass. My concrete recommendation: extract the styling setup (header, lang_style, count_style, dim, bar_style, total_style) into a small struct built once, separate from the per-language formatting loop — that alone should cut the fan-out meaningfully.
deduce — src/options/view.rs (nesting depth 10)
This is the second-highest score in the repo, and the number that jumps out is a nesting depth of 10 — far past the depth-4 threshold where code becomes hard to reason about. The cyclomatic complexity of 6 is deceptively low; the risk here isn’t branch count, it’s how deeply those branches are wrapped inside each other while deciding between Code, Details, GridDetails, and Grid view modes based on flag combinations like --long, --grid, --tree, and --oneline. This function sits in the ‘debt’ quadrant with zero touches in the last 30 days and 160 days since its last change, so it isn’t actively being edited — it’s dormant structural debt with a high blast radius whenever someone next needs to add a view mode or flag interaction. The doc comment even states the intent explicitly: flags are scanned right-to-left and the first match wins, exactly the kind of implicit ordering logic that gets harder to verify correctly as nesting grows. The file’s history shows a bug-fix rate of 50% across 8 total commits and a review comment density of 3.2222, meaning past reviewers spent real discussion time here — worth reading before the next change. My recommendation: flatten the mode-selection logic into a match on a tuple of the four booleans, or extract the tree/grid/details branches into named helper functions, before this file sees its next flag addition.
run — src/main.rs
This is the CLI’s top-level dispatch function, and it’s in the ‘fire’ quadrant with one touch in the last 30 days and zero days since its last change — active work is happening here now. A cyclomatic complexity of 17 with a fan-out of 9 lines up with the ‘exit heavy’ and ‘long function’ tags: the excerpt shows an early return for the --code summary path, then separate handling for missing files, directories versus regular files, and permission errors, each with its own early exit. That’s a lot of independent paths to hold in your head, and each one is a required test case if the goal is confidence in a change. The file’s history shows 14 total commits and a review comment density of 2.75, both signs this function already draws real reviewer attention. Given it’s changing right now, I’d treat any pending pull request touching run as a candidate for extracting the --code handling block into its own function — it’s already structurally separate in the excerpt, just not extracted.
print_dirs — src/main.rs
This one carries five separate pattern flags at once: complex branching, exit heavy, god function, long function, and stale complex. It sits in the ‘debt’ quadrant, untouched for 390 days, which is the ‘stale complex’ signal made literal — a function that accumulated complexity long ago and hasn’t been revisited since. A cyclomatic complexity of 18 with a nesting depth of 4 and a fan-out of 13 means it’s both branchy and broadly coupled: the excerpt shows it walking directories, handling permission-denied errors inline with a push to a denied-list, formatting path escapes, filtering and sorting children, and branching into recursive versus non-recursive tree printing. That’s several responsibilities living in one function, and thirteen distinct callees mean a change to any of them (filtering, sorting, escaping) has to be re-verified against this function’s assumptions. Because it hasn’t moved in over a year, the risk isn’t live regression — it’s that whoever eventually adds a new directory-rendering feature inherits all eighteen branches at once. I’d recommend splitting the permission-error handling and the recursion-depth logic into their own functions before the next feature lands here.
deduce — src/options/view.rs (second overload)
The same file appears twice in the top five, which on its own is a signal: src/options/view.rs has two independently critical functions, one dormant and one live. This second entry shares the identical view-mode-selection logic described above but is scored separately at a cyclomatic complexity of 19 — one of the highest branch counts in the top five — with one touch in the last 30 days and zero days since last change, putting it squarely in ‘fire.’ The ‘exit heavy’ tag reflects the same early-return chain across Code, long, grid, tree, and oneline branches. Given this function is actively being edited while its sibling entry in the same file sits stale, I’d prioritize a single consolidated review pass on src/options/view.rs rather than treating the two as unrelated — a change to the flag-precedence logic in one likely has implications for the other.
Worth noting in passing: paint in src/output/file_name.rs (complexity 34, fan-out 8, one touch in the last 30 days, zero days since its last change) and render in src/output/details.rs (complexity 15, fan-out 13, also one touch in the last 30 days, zero days since its last change) didn’t make the top five but sit close behind in the ‘fire’ quadrant — both in the rendering layer, both actively changing. If a refactor sprint targets src/output/, those two belong on the same list as code.rs’s render.
Patterns Found
Antipatterns detected across the top functions in this snapshot:
| Pattern | Occurrences |
|---|---|
exit_heavy | 7 |
long_function | 5 |
god_function | 4 |
complex_branching | 3 |
deeply_nested | 1 |
stale_complex | 1 |
These labels belong to two tiers — Tier 1 (structural): complex_branching, deeply_nested, exit_heavy, long_function, god_function. Tier 2 (relational/temporal): hub_function, cyclic_hub, middle_man, neighbor_risk, stale_complex, churn_magnet, shotgun_target, volatile_god.
See more analyses with these patterns: complex_branching, deeply_nested, exit_heavy, god_function, long_function, stale_complex.
Reproduce This Analysis
git clone https://github.com/eza-community/eza
cd eza
git checkout 471bfbc7b03cbac8c738e8d9050edb06ee79132a
hotspots analyze . --mode snapshot --explain-patterns --force
To run the same analysis on your own codebase, run hotspots analyze . --mode snapshot in any local git repo — no configuration required.
I use Hotspots to highlight structural and activity risk — not “bad code.” I treat these findings as a prioritization aid, not a bug predictor. Editorial policy →