Language support
All languages feed the same language-agnostic model, so dependency resolution, the call graph, taint reachability, and the governance rules work across every supported language. Depth varies by extractor.
JavaScript / TypeScript (deepest support)
The JS/TS family is parsed and enriched by a native extractor stack:
- Real module resolution —
tsconfigpaths, packageexportsmaps, index files, the works. "Unused export" claims come from resolution, not regex. - Per-function complexity — McCabe cyclomatic + SonarSource cognitive, powering
healthand thecomplexityrule. - Exports & dead code — unused exports (type-only tagged separately),
entry-point file reachability, unused/phantom dependency detection against
package.json+package-lock.json. - HTTP route extraction — Express-style
app.get/post/…andRouter()registrations, including inline arrow handlers (synthesized as<VERB /path handler>symbols so taint stays connected). - SQL table extraction — table references in query strings become
table:nodes. - Security detectors + taint — the full set on the rules page.
Python, Go, Rust, C++
Covered by a single specification-driven adapter behind the same parser boundary:
| Capability | Status |
|---|---|
| Import/dependency graph | ✔ |
| Symbols & call graph | ✔ |
| Module inference, cycles, boundaries, banned imports | ✔ |
| File-level reachability (dead files) | ✔ (e.g. Cargo entry points are detected for Rust) |
| Security patterns | ✔ language-appropriate: os.system / subprocess.* / hashlib.md5 (Python), exec.Command (Go), process::Command (Rust), eval/exec (generic) |
| Inline suppressions | ✔ (# ovecc-ignore in Python, // ovecc-ignore elsewhere) |
| Per-function complexity thresholds | JS/TS-deep today |
| Unused-export analysis | JS/TS-deep today |
When an analysis doesn't apply, ovecc says so rather than emitting a silent zero —
e.g. deadcode reports its coverage (entry points
found, JS/TS files analyzed) with every clean result.
Everything else
Files in unsupported languages are ignored by the parser but still visible to Git-based signals (churn, ownership) where relevant. Adding a language is a new extractor behind the parser boundary, not a core change — support widens without altering the model or the commands.
Manifests & lockfiles
| Ecosystem | Manifest | Lockfile (audit) |
|---|---|---|
| npm / Node | package.json ✔ | package-lock.json ✔ (other formats planned) |
| Rust | Cargo entry-point detection ✔ | — |