Avatar for the oxc-project user
oxc-project
oxc
BlogDocsChangelog

Performance History

Latest Results

WIP 2
alubbe:asd
6 minutes ago
update
babu-ch:fix/ts-constructor-type-arrow-parens
26 minutes ago
feat(formatter): add JSDoc comment formatting support (#19828) ## Summary Implements native JSDoc comment formatting in oxfmt, porting behavior from [prettier-plugin-jsdoc](https://github.com/hosseinmd/prettier-plugin-jsdoc) (v1.8.0). Tracked in #19702. ### Conformance **145/145 (100%)** compatibility with prettier-plugin-jsdoc test suite. - 1 fixture intentionally skipped (`descriptions/032-jsx-tsx-css`) — requires embedded CSS/HTML formatter callbacks not available in the standalone conformance runner - Run with: `cargo run -p oxc_prettier_conformance -- --jsdoc` Prettier conformance (non-JSDoc): - **JS**: 746/753 (99.07%) - **TS**: 591/601 (98.34%) ### Real-World Repository Testing Validated against 5 real-world repositories (7,542 JSDoc tags total) using Prettier 3.8.1 + prettier-plugin-jsdoc 1.8.0 as baseline: | Repository | JSDoc Tags | Files with Diffs | |------------|-----------|-----------------| | evolu | 134 | 13 | | wxt | 1,183 | 1 | | typedoc | 792 | 11 | | Chart.js | 1,276 | 4 | | svelte | 4,157 | 5 | | **Total** | **7,542** | **34** | All 34 remaining diffs are **intentional design differences**, not bugs: - `{@link}` kept atomic (upstream breaks across lines) — ~11 files - `{@includeCode}` placed on own line (upstream splits tag syntax) — 3 files - Sub-list continuation indent normalized to 4-space — 5 files - `?Type` expanded to `Type | null` — 1 file - Minor line-break position differences — 5 files - Double-space normalized to single space — 1 file 10 upstream bugs documented in `tasks/prettier_conformance/jsdoc/upstream-jsdoc-bugs.md` — oxfmt intentionally produces correct output where the upstream plugin has known issues. ### Performance Measured with `hyperfine` using `oxfmt --check` on real-world repos (16 threads): | Repository | Without JSDoc | With JSDoc | Overhead | |------------|--------------|------------|-------------| | evolu | 434ms | 427ms | ~0% (noise) | | wxt | 410ms | 410ms | ~0% (noise) | | typedoc | 532ms | 567ms | ~7% | | Chart.js | 497ms | 479ms | ~0% (noise) | | svelte | 510ms | 549ms | ~8% | typedoc and svelte (highest JSDoc density) show measurable ~7-8% wall-clock overhead. The rest are within noise. CPU time overhead is ~1-2% as JSDoc work parallelizes across threads. ### Architecture The formatting pipeline processes each JSDoc comment through these stages: 1. **Parse** — Extract JSDoc structure via `oxc_jsdoc` (description, tags with type/name/comment) 2. **Normalize** — Canonicalize tag aliases (`@return` → `@returns`), normalize types (`Array.<T>` → `T[]`, `?Type` → `Type | null`), normalize markdown emphasis (`__bold__` → `**bold**`, `*italic*` → `_italic_`) 3. **Sort & Group** — Sort tags by upstream priority weights within `@typedef`/`@callback` groups; reorder `@param` tags to match function signature 4. **Format** — Route each tag to its specific formatter (type+name+comment, type+comment, generic, example); format descriptions via markdown AST with word wrapping; format embedded code blocks 5. **Serialize** — Assemble final comment with `/** ... */` wrapper, `* ` prefixes, and single-line optimization **Key modules:** - `serialize.rs` — Main pipeline orchestrator (`JsdocFormatter` struct) - `tag_formatters.rs` — Tag-specific formatters (type+name+comment, type+comment, generic, example) - `normalize.rs` — Type/emphasis/capitalization normalization - `mdast_serialize.rs` — Markdown AST → formatted text serialization with `tag_string_length` offset - `wrap.rs` — Word wrapping with `first_line_offset`, atomic JSDoc link tokens, table formatting - `embedded.rs` — Embedded JS/TS/JSX/TSX code formatting in @example blocks - `imports.rs` — `@import` tag parsing, merging, and sorting - `param_order.rs` — `@param` tag reordering to match function signature - `line_buffer.rs` — Single-allocation line accumulator ### Options Support All 11 options from prettier-plugin-jsdoc are implemented: | Option | Default | Status | |--------|---------|--------| | `capitalizeDescriptions` | `true` | āœ… | | `commentLineStrategy` | `"singleLine"` | āœ… | | `separateTagGroups` | `false` | āœ… | | `separateReturnsFromParam` | `false` | āœ… | | `bracketSpacing` | `false` | āœ… | | `descriptionWithDot` | `false` | āœ… | | `addDefaultToDescription` | `true` | āœ… | | `preferCodeFences` | `false` | āœ… | | `lineWrappingStyle` | `"greedy"` | āœ… (greedy + balance) | | `descriptionTag` | `false` | āœ… | | `keepUnparsableExampleIndent` | `false` | āœ… | **Not yet ported** (no conformance fixtures): `jsdocVerticalAlignment`, `tsdoc` mode — can be added when needed. ### Features - **Description formatting**: Capitalize first letter, normalize markdown emphasis, wrap text to print width - **Markdown AST processing**: Parse descriptions via mdast for heading normalization, list formatting, reference links, code blocks, blockquotes, tables - **Tag description wrapping**: Matches upstream's `tagStringLength` architecture — full description passes through markdown AST with first-line offset - **Tag normalization**: 17 tag synonyms, sort by upstream priority weights within groups - **Type formatting**: Normalize JSDoc types, format via the formatter's TS parser (simulating upstream's `formatType()`), handle rest params, bracket spacing - **@example formatting**: Format embedded JS/TS/JSX/TSX code; fenced code blocks with language detection - **@import handling**: Parse, merge by module path, sort (third-party before relative), format consolidated imports - **@param reordering**: Reorder tags to match function signature parameter order - **Default value handling**: Extract `[name=value]` defaults with "Default is \`value\`" suffix ### Upstream Fidelity Verified against [prettier-plugin-jsdoc](https://github.com/hosseinmd/prettier-plugin-jsdoc) v1.8.0 source: - **Identical**: Tag synonyms (17), sort priorities (46 tags), grouping logic (`TAGS_GROUP_HEAD`, `TAGS_GROUP_CONDITION`), type normalization pipeline, rest param handling, JSDoc link protection, emphasis normalization, capitalization rules - **Architecture aligned**: Tag description wrapping uses `tag_string_length` / `first_line_offset` (equivalent to upstream's `!...?` prefix trick), balance mode effective width calculation, greedy fallback - **10 upstream bugs documented** — oxfmt intentionally produces correct output where the plugin has known issues (HTML comment wrapping, `{@link}` off-by-one, `{@includeCode}` splitting, `@type` capitalization inconsistency, etc.) ### Optimization Techniques - Single `LineBuffer` allocation per comment (one contiguous `String`, not `Vec<String>`) - `Cow<'_, str>` throughout normalization — borrows when unchanged, allocates only when modified - Fast-path skip of mdast parsing for plain-text descriptions (`needs_mdast_parsing()` heuristic) - Fast-path skip of TS formatter for simple types (`needs_formatter_pass()` check) - `SmallVec<[usize; 4]>` for import tag indices (stack allocation for common case) ## Test plan - [x] `cargo test -p oxc_formatter` — 335 tests pass (76 unit + 259 fixture) - [x] `cargo run -p oxc_prettier_conformance -- --jsdoc` — 145/145 (100%) - [x] Prettier conformance: JS 746/753 (99.07%), TS 591/601 (98.34%) - [x] Real-world repos: 34 diffs across 5 repos (7,542 JSDoc tags) — all design differences - [x] Performance: 0-8% overhead across 5 real-world repos (typedoc ~7%, svelte ~8%, rest within noise) - [x] `cargo clippy -p oxc_formatter --all-targets` — clean - [x] `cargo fmt -- --check` — clean šŸ¤– Generated with [Claude Code](https://claude.com/claude-code)
main
33 minutes ago
feat(oxfmt): Support html-in-js substitution (#20193) Part of #15180 The basic flow is the same as css-in-js: replace `${expr}` with placeholder strings, let Prettier format the HTML, then substitute back with formatted `expr`s. However, there are a few key differences: ### `options.htmlWhitespaceSensitivity` This HTML-specific option also affects html-in-js (template wrapping strategy, hug detection), so it needed to be held in `oxc_formatter::FormatOptions`. ### `prettier.__internal.formatOptionsHiddenDefaults` Prettier adds hidden fields to the `options` object during its internal print phase for embedded formatters. However, `__debug.printToDoc()` runs `normalizeFormatOptions()` which strips unknown keys. Unlike internal `textToDoc()` (which uses `passThrough: true`), `printToDoc()` does not preserve them. To work around this, we pre-register keys in `formatOptionsHiddenDefaults` so they survive normalization. ### NOTE: Not fully supported cases #### js-in-html-in-js Currently, the process of converting Docs to our IR does not support `conditionalGroup`. Since Prettier only uses this for YAML and JS formatting. YAML is never embedded, and we would like to use `oxc_formatter` for JS. However, applying `oxc_formatter` to the **js**-in-html-in-js case was not straightforward. Therefore, I have implemented a fallback to a simpler formatting process for that case for now. #### `label({ embed, hug })` equivalent With current implementation, `is_huggable_html_embed_single_arg()` always hugs via early-return, ignoring line width. Prettier uses `label({ embed, hug })` + `conditionalGroup` to try hugged first and fall back to expanded. We have the equivalent `BestFitting` 3-variant flow in `write_grouped_arguments`, but `ExpandParent` from HTML template's `hardline` propagates through `will_break` / `propagate_expands` / fit check, forcing the expanded variant to always be chosen. To fix, we need to add new IR for boundary (prevents `ExpandParent` propagation in `will_break` / `propagate_expands` / fit check), then add HTML embeds to `can_group_expression_argument` so they enter the existing `BestFitting` 3-variant flow. However, I'm not sure this is worth to add. So just leave it for now.
main
48 minutes ago

Latest Branches

CodSpeed Performance Gauge
0%
fix(oxfmt): Align more trailing comment cases with prettier (#20636)#20643
22 hours ago
b06d58b
alubbe:asd
CodSpeed Performance Gauge
0%
fix(formatter): remove unnecessary parens around TSConstructorType in arrow function return type#20573
28 minutes ago
fe805e7
babu-ch:fix/ts-constructor-type-arrow-parens
CodSpeed Performance Gauge
-3%
1 hour ago
a7d639f
feat/jsdoc-comment-formatting
Ā© 2026 CodSpeed Technology
Home Terms Privacy Docs