oxc-project
oxc
BlogDocsChangelog

feat(formatter): support printing comments

#11716Merged
Comparing
06-15-feat_formatter_support_printing_comments
(
d4817b9
) with
main
(
70749bb
)
CodSpeed Performance Gauge
-4%
Regressions
4
Untouched
34

Benchmarks

Failed

formatter[RadixUIAdoptionSection.jsx]
tasks/benchmark/benches/formatter.rs::formatter::bench_formatter
Regression
CodSpeed Performance Gauge
-4%
330.3 µs343.1 µs
formatter[react.development.js]
tasks/benchmark/benches/formatter.rs::formatter::bench_formatter
Regression
CodSpeed Performance Gauge
-3%
10.1 ms10.4 ms
formatter[cal.com.tsx]
tasks/benchmark/benches/formatter.rs::formatter::bench_formatter
Regression
CodSpeed Performance Gauge
-3%
161.1 ms166.8 ms
formatter[binder.ts]
tasks/benchmark/benches/formatter.rs::formatter::bench_formatter
Regression
CodSpeed Performance Gauge
-4%
20.6 ms21.5 ms

Passed

mangler[RadixUIAdoptionSection.jsx]
tasks/benchmark/benches/minifier.rs::minifier::bench_mangler
CodSpeed Performance Gauge
0%
14.3 µs14.2 µs
mangler[cal.com.tsx]
tasks/benchmark/benches/minifier.rs::minifier::bench_mangler
CodSpeed Performance Gauge
0%
3.1 ms3.1 ms
transformer[RadixUIAdoptionSection.jsx]
tasks/benchmark/benches/transformer.rs::transformer::bench_transformer
CodSpeed Performance Gauge
0%
128.8 µs128.5 µs
minifier[RadixUIAdoptionSection.jsx]
tasks/benchmark/benches/minifier.rs::minifier::bench_minifier
CodSpeed Performance Gauge
0%
66.3 µs66.2 µs
lexer[RadixUIAdoptionSection.jsx]
tasks/benchmark/benches/lexer.rs::lexer::bench_lexer
CodSpeed Performance Gauge
0%
21 µs20.9 µs
transformer[react.development.js]
tasks/benchmark/benches/transformer.rs::transformer::bench_transformer
CodSpeed Performance Gauge
0%
614.4 µs613.8 µs
minifier[cal.com.tsx]
tasks/benchmark/benches/minifier.rs::minifier::bench_minifier
CodSpeed Performance Gauge
0%
23 ms23 ms
codegen[react.development.js]
tasks/benchmark/benches/codegen.rs::codegen::bench_codegen
CodSpeed Performance Gauge
0%
2.2 ms2.2 ms
minifier[binder.ts]
tasks/benchmark/benches/minifier.rs::minifier::bench_minifier
CodSpeed Performance Gauge
0%
3.4 ms3.4 ms
codegen[binder.ts]
tasks/benchmark/benches/codegen.rs::codegen::bench_codegen
CodSpeed Performance Gauge
0%
4.8 ms4.8 ms
mangler[binder.ts]
tasks/benchmark/benches/minifier.rs::minifier::bench_mangler
CodSpeed Performance Gauge
0%
809.9 µs809.8 µs
lexer[binder.ts]
tasks/benchmark/benches/lexer.rs::lexer::bench_lexer
CodSpeed Performance Gauge
0%
930.1 µs929.9 µs
linter[cal.com.tsx]
tasks/benchmark/benches/linter.rs::linter::bench_linter
CodSpeed Performance Gauge
0%
1.2 s1.2 s
minifier[react.development.js]
tasks/benchmark/benches/minifier.rs::minifier::bench_minifier
CodSpeed Performance Gauge
0%
1.8 ms1.8 ms
lexer[cal.com.tsx]
tasks/benchmark/benches/lexer.rs::lexer::bench_lexer
CodSpeed Performance Gauge
0%
5.8 ms5.8 ms
codegen[RadixUIAdoptionSection.jsx]
tasks/benchmark/benches/codegen.rs::codegen::bench_codegen
CodSpeed Performance Gauge
0%
132.3 µs132.3 µs
linter[binder.ts]
tasks/benchmark/benches/linter.rs::linter::bench_linter
CodSpeed Performance Gauge
0%
149.9 ms149.9 ms
estree[checker.ts]
tasks/benchmark/benches/parser.rs::parser::bench_estree
CodSpeed Performance Gauge
0%
101.9 ms101.9 ms
parser[binder.ts]
tasks/benchmark/benches/parser.rs::parser::bench_parser
CodSpeed Performance Gauge
0%
3.4 ms3.4 ms
linter[react.development.js]
tasks/benchmark/benches/linter.rs::linter::bench_linter
CodSpeed Performance Gauge
0%
54.9 ms54.9 ms
semantic[cal.com.tsx]
tasks/benchmark/benches/semantic.rs::semantic::bench_semantic
CodSpeed Performance Gauge
0%
29.7 ms29.7 ms
parser[cal.com.tsx]
tasks/benchmark/benches/parser.rs::parser::bench_parser
CodSpeed Performance Gauge
0%
27.2 ms27.2 ms
lexer[react.development.js]
tasks/benchmark/benches/lexer.rs::lexer::bench_lexer
CodSpeed Performance Gauge
0%
383.9 µs384 µs
linter[RadixUIAdoptionSection.jsx]
tasks/benchmark/benches/linter.rs::linter::bench_linter
CodSpeed Performance Gauge
0%
2.6 ms2.6 ms
semantic[react.development.js]
tasks/benchmark/benches/semantic.rs::semantic::bench_semantic
CodSpeed Performance Gauge
0%
1.8 ms1.8 ms
parser[react.development.js]
tasks/benchmark/benches/parser.rs::parser::bench_parser
CodSpeed Performance Gauge
0%
1.4 ms1.4 ms
semantic[binder.ts]
tasks/benchmark/benches/semantic.rs::semantic::bench_semantic
CodSpeed Performance Gauge
0%
4.5 ms4.6 ms
isolated-declarations[vue-id.ts]
tasks/benchmark/benches/transformer.rs::transformer::bench_isolated_declarations
CodSpeed Performance Gauge
0%
57.5 ms57.5 ms
parser[RadixUIAdoptionSection.jsx]
tasks/benchmark/benches/parser.rs::parser::bench_parser
CodSpeed Performance Gauge
0%
84.6 µs84.7 µs
semantic[RadixUIAdoptionSection.jsx]
tasks/benchmark/benches/semantic.rs::semantic::bench_semantic
CodSpeed Performance Gauge
0%
82.4 µs82.5 µs
transformer[binder.ts]
tasks/benchmark/benches/transformer.rs::transformer::bench_transformer
CodSpeed Performance Gauge
0%
1.4 ms1.4 ms
mangler[react.development.js]
tasks/benchmark/benches/minifier.rs::minifier::bench_mangler
CodSpeed Performance Gauge
0%
283.5 µs284.3 µs
codegen[cal.com.tsx]
tasks/benchmark/benches/codegen.rs::codegen::bench_codegen
CodSpeed Performance Gauge
0%
38.8 ms38.9 ms
transformer[cal.com.tsx]
tasks/benchmark/benches/transformer.rs::transformer::bench_transformer
CodSpeed Performance Gauge
-1%
24.3 ms24.6 ms

Commits

Click on a commit to change the comparison range
Base
main
70749bb
-3.95%
feat(formatter): support printing comments (#11716) This PR implements support for printing leading, trailing, and dangling comments based on an approach inspired by [Prettier's algorithm](https://github.com/prettier/prettier/blob/7584432401a47a26943dd7a9ca9e8032ead7285/src/main/comments/attach.js#L135). ## Summary of Changes ### 1. Introduction of `following_node` field in `AstNode` We've added a `following_node` field of type `SiblingNode` to `AstNode`. This enum includes all AST structs and stores the next node of the current node. This addition is crucial for determining whether a comment is leading or trailing. (Note: This could potentially be replaced by `AstKind` after resolving [#11490](https://github.com/oxc-project/oxc/issues/11490)) ### 2. Custom `Comments` Implementation We've replaced Biome's `Comments` with our own implementation: ```rs #[derive(Debug, Clone)] pub struct Comments<'a> { source_text: &'a str, comments: &'a Vec<'a, Comment>, printed_count: usize, } ``` This implementation avoids heap allocations, shifting the overhead to comment checking operations. ## Design Approach Our approach is based on Prettier's algorithm but with a key difference: instead of preprocessing comments, we handle comment printing directly during the formatting process. ### Design Rationale Several constraints informed this design decision: 1. The AST is immutable, preventing direct attachment of comments to nodes 2. `AstNode` instances are generated during formatting, making pre-generation with comments impractical 3. Without unique node identifiers ([AstNodeId #4188](https://github.com/oxc-project/oxc/issues/4188)), mapping comments to nodes for later retrieval is not feasible ### Implementation Details We've generated a file implementing the `Format` trait for nearly all AstNodes. In each implementation: - Leading comments are formatted before the node itself - Trailing comments are formatted after the node - Dangling comments are printed for empty block-like nodes or `CallExpression` nodes with no arguments The `printed_count` field in `Comments` tracks how many comments have been printed, preventing duplicate processing, which would significantly impact performance. #### Comment Classification Logic 1. **Leading Comments**: All comments preceding the current node are treated as leading comments. 2. **Trailing Comments**: Comments between the current node and the next node require careful handling. We determine if they belong to the current node; otherwise, they're left as leading comments for the subsequent node. 3. **Dangling Comments**: These are simply comments inside empty block-like nodes. ## Advantages and Disadvantages ### Advantages 1. Eliminates the need for an additional AST traversal to attach comments, saving time and resources 2. Direct printing of processed comments avoids heap allocations and memory overhead ### Disadvantages 1. Comment checking becomes more complex, requiring iteration through unprinted comments, which may have performance implications (though this is uncommon) 2. The approach may present a steeper learning curve for new contributors, which we'll address through documentation and user-friendly APIs ## Performance Impact The implementation introduces approximately 4% performance regression, which is significantly better than the estimated 10%+ regression that would result from implementing a separate AST traversal for comment attachment. <img width="709" alt="image" src="https://github.com/user-attachments/assets/3a8c3e30-c114-4a38-9779-168a2ead2942" /> ## Test Improvements | Language | Before | After | Improvement | |-------------|----------------|----------------|-------------| | JavaScript | 295/699 (42.20%) | 324/699 (46.35%) | +4.15% | | TypeScript | 186/573 (32.46%) | 200/573 (34.90%) | +2.44% | Currently, we're focusing on JavaScript support, with TypeScript improvements planned for future work. ## Future Work 1. Port special printing cases from [Prettier's comment handling](https://github.com/prettier/prettier/blob/7584432401a47a26943dd7a9ca9a8e032ead7285/src/language-js/comments/handle-comments.js) 2. Develop APIs to facilitate comment checking during the formatting process
d4817b9
6 months ago
by Dunqing
© 2025 CodSpeed Technology
Home Terms Privacy Docs