Skip to main content

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 resolutiontsconfig paths, package exports maps, index files, the works. "Unused export" claims come from resolution, not regex.
  • Per-function complexity — McCabe cyclomatic + SonarSource cognitive, powering health and the complexity rule.
  • 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/… and Router() 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:

CapabilityStatus
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 thresholdsJS/TS-deep today
Unused-export analysisJS/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

EcosystemManifestLockfile (audit)
npm / Nodepackage.jsonpackage-lock.json ✔ (other formats planned)
RustCargo entry-point detection ✔