Skip to main content

oxc_coverage_instrument/
lib.rs

1//! Istanbul-compatible JavaScript/TypeScript coverage instrumentation using the Oxc AST.
2//!
3//! This crate parses JS/TS source with [`oxc_parser`], identifies statements,
4//! functions, and branches, injects coverage counter expressions, and emits
5//! instrumented code. The coverage map output is compatible with Istanbul's
6//! `coverage-final.json` format (consumed by Jest, Vitest, c8, nyc, Codecov).
7//!
8//! # Example
9//!
10//! ```
11//! use oxc_coverage_instrument::{instrument, InstrumentOptions};
12//!
13//! let source = "function add(a, b) { return a + b; }";
14//! let result = instrument(source, "add.js", &InstrumentOptions::default()).unwrap();
15//!
16//! println!("Instrumented code:\n{}", result.code);
17//! println!("Functions found: {}", result.coverage_map.fn_map.len());
18//! ```
19//!
20//! # Coverage model
21//!
22//! The coverage map tracks three dimensions:
23//!
24//! - **Statements**: every executable statement gets a counter
25//! - **Functions**: every function declaration, expression, arrow, and method
26//! - **Branches**: if/else, ternary, switch cases, logical &&/||
27//!
28//! Function names are derived from the same Oxc parser used by other Oxc-based
29//! tools, so they match consistently across the ecosystem.
30
31mod instrument;
32mod pragma;
33mod transform;
34mod types;
35
36pub use instrument::{InstrumentError, InstrumentOptions, InstrumentResult, instrument};
37pub use types::{BranchEntry, FileCoverage, FnEntry, Location, Position, UnhandledPragma};
38
39/// Parse a `coverage-final.json` string into a map of file paths to coverage data.
40///
41/// This is the inverse of instrumentation — it reads existing coverage data
42/// produced by any Istanbul-compatible tool (Jest, Vitest, c8, nyc, etc.).
43///
44/// # Example
45///
46/// ```
47/// use oxc_coverage_instrument::parse_coverage_map;
48///
49/// let json = r#"{"file.js": {"path": "file.js", "statementMap": {}, "fnMap": {}, "branchMap": {}, "s": {}, "f": {}, "b": {}}}"#;
50/// let map = parse_coverage_map(json).unwrap();
51/// assert!(map.contains_key("file.js"));
52/// ```
53pub fn parse_coverage_map(
54    json: &str,
55) -> Result<std::collections::BTreeMap<String, FileCoverage>, serde_json::Error> {
56    serde_json::from_str(json)
57}